Managing Secrets in OpenClaw
I’ve been there—you’re about to push a config change and you realize your API keys are sitting right there in plain text. It’s a common headache. You want to keep your secrets safe without making your configuration impossible to manage or risking a leak.
OpenClaw handles this with SecretRefs. Instead of hardcoding credentials, you can point to environment variables, files, or external commands. This keeps your sensitive data in memory and away from your disk-based config files.
What You’ll Need
Section titled “What You’ll Need”- An active OpenClaw installation.
- Credentials stored in one of the supported sources:
- Environment variables.
- JSON files.
- External secret managers (via executable commands).
- Interactive onboarding access.
Quick Start
Section titled “Quick Start”I recommend using the standard SecretRef object. It follows the same shape everywhere in the system:
{ source: "env" | "file" | "exec", provider: "default", id: "..." }1. Using Environment Variables
Section titled “1. Using Environment Variables”This is the simplest way to get started. Set your id to the name of the environment variable.
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }- Provider: Must match
^[a-z][a-z0-9_-]{0,63}$. - ID: Must match
^[A-Z][A-Z0-9_]{0,127}$.
2. Using File-Based Secrets
Section titled “2. Using File-Based Secrets”If you store secrets in a JSON file, use a JSON pointer for the id.
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }- ID: Must be an absolute JSON pointer starting with
/. - Escaping: Use
~0for~and~1for/.
3. Using External Commands (Exec)
Section titled “3. Using External Commands (Exec)”For setups with tools like Vault, use the exec source.
{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }- ID: Must match
^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$.
4. Interactive Onboarding
Section titled “4. Interactive Onboarding”When you run onboarding in interactive mode, OpenClaw performs a preflight check. It validates your environment variable names or provider IDs before saving. If the value is empty or the provider fails, the system shows an error so you can fix it immediately.
How the Runtime Works
Section titled “How the Runtime Works”I like that OpenClaw is designed to fail fast. Secrets are resolved into an in-memory snapshot during startup. If an active SecretRef cannot be resolved, the system won’t start.
When you reload the configuration, the system uses an atomic swap. It either succeeds completely or stays on the last-known-good snapshot. This design keeps secret provider outages from breaking your active request paths.
Troubleshooting
Section titled “Troubleshooting”If things aren’t working as expected, check your logs for these specific diagnostic codes:
SECRETS_REF_IGNORED_INACTIVE_SURFACE: This means your SecretRef is on an inactive surface, like a disabled account or a tool that isn’t selected. The system ignores these to avoid unnecessary startup failures.SECRETS_GATEWAY_AUTH_SURFACE: This log entry tells you if a gateway credential isactiveorinactive. For example, if you setOPENCLAW_GATEWAY_TOKENin your environment, it wins over the config file, making the SecretRef in your configinactive.
If you are using gateway.remote.token, remember it only becomes active if gateway.mode=remote, a remote URL is configured, or you are using Tailscale serve or funnel modes.
Need more help with your specific configuration? Talk to our AI Setup Assistant.
What’s Next
Section titled “What’s Next”I have spent too many hours debugging why a secret didn’t load because one service expected an environment variable while another looked for a local JSON file. It gets messy fast when you have to manually handle different logic for every secret source in your stack.
I prefer having a single, unified way to define where secrets come from. It keeps the configuration clean and ensures that your application doesn’t care if a secret lives in a .env file or a secure vault.
What You’ll Need
Section titled “What You’ll Need”- An OpenClaw configuration file.
- Access to environment variables, local secret files, or external vault binaries.
Quick Start
Section titled “Quick Start”The best way to start is by defining your providers under the secrets.providers object. I recommend setting up a default for environment variables and specific providers for files or external tools.
Here is a complete configuration example from the documentation:
{ secrets: { providers: { default: { source: "env" }, filemain: { source: "file", path: "~/.openclaw/secrets.json", mode: "json", // or "singleValue" }, vault: { source: "exec", command: "/usr/local/bin/openclaw-vault-resolver", args: ["--profile", "prod"], passEnv: ["PATH", "VAULT_ADDR"], jsonOnly: true, }, }, defaults: { env: "default", file: "filemain", exec: "vault", }, resolution: { maxProviderConcurrency: 4, maxRefsPerProvider: 512, maxBatchBytes: 262144, }, },}Env Provider
Section titled “Env Provider”The environment provider is straightforward. You can use an optional allowlist to restrict which variables are accessible. Just keep in mind that missing or empty environment values will cause the resolution to fail.
File Provider
Section titled “File Provider”This provider reads from a local file at a specific path. I use two different modes depending on the file structure:
mode: "json": Use this when the file is a JSON object. It resolves theidas a pointer.mode: "singleValue": Use this if the file contains only the secret. It expects the ref id to be"value".
Security is strict here. The path must pass ownership and permission checks. On Windows, if ACL verification is unavailable for a path, resolution fails by default. If you are working with a trusted path and need to bypass these checks, set allowInsecurePath: true.
Exec Provider
Section titled “Exec Provider”This runs an absolute binary path directly without a shell. By default, the command cannot be a symlink. If you need to use symlinks (like Homebrew shims), you must set allowSymlinkCommand: true and pair it with trustedDirs (for example, ["/opt/homebrew"]).
The exec provider supports:
- Timeouts and no-output timeouts.
- Output byte limits.
- Environment allowlists.
- Trusted directories.
The communication happens via stdin and stdout. Here is the request payload format:
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }The expected response on stdout looks like this:
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secretIf something goes wrong with a specific ID, the executable can return optional per-id errors:
{ "protocolVersion": 1, "values": {}, "errors": { "providers/openai/apiKey": { "message": "not found" } }}Troubleshooting
Section titled “Troubleshooting”- Windows ACL Failures: If resolution fails because ACL verification is unavailable, set
allowInsecurePath: truefor that specific provider. - Symlink Command Errors: If your
commandpoints to a symlink and fails, ensureallowSymlinkCommand: trueis enabled and the directory is intrustedDirs. - Missing Env Values: If an environment variable is empty or missing, the provider will fail the resolution process.
- Exec Path Issues: The
commandmust be an absolute path to a regular file unless symlinks are explicitly allowed.
If you hit a wall while setting this up, check out the AI Setup Assistant for help.
What’s Next
Section titled “What’s Next”I’ve spent too much time worrying about where my API keys live. Keeping them in plain text is a bad idea, but copying and pasting them from a manager every time I run a command is just as frustrating. I prefer a setup where the tool handles the handshake with my secret manager directly.
The exec provider is my favorite way to handle this. It lets you run a local command to fetch a secret right when you need it. This keeps your keys out of your shell history and off your disk in plain text.
What You’ll Need
Section titled “What You’ll Need”- A local installation of your secret manager CLI (1Password, Vault, or
sops). - Your configuration file ready for provider blocks.
Quick Start
Section titled “Quick Start”You can set up an exec provider for different tools. Here is how I configure the most common ones.
1Password CLI
Section titled “1Password CLI”If you use 1Password, you can point the command to your op binary. This example pulls a password from a specific vault item.
{ secrets: { providers: { onepassword_openai: { source: "exec", command: "/opt/homebrew/bin/op", allowSymlinkCommand: true, // required for Homebrew symlinked binaries trustedDirs: ["/opt/homebrew"], args: ["read", "op://Personal/OpenClaw QA API Key/password"], passEnv: ["HOME"], jsonOnly: false, }, }, }, models: { providers: { openai: { baseUrl: "https://api.openai.com/v1", models: [{ id: "gpt-5", name: "gpt-5" }], apiKey: { source: "exec", provider: "onepassword_openai", id: "value" }, }, }, },}HashiCorp Vault CLI
Section titled “HashiCorp Vault CLI”For those using Vault, you need to pass your address and token through the environment so the CLI can authenticate.
{ secrets: { providers: { vault_openai: { source: "exec", command: "/opt/homebrew/bin/vault", allowSymlinkCommand: true, // required for Homebrew symlinked binaries trustedDirs: ["/opt/homebrew"], args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"], passEnv: ["VAULT_ADDR", "VAULT_TOKEN"], jsonOnly: false, }, }, }, models: { providers: { openai: { baseUrl: "https://api.openai.com/v1", models: [{ id: "gpt-5", name: "gpt-5" }], apiKey: { source: "exec", provider: "vault_openai", id: "value" }, }, }, },}If you prefer encrypted files in your repository, sops works great. I use the --extract flag to grab the specific key from the encrypted JSON.
{ secrets: { providers: { sops_openai: { source: "exec", command: "/opt/homebrew/bin/sops", allowSymlinkCommand: true, // required for Homebrew symlinked binaries trustedDirs: ["/opt/homebrew"], args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"], passEnv: ["SOPS_AGE_KEY_FILE"], jsonOnly: false, }, }, }, models: { providers: { openai: { baseUrl: "https://api.openai.com/v1", models: [{ id: "gpt-5", name: "gpt-5" }], apiKey: { source: "exec", provider: "sops_openai", id: "value" }, }, }, },}Troubleshooting
Section titled “Troubleshooting”Symlink Errors
Section titled “Symlink Errors”If you are using Homebrew on macOS, your binaries are often symlinked. If the command fails to execute, ensure you have set allowSymlinkCommand: true in your provider configuration.
Missing Environment Variables
Section titled “Missing Environment Variables”Commands like vault or sops often require specific environment variables (like VAULT_ADDR or SOPS_AGE_KEY_FILE) to function. If the execution fails, check that these are included in the passEnv array.
If you hit a wall with your specific setup, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I’ve spent too many hours tracking down why a config change didn’t pick up a new key or worrying about plaintext secrets sitting in configuration files. It is a common headache when you want to move toward more secure, reference-based credential management without breaking your existing setup. I want to show you how OpenClaw handles this through the SecretRef system so you can keep your environment clean and your credentials secure.
What You’ll Need
Section titled “What You’ll Need”- Access to the SecretRef Credential Surface documentation.
- An active OpenClaw instance for testing secret reloads.
Quick Start
Section titled “Quick Start”The core idea here is simple: if you provide a reference (a SecretRef), OpenClaw prefers it over a plaintext value. This allows you to transition away from hardcoded strings.
- Check your fields: If a field has a ref, it is required on active surfaces during activation.
- Understand Precedence: If you provide both a plaintext value and a ref, the ref takes precedence. For example, in Google Chat configurations,
serviceAccountRefalways wins over a plaintextserviceAccount. - Trigger Activation: Secrets aren’t just loaded once. They activate during:
- Initial Startup (preflight and final activation).
- Config reload (both hot-apply and restart-check paths).
- Manual triggers via the
secrets.reloadcommand.
- Monitor the Swap: When activation succeeds, OpenClaw swaps the secret snapshot atomically. If it fails during startup, the gateway aborts to prevent running in an insecure state.
How Commands Handle Secrets
Section titled “How Commands Handle Secrets”Not every command treats secrets the same way. I find it helpful to group them into two categories based on how they react when a secret is missing.
Strict Command Paths
Section titled “Strict Command Paths”Commands like openclaw memory (for remote-memory paths) and openclaw qr --remote are “strict.” They read from the active snapshot and will fail fast if a required SecretRef is unavailable. This prevents the system from attempting operations with incomplete credentials.
Read-Only Command Paths
Section titled “Read-Only Command Paths”Other commands are more forgiving. If you run openclaw status, openclaw status --all, openclaw channels status, or openclaw channels resolve, the system prefers the active snapshot but won’t quit if a ref is missing. Instead:
- They try a targeted local fallback if the gateway is unavailable.
- If the secret is still missing, the command continues with “degraded” output.
- You will see a diagnostic message like “configured but unavailable in this command path.”
This behavior ensures that your diagnostic tools still work even if the gateway is having trouble resolving a specific secret.
Troubleshooting
Section titled “Troubleshooting”When things go wrong, OpenClaw uses specific signals to tell you what happened.
SECRETS_REF_OVERRIDES_PLAINTEXT: You’ll see this runtime warning if you have both a plaintext value and a ref defined. The ref is being used, and the plaintext is ignored.REF_SHADOWED: This is an audit finding. It happens when credentials inauth-profiles.jsontake precedence over youropenclaw.jsonrefs.SECRETS_RELOADER_DEGRADED: If a reload fails after the system was already healthy, it enters a degraded state. It keeps the last-known-good snapshot so your service doesn’t go down.SECRETS_RELOADER_RECOVERED: You will see this once after the next successful activation following a failure.
If you rotate a secret on the backend, remember to run openclaw secrets reload to refresh the gateway snapshot via the secrets.resolve RPC method.
If you have questions about specific credential types, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I’ve spent too much time worrying about plaintext secrets hiding in my configuration files. It is easy to leave a sensitive token in a .env file or an agent config without realizing it, which creates a security risk if those files are ever shared or committed. I want to show you the best way to clean this up using the OpenClaw secrets workflow.
What You’ll Need
Section titled “What You’ll Need”- OpenClaw CLI installed
- Existing configuration files (like
openclaw.jsonorauth-profiles.json) - Access to your terminal
Quick Start
Section titled “Quick Start”You can fix your secret posture in about five minutes. I recommend following this basic loop to find and secure your credentials.
openclaw secrets audit --checkopenclaw secrets configureopenclaw secrets audit --checkThe Audit Process
Section titled “The Audit Process”When you run secrets audit, the tool looks for several security issues. It specifically scans for:
- Plaintext values at rest in
openclaw.json,auth-profiles.json,.env, and generatedagents/*/agent/models.jsonfiles. - Plaintext sensitive provider header residues in
models.jsonentries. - Unresolved references.
- Precedence shadowing, such as when
auth-profiles.jsontakes priority overopenclaw.jsonreferences. - Legacy residues like
auth.jsonor OAuth reminders.
If you are wondering how it finds headers, it uses a name-heuristic. It looks for common credential fragments like authorization, x-api-key, token, secret, password, and credential.
Using the Interactive Helper
Section titled “Using the Interactive Helper”The secrets configure command is an interactive tool that guides you through the setup. It starts by configuring your secrets.providers (supporting env, file, or exec).
From there, you can select secret-bearing fields in openclaw.json or auth-profiles.json. The tool captures SecretRef details including the source, provider, and id. Before it saves anything, it runs a preflight resolution to make sure the secrets actually work.
You can use these specific modes depending on what you need:
openclaw secrets configure --providers-onlyopenclaw secrets configure --skip-provider-setupopenclaw secrets configure --agent <id>
When you apply these changes, the CLI automatically scrubs matching static credentials from auth-profiles.json, legacy api_key entries from auth.json, and known secret lines from your .env file.
Applying a Saved Plan
Section titled “Applying a Saved Plan”If you prefer to generate a plan first, you can apply it later using the secrets apply command. I suggest using the --dry-run flag first to see exactly what will happen.
openclaw secrets apply --from /tmp/openclaw-secrets-plan.jsonopenclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-runSafety and Legacy Notes
Section titled “Safety and Legacy Notes”OpenClaw uses a one-way safety policy. It does not write rollback backups that contain historical plaintext secret values. To keep your data safe, the tool requires preflight checks to succeed before writing, and it uses atomic file replacement to update your configurations.
For those moving away from older setups, the runtime no longer depends on plaintext legacy auth storage. It uses an in-memory snapshot for credentials. While legacy api_key entries are scrubbed, OAuth-related compatibility behavior stays separate.
Troubleshooting
Section titled “Troubleshooting”The Web UI form is hard to use for complex secrets
Some SecretInput unions are easier to configure in raw editor mode than in form mode. If the UI feels restrictive, switch to the raw editor.
Audit reports precedence shadowing
This happens when auth-profiles.json is taking priority over your openclaw.json references. Use the audit results to identify which file is winning and update your configuration to point to the correct SecretRef.
Need more help with your setup? Check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.