OpenClaw
Point OpenClaw at the gateway. Config alone is enough, so it works in a hardened container with nothing installed into it.
The route below is the common sandboxed case: OpenClaw in a locked-down container, inference on xAI Grok via Oracle Cloud Infrastructure Generative AI. Oracle credentials stay server-side on the gateway, and the container holds only its own client key. You need a running gateway the container can reach, and console admin access.
Other model menus (Claude, GPT, direct xAI, aliases, mixed fleets), the Connect and plugin install paths, and troubleshooting live in the OpenClaw reference.
Console Providers, or PUT /admin/provider-keys
(field list). oracleRegion is required and has
no default. Production uses IAM request signing, so there is no API key.
Console Routing: single for Grok-only, or
dispatch by requested model for a multi-vendor menu.
Console Users → Agents → Add agent mints an ark_svc_… key attributed to the agent
name (client keys). Set it as ANYRAY_CLIENT_KEY on the container.
OpenClaw substitutes ${ANYRAY_CLIENT_KEY} at load, so no credential touches disk.
Write this to ~/.openclaw/openclaw.json, or wherever OPENCLAW_CONFIG_PATH points. Read-only
works.
{
models: {
providers: {
anyray: {
// Bare origin, no `/v1`: the anthropic-messages transport appends
// `/v1/messages` itself.
baseUrl: 'https://gateway.example.anyray.ai',
// Without the explicit api kind OpenClaw serves the entry over
// openai-completions: wrong dialect, wrong path.
api: 'anthropic-messages',
apiKey: '${ANYRAY_CLIENT_KEY}',
headers: {
'x-anyray-api-key': '${ANYRAY_CLIENT_KEY}',
// OpenClaw drops its implicit beta headers on a custom host.
'anthropic-beta': 'interleaved-thinking-2025-05-14',
// Labels this traffic as OpenClaw. User and team come from the key,
// not from here.
'x-anyray-metadata': '{"tool":"openclaw"}',
},
// A provider OpenClaw does not ship must list its own models. OCI keeps
// its dotted vendor prefix on the wire, so the id is `xai.grok-4.3`,
// not `grok-4.3`.
models: [
{
id: 'xai.grok-4.3',
name: 'Grok 4.3 (Anyray)',
reasoning: true,
input: ['text'],
contextWindow: 1000000,
maxTokens: 128000,
},
],
},
},
},
mcp: {
servers: {
// Lets the model read back anything the optimizer replaced with a
// marker. Without it, trims are irreversible. Same key as above.
anyray: {
url: 'https://gateway.example.anyray.ai/mcp',
transport: 'streamable-http',
headers: { 'x-anyray-api-key': '${ANYRAY_CLIENT_KEY}' },
},
},
},
agents: {
// Routing stays inert until the primary model resolves to a routed
// provider.
defaults: { model: { primary: 'anyray/xai.grok-4.3' } },
},
}
Two paths on the gateway origin: /v1/messages for routing and /mcp for retrieval. OpenClaw
also reaches other hosts, such as the model-catalog refresh at boot and chat channels. Allowlist
by what OpenClaw needs, not this route alone.
openclaw config validate
openclaw mcp probe anyray --json
The first names any unresolved environment variable, so a missing key surfaces as a warning
rather than a runtime 401. The second makes a fresh connection to the configured server and
should show two tools (anyray_retrieve, anyray_recall). A configured server with zero tools
is not ready: run openclaw mcp reload and check again. The fresh probe proves the server is
healthy; only an agent turn or Anyray's content-free no_discovery telemetry reveals a stale
catalog OpenClaw is holding from before. A gateway restart no longer strands that catalog. The
next handshake re-mints its session, so retrieval returns on the following turn on its own.
Then check the console's Agents card. Active means both halves are up. Active · retrieval not seen means the agent routes but cannot read content back, so most optimization stays held back for it.
Getting api and baseUrl right
These two fields decide whether the route works at all. They come as a pair:
api | baseUrl shape | OpenClaw appends | Use it for |
|---|---|---|---|
anthropic-messages | Bare origin, no /v1 | /v1/messages | Anything the gateway serves or translates to Claude's wire. Prefer it: it carries cache_control and thinking blocks |
openai-completions | Ends in /v1 | /chat/completions | GPT, which has no /v1/messages |
Omit api and OpenClaw serves the entry over openai-completions against a bare origin: wrong
dialect, and a path the gateway answers with a 404.
Why the mcp block is not optional
It is what makes optimization safe to run. When the optimizer replaces bulky content with an
[anyray: … retrieve ctx_…] marker, the model reads the original back through that server. Drop the
block and retrieval-dependent optimization is held back, while what still runs trims irreversibly.
How the loop works in general: retrieval reference. Machines running
anyray-connect get a local
mcp.servers.anyray written for them, so they need no block here.
Adding more vendors
Claude and Grok can share the one anthropic-messages entry above. The gateway serves
/v1/messages natively for anthropic and translates for oracle, x-ai, nebius,
tensormesh, litellm, and truefoundry. openai has no /v1/messages, so GPT gets its own
openai-completions entry. Ready-made configs for each shape:
Config variants.
A multi-vendor menu does not route itself. The gateway never infers a provider from a model
id, so an entry spanning vendors with no x-anyray-provider pinned needs a conditional routing
config keyed on params.model (routing examples).
single mode sends every model to that one provider, giving an upstream 404 for the rest, and
several stored provider keys with no routing config fail every request with Either x-anyray-config or x-anyray-provider header is required.
Handling the key
Mint one agent key (ark_svc_…) per deployment, never share one, and put it straight into
the container's secret store. The key sets the attributed user and team, while
x-anyray-metadata carries tool only.
Rotation is a new key plus a restart, because openclaw.json references ${ANYRAY_CLIENT_KEY},
not the value.
You already pointed a provider at your own upstream
A provider entry you pinned at your own upstream by hand keeps its routing headers
(x-anyray-auth-mode, x-anyray-custom-host, x-anyray-provider), its Authorization, and its
key. anyray-connect recognizes headers it did not write, adds only the attribution header, and
names the lanes it left alone in its output.
To hand those lanes to Connect instead, run it with --upstream <url> --upstream-key <key>: it
then writes the passthrough pins itself, on the Anthropic and the OpenAI lane both.