Skip to main content

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.

1
Store the Oracle credential on the gateway

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.

2
Point routing at your providers

Console Routing: single for Grok-only, or dispatch by requested model for a multi-vendor menu.

3
Mint an agent key

Console UsersAgentsAdd 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.

4
Mount the config

Write this to ~/.openclaw/openclaw.json, or wherever OPENCLAW_CONFIG_PATH points. Read-only works.

Grok on Oracle OCI
{
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' } },
},
}
5
Allow the gateway through egress

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.

6
Validate, then run one turn
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:

apibaseUrl shapeOpenClaw appendsUse it for
anthropic-messagesBare origin, no /v1/v1/messagesAnything the gateway serves or translates to Claude's wire. Prefer it: it carries cache_control and thinking blocks
openai-completionsEnds in /v1/chat/completionsGPT, 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.