This guide covers configuring Claw instances: LLM providers (built-in and custom/self-hosted), external services, messaging channels, MCP servers, web search, web fetch, application configuration, workspace files, skills, and custom domains. Each section walks through creating the necessary Secrets and Claw CR configuration.
All examples assume you have set your target namespace:
export NS=my-claw-namespaceFor known providers (google, anthropic, openai, xai, openrouter), the operator automatically infers type, domain, and auth headers — you only need name, provider, and secretRef. You can still override any inferred field if needed (e.g., routing through a custom proxy or using a different credential type).
The provider field also accepts arbitrary strings for custom/self-hosted providers — see Custom / Self-Hosted Providers below. For the best experience with custom endpoints, use spec.customProviders which provides full control over baseUrl, wire format, and model registration.
Adding credentials incrementally: Each
oc applyof the Claw CR replaces the entirecredentialslist. When adding a new provider, include all existing credentials in the YAML — otherwise they will be removed. You can retrieve your current configuration withoc get claw instance -n $NS -o yamland add the new entry to the list.
Uses the Gemini REST API directly with an API key.
1. Get an API key from Google AI Studio.
2. Create the Secret:
oc create secret generic gemini-api-key \
--from-literal=api-key=YOUR_GEMINI_API_KEY \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
provider: google
secretRef:
- name: gemini-api-key
key: api-key
EOFUses the Anthropic API directly with an API key.
1. Get an API key from the Anthropic Console.
2. Create the Secret:
oc create secret generic anthropic-api-key \
--from-literal=api-key=YOUR_ANTHROPIC_API_KEY \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: anthropic
provider: anthropic
secretRef:
- name: anthropic-api-key
key: api-key
EOFUses the OpenAI API with a bearer token.
1. Get an API key from the OpenAI Platform.
2. Create the Secret:
oc create secret generic openai-api-key \
--from-literal=api-key=YOUR_OPENAI_API_KEY \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: openai
provider: openai
secretRef:
- name: openai-api-key
key: api-key
EOFGPT-5.x models: OpenClaw routes newer GPT models (gpt-5.5, gpt-5.4, gpt-5.4-mini) through an internal provider called
openai-codex. The operator handles this automatically — when you configure anopenaicredential, a companionopenai-codexprovider entry is created with the same endpoint and credentials. No additional configuration is needed.
Uses the xAI API with a bearer token.
1. Get an API key from the xAI Console.
2. Create the Secret:
oc create secret generic xai-api-key \
--from-literal=api-key=YOUR_XAI_API_KEY \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: xai
provider: xai
secretRef:
- name: xai-api-key
key: api-key
EOFOpenRouter is a meta-provider that routes requests to many upstream model providers (OpenAI, Anthropic, Google, Meta, and others) through a single API key. The operator auto-infers type: bearer, domain: openrouter.ai, and a /api/v1 base path. The default model catalog includes popular models from multiple upstream providers.
1. Get an API key from openrouter.ai/keys.
2. Create the Secret:
oc create secret generic openrouter-api-key \
--from-literal=api-key=YOUR_OPENROUTER_API_KEY \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: openrouter
provider: openrouter
secretRef:
- name: openrouter-api-key
key: api-key
EOFOpenRouter model names use the upstream-provider/model convention (e.g., openai/gpt-5.5, anthropic/claude-sonnet-4-6). In the model picker, these appear as openrouter/openai/gpt-5.5, etc. To add additional OpenRouter models beyond the default catalog, use spec.config.raw:
spec:
config:
mergeMode: overwrite
raw:
agents:
defaults:
models:
openrouter/qwen/qwen3-coder:free:
alias: Qwen3 Coder (free)Vertex AI lets you access multiple model providers (Anthropic, Google, Meta, and others) through a single GCP project using IAM-based authentication instead of per-provider API keys. The domain defaults to .googleapis.com for all gcp credentials.
- A GCP project with the Vertex AI API enabled
- A GCP service account with the
Vertex AI Userrole
These steps are shared across all Vertex AI providers below.
1. Create the service account and download the JSON key:
gcloud iam service-accounts create claw-vertex \
--display-name="Claw Vertex AI"
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:claw-vertex@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
gcloud iam service-accounts keys create sa-key.json \
--iam-account=claw-vertex@YOUR_PROJECT_ID.iam.gserviceaccount.com2. Create the Secret:
oc create secret generic vertex-sa-key \
--from-file=sa-key.json=sa-key.json \
-n $NSFor testing with your personal account: you can skip the service account setup and use Application Default Credentials instead:
gcloud auth application-default login oc create secret generic vertex-sa-key \ --from-file=sa-key.json=$HOME/.config/gcloud/application_default_credentials.json \ -n $NSThe Google Cloud libraries accept both
authorized_userandservice_accountcredential types.
Requires Anthropic Claude models enabled in your project's Model Garden and a region that supports them (e.g., us-east5, europe-west1 — check Anthropic's Vertex AI docs for the latest availability).
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: anthropic-vertex
type: gcp
secretRef:
- name: vertex-sa-key
key: sa-key.json
gcp:
project: "YOUR_PROJECT_ID"
location: "us-east5"
provider: anthropic
EOFUseful when you need IAM-based access control or when API keys aren't available.
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
type: gcp
secretRef:
- name: vertex-sa-key
key: sa-key.json
gcp:
project: "YOUR_PROJECT_ID"
location: "us-central1"
provider: google
EOFYou can use multiple providers in the same Claw instance with a single service account:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: anthropic-vertex
type: gcp
secretRef:
- name: vertex-sa-key
key: sa-key.json
gcp:
project: "YOUR_PROJECT_ID"
location: "us-east5"
provider: anthropic
- name: gemini
type: gcp
secretRef:
- name: vertex-sa-key
key: sa-key.json
gcp:
project: "YOUR_PROJECT_ID"
location: "us-central1"
provider: google
EOFThe operator uses two different routing strategies depending on the provider:
Google Gemini via Vertex AI (provider: google, type: gcp): Uses a gateway proxy route that forwards requests through https://{location}-aiplatform.googleapis.com/v1/projects/{project}/locations/{location}/publishers/google/....
Non-Google providers via Vertex AI (e.g., provider: anthropic, type: gcp): Uses OpenClaw's native Vertex SDK (e.g., @anthropic-ai/vertex-sdk). The operator:
- Configures OpenClaw with the
anthropic-vertexprovider, which uses the native Vertex AI SDK to construct correct API URLs - Provides the OpenClaw pod with a stub ADC (Application Default Credentials) — a dummy credentials file with no real secrets
- The MITM proxy transparently intercepts GCP auth traffic and injects real OAuth2 tokens from the service account
This ensures real GCP credentials stay on the proxy pod only — the application pod never sees them.
For self-hosted models (vLLM, Ollama, TGI, LiteLLM) or hosted providers not in the built-in catalog (Together AI, Fireworks, Groq, Cerebras, etc.), use spec.customProviders to declare the endpoint, wire format, and available models. The operator generates models.providers entries and registers models in the picker automatically.
Each custom provider references a credential in spec.credentials that handles proxy routing and authentication for the provider's domain. The credential does not need a provider field — customProviders handles model routing separately.
Adding credentials incrementally: Each
oc applyof the Claw CR replaces the entirecredentialsandcustomProviderslists. When adding a new provider, include all existing entries in the YAML. Retrieve your current configuration withoc get claw instance -n $NS -o yaml.
A typical self-hosted vLLM or OpenAI-compatible endpoint using bearer token auth.
1. Create the Secret:
oc create secret generic vllm-key \
--from-literal=api-key=YOUR_VLLM_API_KEY \
-n $NS2. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: my-vllm
type: bearer
domain: llm.mycompany.com
secretRef:
- name: vllm-key
key: api-key
customProviders:
- name: my-vllm
baseUrl: "https://llm.mycompany.com/v1"
credentialRef: my-vllm
models:
- name: qwen3-14b
alias: Qwen 3 14B
- name: llama-4-scout
alias: Llama 4 Scout
EOFThe operator generates:
- A proxy route for
llm.mycompany.comwith bearer token injection - A
models.providers.my-vllmentry withbaseUrl: "https://llm.mycompany.com/v1" - Model picker entries:
my-vllm/qwen3-14bandmy-vllm/llama-4-scout
Self-hosted Ollama using the native Ollama wire format. Since Ollama typically runs without authentication, use type: none to allowlist the domain without credential injection.
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: local-ollama
type: none
domain: ollama.internal.corp
customProviders:
- name: ollama
baseUrl: "http://ollama.internal.corp:11434"
api: ollama
credentialRef: local-ollama
models:
- name: llama3.3
alias: Llama 3.3 70B
- name: qwen3-8b
alias: Qwen 3 8B
EOFThe api field selects the wire format / request adapter OpenClaw uses when talking to the provider. If omitted, it defaults to openai-completions.
| Value | Protocol | Use for |
|---|---|---|
openai-completions (default) |
/v1/chat/completions |
vLLM, LiteLLM, Together AI, Fireworks, Groq, most OpenAI-compatible APIs |
openai-responses |
OpenAI Responses API | Endpoints implementing the newer OpenAI Responses format |
anthropic-messages |
Anthropic Messages API | Self-hosted or proxied Anthropic-compatible APIs |
ollama |
Ollama native API | Ollama servers |
| Field | Required | Description |
|---|---|---|
name |
Yes | Provider key and model prefix. Must match ^[a-z][a-z0-9-]*$. Models appear as {name}/{model} in the picker. |
baseUrl |
Yes | Full API endpoint URL including path prefix (e.g., https://llm.mycompany.com/v1). |
credentialRef |
Yes | Name of a credential in spec.credentials that handles proxy routing for this provider's domain. |
models |
Yes | List of models (at least one). Each has a name (API model ID) and optional alias (display name). |
api |
No | Wire format adapter. Default: openai-completions. See table above. |
Custom providers work alongside built-in providers in the same Claw instance:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: anthropic
type: apiKey
secretRef:
- name: anthropic-api-key
key: api-key
provider: anthropic
- name: my-vllm
type: bearer
domain: llm.mycompany.com
secretRef:
- name: vllm-key
key: api-key
customProviders:
- name: my-vllm
baseUrl: "https://llm.mycompany.com/v1"
credentialRef: my-vllm
models:
- name: qwen3-14b
alias: Qwen 3 14B
EOFThe model picker shows both built-in Anthropic models (anthropic/claude-sonnet-4-6, etc.) and the custom model (my-vllm/qwen3-14b).
For power users, setting provider to an arbitrary string on a credential also works without spec.customProviders. The operator auto-generates a models.providers entry with baseUrl: "https://<domain>". However, the operator has no built-in catalog for unknown providers, so models must be added manually via spec.config.raw:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: groq
type: bearer
provider: groq
domain: api.groq.com
secretRef:
- name: groq-key
key: api-key
config:
raw:
agents:
defaults:
model:
primary: groq/llama-4-scout-17b-16e-instruct
models:
groq/llama-4-scout-17b-16e-instruct:
alias: Llama 4 Scout
EOFThis approach is simpler for quick oc apply workflows but has limitations: baseUrl is always https://<domain> (no custom path), and models must be specified separately in spec.config.raw. For full control, prefer spec.customProviders.
The controller rejects the CR (condition = Ready=False) if:
customProviders[].nameis not unique across all custom providerscustomProviders[].namecollides with anycredentials[].providervaluecustomProviders[].credentialRefdoes not match a credential name inspec.credentialscustomProviders[].modelsis empty
The kubernetes credential type lets the AI assistant interact with Kubernetes API servers through the credential-injecting proxy. You provide a standard kubeconfig file in a Secret — the operator parses it to extract server URLs, contexts, namespaces, and tokens. The assistant gets a sanitized kubeconfig (real tokens replaced with placeholders) and all API requests are transparently authenticated by the proxy.
Requirements:
- The kubeconfig must use token-based authentication (static tokens or projected service account tokens). Client certificate, exec-based, and auth provider-based auth are not supported yet.
- Each cluster server URL must map to exactly one token. If the same cluster is referenced by multiple contexts with different users/tokens, split into separate kubeconfigs.
1. Create a ServiceAccount with RBAC:
oc create namespace my-workspace
oc create sa claw-assistant -n my-workspace
oc create rolebinding claw-assistant-edit \
--clusterrole=edit \
--serviceaccount=my-workspace:claw-assistant \
-n my-workspace2. Build a kubeconfig from your current cluster:
This extracts the server URL and CA from your existing kubeconfig, then creates a new one with the SA token — no need to find CA files manually.
# Get the API server URL and CA data from the current context
SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
CA_DATA=$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
# Request a token for the ServiceAccount
SA_TOKEN=$(oc create token claw-assistant -n my-workspace --duration=8760h)
# Build the kubeconfig
kubectl config set-cluster target \
--server="$SERVER" \
--kubeconfig=/tmp/kubeconfig
kubectl config set clusters.target.certificate-authority-data "$CA_DATA" \
--kubeconfig=/tmp/kubeconfig
kubectl config set-credentials claw-sa \
--token="$SA_TOKEN" \
--kubeconfig=/tmp/kubeconfig
kubectl config set-context workspace \
--cluster=target \
--user=claw-sa \
--namespace=my-workspace \
--kubeconfig=/tmp/kubeconfig
kubectl config use-context workspace --kubeconfig=/tmp/kubeconfigTip: If your cluster uses a CA file instead of inline
certificate-authority-data, you can embed it:CA_FILE=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.certificate-authority}') kubectl config set-cluster target \ --server="$SERVER" \ --certificate-authority="$CA_FILE" \ --embed-certs=true \ --kubeconfig=/tmp/kubeconfig
3. Create the Secret:
oc create secret generic my-kubeconfig \
--from-file=kubeconfig=/tmp/kubeconfig \
-n $NS4. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: k8s-workspace
type: kubernetes
secretRef:
- name: my-kubeconfig
key: kubeconfig
EOFA single kubeconfig can contain multiple clusters. The operator creates a proxy route per cluster server and the assistant can switch contexts with kubectl config use-context.
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: k8s-multi
type: kubernetes
secretRef:
- name: multi-cluster-kubeconfig
key: kubeconfig
EOFThe operator automatically:
- Creates proxy routes for each cluster server
hostname:port - Patches the proxy egress NetworkPolicy to allow non-443 ports (e.g., 6443)
- Mounts a sanitized kubeconfig on the gateway pod (tokens replaced with placeholders)
- Injects a "Kubernetes Access" section into AGENTS.md listing available contexts and namespaces
Kubernetes credentials work alongside LLM provider credentials in the same Claw instance:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
provider: google
- name: k8s-workspace
type: kubernetes
secretRef:
- name: my-kubeconfig
key: kubeconfig
EOFThe kubernetes credential uses the proxy's existing MITM forward proxy mode (CONNECT tunneling). The gateway pod's HTTP_PROXY / HTTPS_PROXY env vars route all traffic through the proxy, which:
- Matches the request
hostname:portagainst cluster servers from the kubeconfig - TLS-terminates via MITM
- Strips all existing auth headers
- Injects the real
Authorization: Bearer <token>for the matched cluster - Re-encrypts and forwards to the upstream API server
The gateway pod cannot reach any API server directly — egress is restricted to the proxy by NetworkPolicy. The assistant never sees real tokens; only the sanitized kubeconfig with placeholder values.
For known channels (telegram, discord, slack, whatsapp), the operator automatically infers all proxy configuration — domain, credential type, companion routes, and placeholder tokens. You only need name, channel, and secretRef. The operator also injects the channel's config into operator.json so OpenClaw starts with the channel pre-configured. No manual openclaw channels add is needed.
Adding credentials incrementally: Each
oc applyof the Claw CR replaces the entirecredentialslist. When adding a new channel, include all existing credentials in the YAML — otherwise they will be removed. You can retrieve your current configuration withoc get claw instance -n $NS -o yamland add the new entry to the list.
Uses the Telegram Bot API with path-based token injection (/bot<TOKEN>/method).
1. Create a bot via @BotFather and copy the bot token.
2. Create the Secret:
oc create secret generic telegram-bot-secret \
--from-literal=token=YOUR_BOT_TOKEN \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: telegram
channel: telegram
secretRef:
- name: telegram-bot-secret
key: token
EOFThe operator infers type: pathToken, domain: api.telegram.org, and pathToken.prefix: /bot. The proxy intercepts requests like /botplaceholder/sendMessage and forwards them as /bot<REAL_TOKEN>/sendMessage. The real token never reaches the gateway pod.
By default, the operator sets dmPolicy: "open" so anyone who knows the bot's username can message it. This means Telegram works immediately after setup — no pairing approval needed.
To restrict who can DM the bot, override with channelConfig:
- name: telegram
channel: telegram
secretRef:
- name: telegram-bot-secret
key: token
channelConfig:
dmPolicy: allowlist
allowFrom: [12345, 67890]Valid dmPolicy values: open (default — anyone can message), allowlist (only listed user IDs), pairing (manual approval via CLI), disabled (no DMs).
Uses the Discord Bot API with Authorization: Bot <TOKEN> header injection. The operator automatically creates companion routes for Discord's WebSocket gateway (gateway.discord.gg) and CDN (cdn.discordapp.com).
1. Create a bot in the Discord Developer Portal and copy the bot token.
2. Create the Secret:
oc create secret generic discord-bot-secret \
--from-literal=token=YOUR_BOT_TOKEN \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: discord
channel: discord
secretRef:
- name: discord-bot-secret
key: token
EOFThe operator infers type: apiKey, domain: discord.com, and the Authorization header with Bot prefix. Companion domains for WebSocket and CDN are generated automatically.
Slack requires two tokens: an app-level token (xapp-...) for Socket Mode and a bot token (xoxb-...) for the REST API. Use the role field to distinguish them.
1. Create a Slack app at api.slack.com/apps. Enable Socket Mode, add the required OAuth scopes, and install the app to your workspace. Copy the bot token (xoxb-...) and app-level token (xapp-...).
2. Create the Secret:
oc create secret generic slack-secret \
--from-literal=app-token=YOUR_APP_TOKEN \
--from-literal=bot-token=YOUR_BOT_TOKEN \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: slack
channel: slack
secretRef:
- name: slack-secret
key: bot-token
role: botToken
- name: slack-secret
key: app-token
role: appToken
EOFThe operator infers type: bearer, domain: slack.com, path-based routing for the two tokens, and a companion route for WebSocket connections (.slack.com).
WhatsApp Web uses phone-based QR pairing — no API keys or secrets needed. The operator allowlists the required WhatsApp domains and enables the channel plugin.
1. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: whatsapp
channel: whatsapp
EOFThe operator infers type: none and creates companion routes for .whatsapp.com, .whatsapp.net, .facebook.com, .facebook.net, and .fbcdn.net (WhatsApp Web relies on Meta's auth and CDN infrastructure). It also enables the WhatsApp plugin entry in operator.json.
After applying, the OpenClaw assistant handles plugin installation (@openclaw/whatsapp) and QR pairing. A pod restart is required after plugin install since npm plugins load at boot:
oc delete pod -n $NS -l app=clawOnce the new pod is ready, the assistant completes the pairing flow. The user scans the QR code with their phone (WhatsApp → Linked Devices).
You can override any inferred field if needed (e.g., routing through a corporate proxy or using a custom domain):
- name: telegram
channel: telegram
type: pathToken
domain: "telegram.internal.corp.com"
pathToken:
prefix: "/bot"
secretRef:
- name: telegram-bot-secret
key: tokenThe channel field still enables declarative channel config injection into operator.json — only the proxy routing is overridden. You can override type, domain, and type-specific config (apiKey, pathToken) independently.
Gives OpenClaw access to GitHub's REST API for working with issues, pull requests, code search, and repositories. The proxy injects a Personal Access Token as a bearer credential — the real token never reaches the gateway pod.
Note: The pre-allowed
github.comdomain covers git HTTPS clones only (for npm dependencies).api.github.comis a separate host and requires an explicit credential entry.
1. Create a Personal Access Token at github.com/settings/tokens. A fine-grained token scoped to specific repositories is recommended over a classic token.
2. Create the Secret:
oc create secret generic github-pat-secret \
--from-literal=token=YOUR_GITHUB_PAT \
-n $NS3. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: github
type: bearer
domain: api.github.com
secretRef:
- name: github-pat-secret
key: token
EOFThe proxy intercepts requests to api.github.com and injects Authorization: Bearer <real PAT>. Skills that use curl with the GitHub REST API (like the built-in gh-issues skill) work through the proxy — they use a placeholder token that the proxy replaces transparently.
ghCLI vs curl: TheghCLI manages its own credentials viagh auth login(interactive OAuth). It doesn't use theAuthorizationheader in the same way ascurl-based skills, so proxy-based credential injection is less reliable withgh. For best results, use skills that call the GitHub REST API withcurldirectly.
MCP (Model Context Protocol) servers extend the AI assistant's capabilities by providing structured tool access to external services (GitHub API, filesystems, databases, etc.). The operator manages MCP server configuration declaratively via spec.mcpServers in the Claw CR, injecting the config into operator.json at reconciliation time.
The operator uses a three-tier security model for MCP server credentials:
| Tier | Transport | Secret handling | Secrets on gateway? |
|---|---|---|---|
| 1. HTTP/SSE (preferred) | HTTP URL | Proxy credentials entry for the domain |
No |
| 2. Stdio + proxy placeholder | Subprocess | Placeholder env var + proxy credentials entry |
No |
| 3. Stdio + real secret (escape hatch) | Subprocess | envFrom with secretKeyRef on gateway |
Yes |
Tier 1 is the recommended path — traffic goes through the MITM proxy, and credentials are injected transparently. Tier 2 keeps secrets off the gateway for stdio MCP servers whose target domain and auth type are known. Tier 3 is an explicit escape hatch for cases where tiers 1–2 are not viable.
The simplest case — an unauthenticated HTTP MCP server. The domain is auto-extracted from the URL and added as a passthrough route in the proxy. No secret or credential entry needed.
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
mcpServers:
context7:
url: https://mcp.context7.com/mcp
transport: streamable-http
EOFAn HTTP MCP server that requires authentication. Add both the MCP server entry and a credentials entry for the domain. The proxy injects the auth header — no secrets reach the gateway.
1. Create the Secret:
oc create secret generic mcp-api-key \
--from-literal=api-key=YOUR_API_KEY \
-n $NS2. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: my-mcp-service
type: bearer
domain: api.example.com
secretRef:
- name: mcp-api-key
key: api-key
mcpServers:
my-service:
url: https://api.example.com/mcp
transport: streamable-http
EOFThe proxy intercepts requests to api.example.com and injects Authorization: Bearer <real key>. The MCP server itself never sees credentials in its configuration.
For stdio MCP servers where you know which domain is called and what auth type it uses. The env var is set to a placeholder value — the proxy intercepts outbound requests and replaces the placeholder with the real credential.
1. Create the Secret:
oc create secret generic github-pat-secret \
--from-literal=token=YOUR_GITHUB_PAT \
-n $NS2. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: github
type: bearer
domain: api.github.com
secretRef:
- name: github-pat-secret
key: token
mcpServers:
github:
command: npx
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: placeholder
EOFHow it works: The GitHub MCP server subprocess inherits HTTP_PROXY/HTTPS_PROXY from the gateway container, so its outbound HTTPS calls to api.github.com go through the MITM proxy. The server sends Authorization: Bearer placeholder (from the env var), and the proxy strips it and injects the real PAT from the Secret. The real token never reaches the gateway.
Reusing credentials: If you already have a
credentialsentry forapi.github.com(e.g., for GitHub REST API access via skills), the same entry covers the MCP server too — no duplication needed.
When you don't know the MCP server's internals, or it uses the secret for non-HTTP purposes (e.g., a database password), use envFrom to mount the real secret as a gateway container environment variable. The subprocess inherits it at runtime.
1. Create the Secret:
oc create secret generic db-credentials \
--from-literal=password=YOUR_DB_PASSWORD \
-n $NS2. Apply the Claw CR:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: db-network
type: none
domain: postgres.internal
mcpServers:
custom-db:
command: node
args: ["db-mcp-server.js"]
env:
DB_HOST: postgres.internal
envFrom:
- name: DB_PASSWORD
secretRef:
name: db-credentials
key: password
EOFSecurity note: Tier 3 places the real secret on the gateway container. Use this only when tiers 1–2 are not viable. The
credentialsentry withtype: noneis still needed to allowlist the domain through the proxy (even without credential injection).
MCP servers work alongside LLM provider credentials and other integrations in the same Claw instance:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: anthropic
type: apiKey
secretRef:
- name: anthropic-api-key
key: api-key
provider: anthropic
- name: github
type: bearer
domain: api.github.com
secretRef:
- name: github-pat-secret
key: token
mcpServers:
context7:
url: https://mcp.context7.com/mcp
transport: streamable-http
github:
command: npx
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: placeholder
EOFThe operator reconciles spec.mcpServers into the mcp.servers section of operator.json. At pod startup, the init-config script deep-merges operator.json into the user's openclaw.json:
- Merge mode (default): Operator-managed MCP servers merge alongside any user-managed servers added via
openclaw mcp setinside the pod. On collision (same server name), the operator-managed entry wins. - Overwrite mode: The full config is replaced on every pod start, including MCP servers.
The operator also validates that all envFrom-referenced Secrets exist and contain the specified keys. If validation fails, the McpServersConfigured condition is set to False with a descriptive error message, and Ready is set to False.
The operator can configure a web search provider for the OpenClaw agent via spec.webSearch. Search API keys are injected by the MITM proxy — they never reach the gateway container.
Uses the Brave Search API with an API key injected via the X-Subscription-Token header.
1. Get an API key from Brave Search API.
2. Create the Secret:
oc create secret generic brave-search-key \
--from-literal=api-key=YOUR_BRAVE_API_KEY \
-n $NS3. Add to your Claw CR:
oc apply -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
namespace: $NS
spec:
credentials: [] # your existing credentials
webSearch:
provider: brave
secretRef:
name: brave-search-key
key: api-key
EOFUses the Tavily API with a bearer token.
1. Get an API key from Tavily.
2. Create the Secret:
oc create secret generic tavily-key \
--from-literal=api-key=YOUR_TAVILY_API_KEY \
-n $NS3. Add to your Claw CR:
oc apply -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
namespace: $NS
spec:
credentials: [] # your existing credentials
webSearch:
provider: tavily
secretRef:
name: tavily-key
key: api-key
EOFYou can pass provider-specific configuration via spec.webSearch.config:
webSearch:
provider: tavily
secretRef:
name: tavily-key
key: api-key
config:
maxResults: 10Key-free search — no API key or Secret needed.
oc apply -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
namespace: $NS
spec:
credentials: [] # your existing credentials
webSearch:
provider: duckduckgo
EOFUses Google's Gemini search grounding, which sends a regular Gemini API call with tools: [{ google_search }]. This reuses your existing google provider credential — no additional Secret is needed.
Prerequisite: You must have a google provider credential in spec.credentials.
oc apply -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
namespace: $NS
spec:
credentials:
- name: google
provider: google
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
webSearch:
provider: gemini
EOFThe operator sets tools.web.search.provider in operator.json and, for API-keyed providers, adds a proxy route for the search domain with credential injection. A placeholder API key is set in the config so OpenClaw makes the HTTP call; the proxy strips it and injects the real key.
The WebSearchConfigured condition tracks the status:
True— provider validated and config injectedFalse— validation failed (missing secret, missing google credential for gemini, unknown provider)
The web_fetch tool allows the agent to fetch arbitrary URLs. Enable it via spec.webFetch:
spec:
webFetch:
enabled: trueFetched URLs are gated by the proxy allowlist. Only domains already permitted by credentials, search providers, or builtin passthroughs are reachable. To allow additional domains for fetching, add type: none credential entries:
oc apply -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
namespace: $NS
spec:
credentials:
- name: docs-site
type: none
domain: docs.python.org
webFetch:
enabled: true
EOFOpenClaw's memory search feature uses embeddings for semantic recall across agent sessions. The operator automatically configures it when an embedding-capable LLM credential is present — no manual setup required.
The operator scans spec.credentials in order and picks the first provider that supports embeddings:
| Provider | Credential type | Memory search adapter |
|---|---|---|
openai |
bearer |
openai |
google |
apiKey |
gemini |
When a match is found, the operator sets agents.defaults.memorySearch.provider in operator.json. OpenClaw's native adapter handles model selection (e.g., text-embedding-3-small for OpenAI, gemini-embedding-001 for Gemini). Embedding requests route through the proxy, which injects the real credential via MITM — just like chat completions.
Providers without embedding support (anthropic, xai) and Google credentials with type: gcp (Vertex AI) are not eligible. If no embedding-capable credential exists, the operator sets memorySearch.enabled: false to suppress runtime errors.
To use a custom embedding endpoint (e.g., vLLM, Ollama, LiteLLM), configure it via spec.config.raw. When agents.defaults.memorySearch is present in the user config, the operator does not inject anything:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
namespace: $NS
spec:
credentials:
- name: anthropic
provider: anthropic
secretRef:
- name: anthropic-api-key
key: api-key
config:
raw:
agents:
defaults:
memorySearch:
provider: "openai-compatible"
model: "my-embedding-model"
remote:
baseUrl: "http://my-endpoint/v1"
apiKey: "placeholder"
EOFTo explicitly disable memory search:
spec:
config:
raw:
agents:
defaults:
memorySearch:
enabled: falseThe Claw CR supports spec.config for declarative OpenClaw application settings — diagnostics, CORS origins, model preferences, agent defaults, and any other openclaw.json key that isn't driven by a typed CRD field.
Accepts arbitrary JSON that maps directly to openclaw.json keys. These values are merged into operator.json before the enrichment pipeline runs:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
provider: google
config:
raw:
diagnostics:
otel:
enabled: true
endpoint: http://langfuse.observability.svc:3000/api/public/otel/v1/traces
captureContent:
inputMessages: true
outputMessages: true
gateway:
controlUi:
allowedOrigins:
- "https://custom.example.com"
agents:
defaults:
model:
primary: google/gemini-3.5-flash
models:
openrouter/qwen3-14b:
alias: Qwen 3 14B
plugins:
entries:
diagnostics-otel:
enabled: true
EOFControls how operator.json is applied to the PVC config at pod start:
merge(default) — deep-merges operator settings into the existing PVC config, preserving runtime changes (primary model choice, plugin installs, UI settings).overwrite— fully replaces the PVC config on every pod start. Useful for clean-slate deployments.
spec:
config:
mergeMode: overwrite
raw:
# ...The operator enforces a three-tier model. Not all config keys are equal:
| Tier | Keys | Behavior |
|---|---|---|
| Always-win | gateway.mode, gateway.bind, gateway.port, gateway.controlUi.enabled, gateway.auth.*, models.providers, channels.*, mcp.servers, tools.web.* |
Operator sets unconditionally — spec.config.raw cannot override |
| Append/merge | gateway.controlUi.allowedOrigins, gateway.trustedProxies, agents.defaults.models, agents.defaults.model.primary |
Operator provides its part, user values are merged or appended |
| User-only | diagnostics.*, session.*, logging.*, plugins.* (non-declared), skills.*, ui.*, cron.*, hooks.*, etc. |
Operator never touches — full user control |
For the complete enrichment policy, see ADR-0013.
Both methods work for user-managed settings:
spec.config.raw |
openclaw config patch |
|
|---|---|---|
| Persistence | Declarative in CR — survives CR re-apply | On PVC — survives pod restarts |
| GitOps friendly | Yes — part of the CR manifest | No — requires pod exec |
| Precedence | Wins over PVC for matching keys (except primary model) | Wins only until next reconcile |
For declarative setups managed via GitOps, prefer spec.config.raw. For one-off tweaks inside the pod, openclaw config patch is fine.
The operator can expose Prometheus metrics from your Claw instance using an OpenTelemetry Collector sidecar. When enabled, the gateway pushes OTLP metrics to a localhost sidecar that exposes a /metrics endpoint for Prometheus scraping.
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
provider: google
metrics:
enabled: true
EOFThis single field (spec.metrics.enabled: true) triggers the operator to:
- Inject
diagnostics.otel.metrics: trueand the sidecar OTLP endpoint into the gateway config - Add an OTel Collector sidecar container to the gateway pod
- Add a
metricsport (9464) to the Service - Open the NetworkPolicy for scraping from monitoring namespaces
- Create a ServiceMonitor for Prometheus Operator auto-discovery
The gateway pushes OTLP/HTTP metrics to localhost:4318. The OTel Collector sidecar receives them and exposes a Prometheus-compatible /metrics endpoint on port 9464. Prometheus (via the ServiceMonitor) scrapes this endpoint.
Gateway ──OTLP/HTTP──▶ OTel Collector sidecar ──:9464/metrics──▶ Prometheus
All traffic between the gateway and sidecar stays within the pod (localhost). The NetworkPolicy allows ingress on port 9464 only from namespaces labeled with network.openshift.io/policy-group: monitoring (OpenShift platform monitoring).
Override the default Prometheus exporter port (9464):
spec:
metrics:
enabled: true
port: 8888By default, the operator creates a ServiceMonitor when metrics are enabled. On OpenShift, Prometheus Operator is a platform component that automatically discovers ServiceMonitors.
Disable ServiceMonitor creation (e.g., if you configure scraping manually):
spec:
metrics:
enabled: true
serviceMonitor:
enabled: falseCustomize the scrape interval (default: 30s):
spec:
metrics:
enabled: true
serviceMonitor:
interval: "15s"Once enabled, verify the metrics endpoint is working:
# Port-forward to the metrics port
oc port-forward -n $NS svc/instance 9464:9464
# In another terminal, check the endpoint
curl http://localhost:9464/metricsYou should see Prometheus-format metrics from the OpenClaw gateway.
When you configure diagnostics.otel in spec.config.raw alongside spec.metrics.enabled: true, the operator deep-merges the sidecar-specific keys (metrics and metricsEndpoint) into your config without overwriting your settings. This lets you send traces to an external backend (e.g., Langfuse, MLflow) while Prometheus metrics flow through the sidecar automatically:
spec:
metrics:
enabled: true
plugins:
- "@openclaw/diagnostics-otel"
config:
raw:
diagnostics:
otel:
enabled: true
endpoint: http://langfuse.observability.svc:3000/api/public/otel/v1/traces
traces: true
captureContent:
inputMessages: true
outputMessages: true
plugins:
entries:
diagnostics-otel:
enabled: true
network:
additionalEgress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: observability
ports:
- port: 3000
protocol: TCPThe operator injects metrics: true and metricsEndpoint: "http://localhost:4318" (pointing to the sidecar) only if you haven't set them yourself. Your endpoint routes traces to Langfuse; the injected metricsEndpoint routes metrics to the sidecar for Prometheus scraping. If you set metrics: false explicitly, the operator respects it.
The operator creates strict NetworkPolicies by default: the gateway pod can only reach the MITM proxy (port 8080) and DNS, while the proxy pod can only reach TCP 443 and DNS. By default, all egress — including in-cluster traffic — goes through the MITM proxy. Set spec.network.inClusterBypass: true to allow the gateway to reach .svc and .svc.cluster.local directly (bypassing the proxy).
The operator automatically generates NetworkPolicy egress rules from spec.mcpServers[].url. No additional configuration is needed — if you declare an MCP server URL, the operator creates the appropriate NetworkPolicy rules.
Same-namespace MCP server (bare hostname):
spec:
mcpServers:
customer-api:
url: http://mcp-customer:9001/mcpWhen inClusterBypass is false (default), the operator adds an egress rule to the proxy NetworkPolicy so the proxy can reach the MCP server. When inClusterBypass is true, the rule goes on the gateway NetworkPolicy instead.
Cross-namespace MCP server (dotted Kubernetes DNS):
spec:
mcpServers:
shared-tools:
url: http://mcp-server.shared-tools.svc:9001/mcpThe operator auto-generates an egress rule targeting the shared-tools namespace on port 9001 (on the proxy NP when bypass is off, or the gateway NP when bypass is on). Cross-namespace services must use the .svc or .svc.cluster.local suffix (e.g., svc.ns.svc or svc.ns.svc.cluster.local). Bare two-part names (e.g., svc.ns) are treated as external.
External MCP on non-443 port (e.g., https://mcp.example.com:8443/mcp): the operator adds port 8443 to the proxy egress NetworkPolicy. External MCP on port 443 needs no change (already allowed).
Stdio MCP servers (subprocess, no URL) need no NetworkPolicy changes.
For services the operator cannot auto-detect — tracing collectors, databases, webhooks — use spec.network.additionalEgress to append raw NetworkPolicyEgressRule objects to the gateway egress NetworkPolicy:
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
provider: google
network:
additionalEgress:
# Cross-namespace tracing collector (Langfuse)
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: langfuse
ports:
- port: 3000
protocol: TCP
# Same-namespace database
- to:
- podSelector: {}
ports:
- port: 5432
protocol: TCP
EOFRules are standard Kubernetes NetworkPolicyEgressRule objects validated by the API server on admission. They are appended to the {instance}-egress NetworkPolicy alongside the auto-generated MCP rules.
Note:
additionalEgressonly modifies the gateway egress NetworkPolicy. For proxy egress customization (rare — only needed for external non-443 services not declared as MCP servers), create supplemental NetworkPolicies directly.
For HTTP MCP servers that need authentication, set credentialRef to the name of a credential in spec.credentials. The proxy injects credentials on the MCP server's behalf, keeping tokens out of the gateway pod:
spec:
credentials:
- name: mcp-auth
type: bearer
secretRef:
- name: mcp-token-secret
key: token
domain: mcp-server.tools.svc
mcpServers:
my-mcp:
url: http://mcp-server.tools.svc:8080/mcp
credentialRef: mcp-authWarning: If
inClusterBypassistrueand an in-cluster MCP server hascredentialRef, the operator sets a warning condition — credentials cannot be injected when traffic bypasses the proxy.
The operator supports declarative plugin installation. List plugins in spec.plugins and the operator runs an init container that installs them on the PVC before the gateway starts.
oc apply -n $NS -f - <<EOF
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: instance
spec:
credentials:
- name: gemini
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
provider: google
plugins:
- "@openclaw/matrix"
- "@openclaw/diagnostics-otel"
EOFWhen spec.plugins is non-empty, the operator adds an init-plugins init container that runs openclaw plugins install clawhub:<pkg> for each entry. The init container:
- Uses the same OpenClaw image as the gateway
- Routes traffic through the MITM proxy (required by the egress NetworkPolicy)
- Installs plugins to the shared PVC so they persist across pod restarts
The init-plugins container runs after the proxy is available and before the gateway starts. It downloads packages from ClawHub/npm through the MITM proxy, writing them to the PVC at /home/node/.openclaw/extensions.
init-volume → init-config → wait-for-proxy → init-plugins → gateway
The operator uses manifest-tracked selective cleanup to manage plugins without disturbing user-installed plugins:
- Reads
.operator-managed(a manifest file tracking previously operator-installed directories) - Removes only the directories listed in that manifest
- Installs the current set of declared plugins
- Records newly-created directories in the manifest
This means:
- User-installed plugins are preserved — plugins installed via the OpenClaw UI or CLI at runtime survive pod restarts
- Removed plugins are cleaned up — removing a plugin from
spec.pluginsuninstalls its files on the next pod restart - Crash-safe — if the pod dies mid-install, the next restart treats it as a first run (installs everything, records the manifest)
Changing the plugin list triggers a pod rollout (the operator includes the plugin list in the config hash annotation).
- The operator only manages plugins declared in
spec.plugins. User-installed plugins are never touched by the operator (not upgraded, not removed). - If a user manually installs the same plugin that is also declared in
spec.plugins, the operator takes ownership of it on the next restart.
The spec.workspace field seeds files into the OpenClaw workspace directory on first pod start. Workspace files are user-owned — they are seeded once (seedIfMissing) and user edits via the OpenClaw UI are preserved across restarts.
Set skipBootstrap: true to suppress the OpenClaw first-run questionnaire. This is useful for demo and onboarding setups where you pre-configure the identity and agents.
Use spec.workspace.files to provide an inline map of workspace-relative paths to file content. Common use cases include IDENTITY.md (user identity), AGENTS.md (agent instructions), and custom documentation.
spec:
workspace:
skipBootstrap: true
files:
IDENTITY.md: |
# Identity
- Name: Demo User
- Role: Enterprise Developer
- Company: FantaCo
AGENTS.md: |
## FantaCo Enterprise Assistant
You are a FantaCo enterprise assistant with access to
internal APIs and compliance guidelines.- Files are seeded once — if the file already exists on the PVC (from a previous pod start or user edit), the operator does not overwrite it.
- If
spec.workspace.filesincludesAGENTS.md, it overrides the operator's built-inAGENTS.mdseed. The built-in seed becomes a no-op since the destination already exists. - Workspace file changes in the CR trigger a pod rollout automatically (the operator includes all ConfigMap keys in the config hash).
The following paths are rejected by the controller (the CR enters Ready=False):
- Empty or absolute paths
- Paths containing
..(directory traversal) - Paths containing
--(reserved as the internal slash-encoding delimiter) - Paths under
skills/platform/orskills/kubernetes/(operator-managed)
The spec.skills field injects operator-managed skills into the workspace. Unlike workspace files, skills are always overwritten on every pod restart (copyAlways). Each entry creates workspace/skills/<name>/SKILL.md.
spec:
skills:
quote-builder: |
---
name: quote-builder
description: Build customer quotes using the pricing API
---
# Quote Builder
Connect to the pricing MCP server and generate quotes...
compliance: |
---
name: compliance
description: Corporate compliance guidelines
---
# Compliance
Always follow FantaCo policy...- Skills are operator-managed — the content from the CR is written to the PVC on every pod restart, overwriting any changes made inside the pod.
- This makes skills suitable for enterprise policies, shared tooling instructions, and any content that must stay in sync with the CR.
Skill names are directory components (not paths). The following names are rejected:
- Empty names
- Names containing
/ - Names containing
--(reserved delimiter) - Builtin operator skill names:
platform,kubernetes
| Feature | Interaction |
|---|---|
spec.config.raw |
Independent — workspace files are PVC content, not openclaw.json config |
spec.plugins |
Independent — plugins are npm packages; skills are markdown files |
| Existing platform/kubernetes skills | Coexist — operator-injected skills use separate ConfigMap keys |
| Config hash / rollout | Automatic — any workspace or skill change triggers pod restart |
apiVersion: claw.sandbox.redhat.com/v1alpha1
kind: Claw
metadata:
name: demo-instance
spec:
credentials:
- name: gemini
type: apiKey
secretRef:
- name: gemini-api-key
key: api-key
provider: google
config:
raw:
agents:
defaults:
model:
primary: google/gemini-2.5-pro
workspace:
skipBootstrap: true
files:
IDENTITY.md: |
# Identity
- Name: Demo User
- Role: Enterprise Developer
- Company: FantaCo
AGENTS.md: |
## FantaCo Enterprise Assistant
You are a FantaCo enterprise assistant with access to
internal APIs and compliance guidelines.
skills:
quote-builder: |
---
name: quote-builder
description: Build customer quotes using the pricing API
---
# Quote Builder
Connect to the pricing MCP server and generate quotes...
plugins:
- "@openclaw/diagnostics-otel"
metrics:
enabled: trueThe operator controller itself has no resource limits set by default. On OpenShift (OLM installs), configure limits via the Subscription CR:
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: claw-operator
namespace: openshift-operators
spec:
channel: alpha
name: claw-operator
source: claw-operator-catalog
sourceNamespace: openshift-marketplace
config:
resources:
limits:
memory: 256Mi
cpu: 500m
requests:
memory: 128Mi
cpu: 50m