SecretRef Credential Surface: Supported and Unsupported Fields

Learn which user-supplied credentials accept SecretRef references in OpenClaw. This reference is for developers and operators validating credential configuration.

Read this when

  • Verifying SecretRef credential coverage
  • Auditing whether a credential is eligible for `secrets configure` or `secrets apply`
  • Verifying why a credential is outside the supported surface

This page describes the canonical SecretRef credential surface, detailing which credential fields accept a SecretRef (a reference backed by env, file, exec, or store) in place of a raw secret value.

Scope:

  • In scope: only user-supplied credentials that OpenClaw neither generates nor rotates.
  • Out of scope: credentials that are runtime-generated or rotated, OAuth refresh material, and session-like artifacts.

The following lists derive from the source target registry and are validated against docs/reference/secretref-user-supplied-credentials-matrix.json in CI; avoid manual edits to entries.

Supported credentials

openclaw.json targets (secrets configure + secrets apply + secrets audit)

  • models.providers.*.apiKey
  • models.providers.*.headers.*
  • models.providers.*.request.auth.token
  • models.providers.*.request.auth.value
  • models.providers.*.request.headers.*
  • models.providers.*.request.proxy.tls.ca
  • models.providers.*.request.proxy.tls.cert
  • models.providers.*.request.proxy.tls.key
  • models.providers.*.request.proxy.tls.passphrase
  • models.providers.*.request.tls.ca
  • models.providers.*.request.tls.cert
  • models.providers.*.request.tls.key
  • models.providers.*.request.tls.passphrase
  • skills.entries.*.apiKey
  • memory.search.remote.apiKey
  • agents.entries.*.tts.providers.*.apiKey
  • agents.entries.*.memory.search.remote.apiKey
  • talk.providers.*.apiKey
  • talk.realtime.providers.*.apiKey
  • tts.providers.*.apiKey
  • plugins.entries.acpx.config.mcpServers.*.env.*
  • plugins.entries.brave.config.webSearch.apiKey
  • plugins.entries.codex.config.appServer.authToken
  • plugins.entries.codex.config.appServer.headers.*
  • plugins.entries.exa.config.webSearch.apiKey
  • plugins.entries.firecrawl.config.webFetch.apiKey
  • plugins.entries.google-meet.config.realtime.providers.*.apiKey
  • plugins.entries.google.config.webSearch.apiKey
  • plugins.entries.google.config.webSearch.headers.*
  • plugins.entries.xai.config.webSearch.apiKey
  • plugins.entries.moonshot.config.webSearch.apiKey
  • plugins.entries.perplexity.config.webSearch.apiKey
  • plugins.entries.firecrawl.config.webSearch.apiKey
  • plugins.entries.minimax.config.webSearch.apiKey
  • plugins.entries.tavily.config.webSearch.apiKey
  • plugins.entries.parallel.config.webSearch.apiKey
  • plugins.entries.voice-call.config.realtime.providers.*.apiKey
  • plugins.entries.voice-call.config.streaming.providers.*.apiKey
  • plugins.entries.voice-call.config.tts.providers.*.apiKey
  • plugins.entries.voice-call.config.twilio.authToken
  • plugins.entries.webhooks.config.routes.*.secret
  • gateway.auth.password
  • gateway.auth.token
  • gateway.remote.token
  • gateway.remote.password
  • cron.webhookToken
  • channels.telegram.botToken
  • channels.telegram.webhookSecret
  • channels.telegram.accounts.*.botToken
  • channels.telegram.accounts.*.webhookSecret
  • channels.slack.botToken
  • channels.slack.appToken
  • channels.slack.relay.authToken
  • channels.slack.userToken
  • channels.slack.signingSecret
  • channels.slack.accounts.*.botToken
  • channels.slack.accounts.*.appToken
  • channels.slack.accounts.*.relay.authToken
  • channels.slack.accounts.*.userToken
  • channels.slack.accounts.*.signingSecret
  • channels.sms.authToken
  • channels.sms.accounts.*.authToken
  • channels.buzz.authTag
  • channels.buzz.privateKey
  • channels.clickclack.token
  • channels.clickclack.accounts.*.token
  • channels.discord.token
  • channels.discord.pluralkit.token
  • channels.discord.voice.tts.providers.*.apiKey
  • channels.discord.accounts.*.token
  • channels.discord.accounts.*.pluralkit.token
  • channels.discord.accounts.*.voice.tts.providers.*.apiKey
  • channels.irc.password
  • channels.irc.nickserv.password
  • channels.irc.accounts.*.password
  • channels.irc.accounts.*.nickserv.password
  • channels.feishu.appSecret
  • channels.feishu.encryptKey
  • channels.feishu.verificationToken
  • channels.feishu.accounts.*.appSecret
  • channels.feishu.accounts.*.encryptKey
  • channels.feishu.accounts.*.verificationToken
  • channels.qqbot.clientSecret
  • channels.qqbot.accounts.*.clientSecret
  • channels.msteams.appPassword
  • channels.mattermost.botToken
  • channels.mattermost.accounts.*.botToken
  • channels.matrix.accessToken
  • channels.matrix.password
  • channels.matrix.accounts.*.accessToken
  • channels.matrix.accounts.*.password
  • channels.nextcloud-talk.botSecret
  • channels.nextcloud-talk.apiPassword
  • channels.nextcloud-talk.accounts.*.botSecret
  • channels.nextcloud-talk.accounts.*.apiPassword
  • channels.zalo.botToken
  • channels.zalo.webhookSecret
  • channels.zalo.accounts.*.botToken
  • channels.zalo.accounts.*.webhookSecret
  • channels.googlechat.serviceAccount
  • channels.googlechat.accounts.*.serviceAccount

