HashiCorp Vault SecretRef provider integration for OpenClaw.
claw-vault lets OpenClaw read model provider API keys from Vault at
startup/reload time instead of storing those keys as plaintext in
openclaw.json. The repository and package are named claw-vault, but the
OpenClaw plugin id is vault.
This path configures OpenRouter through Vault, then sets an OpenRouter model as the OpenClaw default.
From ClawHub, when available:
openclaw plugins install clawhub:claw-vault --forceFrom GitHub:
openclaw plugins install git:github.com/sallyom/claw-vault --forceFrom a local checkout:
openclaw plugins install /path/to/claw-vault --forceConfirm the command is available:
openclaw vault statusThe default resolver expects a KV mount named secret and KV version 2. With
that default, this OpenClaw SecretRef id:
providers/openrouter/apiKey
reads this Vault secret path and field:
secret/data/providers/openrouter -> apiKey
Using the Vault CLI, store the key:
export OPENROUTER_API_KEY=replace-with-openrouter-api-key
vault kv put secret/providers/openrouter apiKey="$OPENROUTER_API_KEY"Use Vault auth that produces a client token for OpenClaw, not a root token. The client token only needs read access to the secret paths OpenClaw should resolve. For default KV v2 paths, a minimal policy looks like:
path "secret/data/providers/*" {
capabilities = ["read"]
}One simple Vault CLI setup flow is:
vault policy write openclaw-model-providers ./openclaw-model-providers.hcl
vault token create -policy=openclaw-model-providersSet these in the same shell, service, or container environment that starts the
OpenClaw Gateway. The default auth method reads a token from VAULT_TOKEN:
export VAULT_ADDR=https://vault.example.com
export VAULT_TOKEN=replace-with-vault-client-tokenIf Vault Agent writes a token sink file, use token-file auth:
export VAULT_ADDR=https://vault.example.com
export CLAW_VAULT_AUTH_METHOD=token_file
export VAULT_TOKEN_FILE=/vault/secrets/tokenFor non-interactive JWT auth, use a workload JWT file and a Vault role of type
jwt:
export VAULT_ADDR=https://vault.example.com
export CLAW_VAULT_AUTH_METHOD=jwt
export CLAW_VAULT_AUTH_MOUNT=jwt
export CLAW_VAULT_AUTH_ROLE=openclaw
export CLAW_VAULT_JWT_FILE=/var/run/secrets/tokens/vaultFor Vault's Kubernetes auth method, use kubernetes. The default mount is
kubernetes, and the default JWT file is the standard service account token
path:
export VAULT_ADDR=https://vault.example.com
export CLAW_VAULT_AUTH_METHOD=kubernetes
export CLAW_VAULT_AUTH_ROLE=openclawOptional settings:
export VAULT_NAMESPACE=namespace-name
export CLAW_VAULT_KV_MOUNT=secret
export CLAW_VAULT_KV_VERSION=2If OpenClaw runs in a container, pass these environment variables to that
container. openclaw vault status can see your shell environment, but the
Gateway can only resolve SecretRefs from the environment it actually runs with.
Check what the plugin can see:
openclaw vault statusThe status output reports whether VAULT_ADDR is set, which auth method is in
use, whether token/JWT file inputs are configured, and which KV mount/version
will be used. It never prints token values.
Generate a plan that maps models.providers.openrouter.apiKey to the Vault
SecretRef:
openclaw vault setup \
--plan-out ./vault-secrets-plan.json \
--openrouter-id providers/openrouter/apiKeyDry-run the plan, apply it, audit the result, and reload a running Gateway:
openclaw secrets apply --from ./vault-secrets-plan.json --dry-run --allow-exec
openclaw secrets apply --from ./vault-secrets-plan.json --allow-exec
openclaw secrets audit --allow-exec --check
openclaw secrets reloadUse --allow-exec because this plugin resolves SecretRefs through an
OpenClaw-managed exec provider.
If the Gateway is not running yet, start it normally after applying the plan
instead of running openclaw secrets reload.
openclaw models set openrouter/qwen/qwen3.7-max
openclaw models status --probe --probe-provider openrouterThe probe should report openrouter/qwen/qwen3.7-max as healthy without an
OPENROUTER_API_KEY in the OpenClaw process environment.
Built-in shortcuts:
openclaw vault setup --openai-id providers/openai/apiKey
openclaw vault setup --anthropic-id providers/anthropic/apiKey
openclaw vault setup --openrouter-id providers/openrouter/apiKeyMultiple provider keys in one plan:
openclaw vault setup \
--plan-out ./vault-secrets-plan.json \
--openai-id providers/openai/apiKey \
--anthropic-id providers/anthropic/apiKey \
--openrouter-id providers/openrouter/apiKeyOpenAI-compatible or custom model providers use --provider-key:
openclaw vault setup \
--plan-out ./vault-secrets-plan.json \
--provider-key local-openai=providers/local-openai/apiKey \
--provider-key groq=providers/groq/apiKeyEach --provider-key <provider=id> writes a SecretRef to
models.providers.<provider>.apiKey.
SecretRef ids use this convention:
<vault-secret-path>/<field>
Examples:
| SecretRef id | Default KV v2 Vault read | Returned field |
|---|---|---|
providers/openrouter/apiKey |
secret/data/providers/openrouter |
apiKey |
providers/openai/apiKey |
secret/data/providers/openai |
apiKey |
teams/agent-prod/openrouter |
secret/data/teams/agent-prod |
openrouter |
The field value must be a string.
For KV v1, set:
export CLAW_VAULT_KV_VERSION=1Then providers/openrouter/apiKey reads
secret/providers/openrouter -> apiKey.
openclaw vault setup writes an OpenClaw secrets apply plan. Applying that
plan stores a plugin-managed Vault provider:
{
"source": "exec",
"pluginIntegration": {
"pluginId": "vault",
"integrationId": "vault"
}
}Model API key fields point at that local provider alias:
{ "source": "exec", "provider": "vault", "id": "providers/openrouter/apiKey" }The resolved API key is kept in OpenClaw's in-memory runtime snapshot after
startup or openclaw secrets reload; it is not written back to
openclaw.json.
openclaw vault is not found:
- Confirm the plugin installed successfully with
openclaw plugins list. - Reinstall with
openclaw plugins install git:github.com/sallyom/claw-vault --force.
VAULT_ADDR is required, VAULT_TOKEN is required, or an auth file/role is
required:
- Export the missing variable for the selected auth method in the environment that runs the command.
- For Gateway startup/reload, make sure the variable is also present in the Gateway service or container environment.
Vault returns 403:
- Use a client token with
readaccess to the exact Vault paths. - For default KV v2, policy paths usually look like
secret/data/providers/*, notsecret/providers/*.
Vault returns 404 or the field is missing:
- Check the mount, KV version, secret path, and field name.
- For default KV v2, create the example OpenRouter secret with
vault kv put secret/providers/openrouter apiKey="$OPENROUTER_API_KEY".
secrets apply rejects the plan:
- Plans containing exec providers require
--allow-execin write mode. - Dry-runs skip exec checks unless
--allow-execis set.
The Gateway still uses old credentials:
- Run
openclaw secrets reload, or restart the Gateway. - For service/container installs, confirm
VAULT_ADDRand the selected auth inputs are in the Gateway runtime environment, not only in your interactive shell.
Run the local test suite to exercise the resolver protocol against HTTP Vault fixtures:
npm test- Getting started with Vault SecretRefs
- OpenClaw SecretRefs: https://docs.openclaw.ai/gateway/secrets
- OpenClaw secrets CLI: https://docs.openclaw.ai/cli/secrets
npm install
npm test