auth-profiles.json targets (secrets configure + secrets apply + secrets audit)

  • profiles.*.keyRef (type: "api_key"; not supported when auth.profiles.<id>.mode = "oauth")
  • profiles.*.tokenRef (type: "token"; not supported when auth.profiles.<id>.mode = "oauth")

Notes: --- END REWRITE ---

  • Store references are named according to ^[A-Z][A-Z0-9_]{0,127}$ and, in this release, can only be resolved from the Gateway-wide team scope. A common example looks like {"source":"store","provider":"default","id":"OPENAI_API_KEY"}.
  • For auth-profile plan targets, agentId is mandatory; plan entries point to profiles.*.key / profiles.*.token and create sibling references (keyRef / tokenRef). Auth-profile references fall under both runtime resolution and audit coverage.
  • Within openclaw.json, SecretRefs must take structured object form, such as {"source":"env","provider":"default","id":"DISCORD_BOT_TOKEN"}. The older secretref-env:<ENV_VAR> marker strings are not accepted on SecretRef credential paths; run openclaw doctor --fix to convert any valid markers.
  • OAuth policy restriction: auth.profiles.<id>.mode = "oauth" is incompatible with SecretRef inputs for that profile. Both startup/reload and auth-profile resolution stop immediately if this policy is breached.
  • For model providers managed through SecretRef, the generated agents/*/agent/models.json entries keep non-secret markers (not the resolved secret values) for apiKey/header surfaces. Marker persistence follows the source as the authority: OpenClaw writes markers from the active source config snapshot (before resolution), never from resolved runtime secret values.
  • A cold Gateway startup can isolate retryable resolution failures for mapped owners that are not Gateway-owned. Currently mapped classes cover model providers and skills, media/TTS/cron providers, eligible auth profiles, per-agent memory, sandbox SSH, channel accounts, and manifest-declared plugin routes. During startup, each failed owner's explicit refs stay in the runtime snapshot, the owner is surfaced through status and doctor, and requests for that owner are refused without falling back to lower-precedence credentials. Reload and config-write preflight apply the same owner-aware logic: healthy owners refresh; an eligible failed owner remains stale only when its ref identities, provider definitions, and the complete non-secret owner contract are unchanged; a new or altered failure turns cold. Gateway ingress auth, structurally invalid refs or values, fail-closed owners, and currently unmapped owners continue to be strict.
  • For web search: in explicit provider mode (tools.web.search.provider set), only the key for the selected provider is active. In auto mode (tools.web.search.provider unset), only the first provider key that resolves by precedence is active, and refs for non-selected providers stay inactive until selected. Provider credentials rely on plugins.entries.<plugin>.config.webSearch.*.
  • Slack identity: "user" uses channels.slack.userToken with channels.slack.appToken for Socket Mode or channels.slack.signingSecret for HTTP mode. The same pairing also applies under channels.slack.accounts.*; this identity does not require a bot token.

Unsupported credentials

These credential classes are minted, rotated, session-bearing, or OAuth-durable, so they do not fit read-only external SecretRef resolution:

  • hooks.token
  • hooks.gmail.pushToken
  • hooks.mappings[].sessionKey
  • auth-profiles.oauth.*
  • channels.discord.threadBindings.webhookToken
  • channels.discord.accounts.*.threadBindings.webhookToken
  • channels.whatsapp.creds.json
  • channels.whatsapp.accounts.*.creds.json
768 words · updated Aug 17, 2026