Files
openclaw/docs/reference/secretref-user-supplied-credentials-matrix.json
Markus Hartung f7a9a361d9 feat(comfy): support custom headers and per-request seed randomization (#130098)
* feat(comfy): support custom headers and per-request seed randomization

Local-mode ComfyUI requests only ever sent Content-Type, so a local
instance reachable behind HTTP auth (Basic auth, a bearer token) had no
way to authenticate. Add a generic headers config key, merged over the
plugin's own headers -- same shape as the ollama plugin's established
remote.headers pattern, rather than inventing a comfy-specific scheme.

Also add optional seedNodeId/seedInputName: without it, a static
workflow file's sampler seed never changes between submissions, so
every generation was silently identical whenever the operator's
workflow relies on a fresh random seed per run.

* fix(comfy): resolve headers through the SecretInput path, not plaintext-only

The new headers config accepted only literal strings, so a credential-bearing
value (Authorization for a gated ComfyUI instance) had no path to secret
storage -- unlike the existing apiKey field, which already resolves through
resolveSecretInputString with an env-backed fallback. Mirrors that same
pattern per-header, plus the ollama plugin's established header-secret
precedent: a header pointed at a SecretRef that can't be resolved fails the
request outright instead of silently sending it unauthenticated.

* fix(comfy): resolve non-env header SecretRefs, hide capability on unresolvable ones

resolveComfyHeadersConfig only ever resolved env-sourced SecretRefs (a
manual process.env fallback bolted onto inspect-mode); any file,
keychain, or plugin-backed reference always threw, despite the schema
and docs advertising the same SecretRef shape apiKey accepts. Now
resolves through resolveConfiguredSecretInputString (the same async
resolver the ollama plugin's own headers use) for the non-literal case,
so a real non-env credential provider actually works.

Separately, isComfyCapabilityConfigured returned true for local mode
without ever inspecting headers, so an unavailable Authorization
SecretRef advertised an image/video/music tool that would always throw
on invocation. Extends the same sync inspect-based veto
resolveComfyApiKey already applies for cloud mode's apiKey.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vk2cBRQdErwRtPea8VuhG6

* fix(comfy): don't veto a resolvable non-env header secret from provider selection

hasUnavailableComfyHeaderSecret treated any non-env SecretRef as
unavailable for the isComfyCapabilityConfigured gate, on the theory that
inspect mode can't confirm it -- but "can't confirm yet" isn't "won't
resolve": the async request path can and does resolve a real
file/keychain/plugin-backed ref. That made a perfectly valid,
already-working header credential permanently hide the image/video/music
tools from the agent, which is a worse outcome than a rare genuinely
broken ref surfacing its error at actual invocation. Only a definitely
missing/empty env var (decidable synchronously, no I/O) still vetoes.

Added a permanent committed integration test
(workflow-runtime.header-secrets.integration.test.ts) that proves this,
plus the env/non-env header resolution and fail-closed paths, over real
sockets with no SDK/ssrf-runtime mocking -- replacing the throwaway
proof script from the previous push, which was deleted after running and
therefore not rerunnable or reviewable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vk2cBRQdErwRtPea8VuhG6

* fix(comfy): register header SecretRefs in the plugin secret contract

headers.* accepts and resolves SecretRef values, but the manifest never
declared configContracts.secretInputs for that path -- the canonical
plugin secret lifecycle (startup materialization, owner diagnostics,
audit/configure discovery, resolved-value redaction) only walks
manifest-declared paths, so this credential surface was invisible to
all of it despite working correctly at request time. apiKey doesn't
need the same declaration (it's covered by the separate, already-wired
provider-auth system via setup.providers.envVars/providerAuthChoices);
headers.* has no other declaration path.

Also fixes two smaller findings from the same review pass: the
seed-injection test asserted the freshly-generated seed is nonzero,
but randomInt(RANDOM_SEED_EXCLUSIVE_MAX) legitimately can (rarely)
return 0 -- a flaky assertion, removed; and documents that a configured
Content-Type header is ignored specifically on image-upload requests,
where the multipart boundary must come from the runtime.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vk2cBRQdErwRtPea8VuhG6

* docs(secrets): register comfy header SecretRefs in the credential matrix

The comfy plugin manifest change in e32863dc6cd registered
plugins.entries.comfy.config.headers.* as a secret-input target, but the
generated docs matrix and its paired markdown list weren't refreshed to
match, breaking the docs-sync CI check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vk2cBRQdErwRtPea8VuhG6

* test(comfy): restore inherited header proof env

* fix(comfy): redact reflected request credentials across generation failures

Reuse the Ollama exact-header redactor through the provider HTTP SDK, scrub structured and truncated diagnostics before retaining them, and cover decoded Basic credentials observed in real ComfyUI proxy failures. Preserve optional header and seed behavior while consolidating tests and documenting the shared boundary.

Co-authored-by: Markus Hartung <mail@hartmark.se>

* fix(provider-http): handle optional Node header values safely

Skip undefined HeaderRecord values allowed by Node types and document the intentional omission of unsafe parser causes in the lint exception. Actual credential and no-header error behavior remain unchanged.

Co-authored-by: Markus Hartung <mail@hartmark.se>

* test(comfy): explicitly stringify reflected proxy header values

Keep the socket fixture compatible with the IncomingHttpHeaders union without changing its reflected-error behavior.

Co-authored-by: Markus Hartung <mail@hartmark.se>

* test(provider-http): register credential-safe parser error exception

Track the intentional preserve-caught-error suppression in the explicit inventory: raw JSON parser causes can quote request credentials. The focused inventory and provider HTTP tests pass; runtime behavior is unchanged.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-28 01:40:22 -07:00

785 lines
23 KiB
JSON

{
"version": 1,
"matrixId": "strictly-user-supplied-credentials",
"pathSyntax": "Dot path with \"*\" for map keys and \"[]\" for arrays.",
"scope": "Credentials that are strictly user-supplied and not minted/rotated by OpenClaw runtime.",
"excludedMutableOrRuntimeManaged": [
"hooks.token",
"hooks.gmail.pushToken",
"hooks.mappings[].sessionKey",
"auth-profiles.oauth.*",
"channels.discord.accounts.*.threadBindings.webhookToken",
"channels.discord.threadBindings.webhookToken",
"channels.whatsapp.accounts.*.creds.json",
"channels.whatsapp.creds.json"
],
"entries": [
{
"id": "agents.entries.*.memory.search.remote.apiKey",
"configFile": "openclaw.json",
"path": "agents.entries.*.memory.search.remote.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "agents.entries.*.tts.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "agents.entries.*.tts.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "auth-profiles.api_key.key",
"configFile": "auth-profile-store",
"path": "profiles.*.key",
"refPath": "profiles.*.keyRef",
"when": {
"type": "api_key"
},
"secretShape": "sibling_ref",
"optIn": true,
"notes": "Compatibility exception: sibling ref field remains canonical."
},
{
"id": "auth-profiles.token.token",
"configFile": "auth-profile-store",
"path": "profiles.*.token",
"refPath": "profiles.*.tokenRef",
"when": {
"type": "token"
},
"secretShape": "sibling_ref",
"optIn": true,
"notes": "Compatibility exception: sibling ref field remains canonical."
},
{
"id": "channels.buzz.authTag",
"configFile": "openclaw.json",
"path": "channels.buzz.authTag",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.buzz.privateKey",
"configFile": "openclaw.json",
"path": "channels.buzz.privateKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.clickclack.accounts.*.token",
"configFile": "openclaw.json",
"path": "channels.clickclack.accounts.*.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.clickclack.token",
"configFile": "openclaw.json",
"path": "channels.clickclack.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.accounts.*.pluralkit.token",
"configFile": "openclaw.json",
"path": "channels.discord.accounts.*.pluralkit.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.accounts.*.token",
"configFile": "openclaw.json",
"path": "channels.discord.accounts.*.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.accounts.*.voice.realtime.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "channels.discord.accounts.*.voice.realtime.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.accounts.*.voice.tts.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "channels.discord.accounts.*.voice.tts.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.pluralkit.token",
"configFile": "openclaw.json",
"path": "channels.discord.pluralkit.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.token",
"configFile": "openclaw.json",
"path": "channels.discord.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.voice.realtime.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "channels.discord.voice.realtime.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.discord.voice.tts.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "channels.discord.voice.tts.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.feishu.accounts.*.appSecret",
"configFile": "openclaw.json",
"path": "channels.feishu.accounts.*.appSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.feishu.accounts.*.encryptKey",
"configFile": "openclaw.json",
"path": "channels.feishu.accounts.*.encryptKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.feishu.accounts.*.verificationToken",
"configFile": "openclaw.json",
"path": "channels.feishu.accounts.*.verificationToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.feishu.appSecret",
"configFile": "openclaw.json",
"path": "channels.feishu.appSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.feishu.encryptKey",
"configFile": "openclaw.json",
"path": "channels.feishu.encryptKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.feishu.verificationToken",
"configFile": "openclaw.json",
"path": "channels.feishu.verificationToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.googlechat.accounts.*.serviceAccount",
"configFile": "openclaw.json",
"path": "channels.googlechat.accounts.*.serviceAccount",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.googlechat.serviceAccount",
"configFile": "openclaw.json",
"path": "channels.googlechat.serviceAccount",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.irc.accounts.*.nickserv.password",
"configFile": "openclaw.json",
"path": "channels.irc.accounts.*.nickserv.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.irc.accounts.*.password",
"configFile": "openclaw.json",
"path": "channels.irc.accounts.*.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.irc.nickserv.password",
"configFile": "openclaw.json",
"path": "channels.irc.nickserv.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.irc.password",
"configFile": "openclaw.json",
"path": "channels.irc.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.matrix.accessToken",
"configFile": "openclaw.json",
"path": "channels.matrix.accessToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.matrix.accounts.*.accessToken",
"configFile": "openclaw.json",
"path": "channels.matrix.accounts.*.accessToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.matrix.accounts.*.password",
"configFile": "openclaw.json",
"path": "channels.matrix.accounts.*.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.matrix.password",
"configFile": "openclaw.json",
"path": "channels.matrix.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.mattermost.accounts.*.botToken",
"configFile": "openclaw.json",
"path": "channels.mattermost.accounts.*.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.mattermost.botToken",
"configFile": "openclaw.json",
"path": "channels.mattermost.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.msteams.appPassword",
"configFile": "openclaw.json",
"path": "channels.msteams.appPassword",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.nextcloud-talk.accounts.*.apiPassword",
"configFile": "openclaw.json",
"path": "channels.nextcloud-talk.accounts.*.apiPassword",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.nextcloud-talk.accounts.*.botSecret",
"configFile": "openclaw.json",
"path": "channels.nextcloud-talk.accounts.*.botSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.nextcloud-talk.apiPassword",
"configFile": "openclaw.json",
"path": "channels.nextcloud-talk.apiPassword",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.nextcloud-talk.botSecret",
"configFile": "openclaw.json",
"path": "channels.nextcloud-talk.botSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.nostr.privateKey",
"configFile": "openclaw.json",
"path": "channels.nostr.privateKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.qqbot.accounts.*.clientSecret",
"configFile": "openclaw.json",
"path": "channels.qqbot.accounts.*.clientSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.qqbot.clientSecret",
"configFile": "openclaw.json",
"path": "channels.qqbot.clientSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.accounts.*.appToken",
"configFile": "openclaw.json",
"path": "channels.slack.accounts.*.appToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.accounts.*.botToken",
"configFile": "openclaw.json",
"path": "channels.slack.accounts.*.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.accounts.*.relay.authToken",
"configFile": "openclaw.json",
"path": "channels.slack.accounts.*.relay.authToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.accounts.*.signingSecret",
"configFile": "openclaw.json",
"path": "channels.slack.accounts.*.signingSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.accounts.*.userToken",
"configFile": "openclaw.json",
"path": "channels.slack.accounts.*.userToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.appToken",
"configFile": "openclaw.json",
"path": "channels.slack.appToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.botToken",
"configFile": "openclaw.json",
"path": "channels.slack.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.relay.authToken",
"configFile": "openclaw.json",
"path": "channels.slack.relay.authToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.signingSecret",
"configFile": "openclaw.json",
"path": "channels.slack.signingSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.slack.userToken",
"configFile": "openclaw.json",
"path": "channels.slack.userToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.sms.accounts.*.authToken",
"configFile": "openclaw.json",
"path": "channels.sms.accounts.*.authToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.sms.authToken",
"configFile": "openclaw.json",
"path": "channels.sms.authToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.telegram.accounts.*.botToken",
"configFile": "openclaw.json",
"path": "channels.telegram.accounts.*.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.telegram.accounts.*.webhookSecret",
"configFile": "openclaw.json",
"path": "channels.telegram.accounts.*.webhookSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.telegram.botToken",
"configFile": "openclaw.json",
"path": "channels.telegram.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.telegram.webhookSecret",
"configFile": "openclaw.json",
"path": "channels.telegram.webhookSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.zalo.accounts.*.botToken",
"configFile": "openclaw.json",
"path": "channels.zalo.accounts.*.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.zalo.accounts.*.webhookSecret",
"configFile": "openclaw.json",
"path": "channels.zalo.accounts.*.webhookSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.zalo.botToken",
"configFile": "openclaw.json",
"path": "channels.zalo.botToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "channels.zalo.webhookSecret",
"configFile": "openclaw.json",
"path": "channels.zalo.webhookSecret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "cron.webhookToken",
"configFile": "openclaw.json",
"path": "cron.webhookToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "gateway.auth.password",
"configFile": "openclaw.json",
"path": "gateway.auth.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "gateway.auth.token",
"configFile": "openclaw.json",
"path": "gateway.auth.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "gateway.remote.password",
"configFile": "openclaw.json",
"path": "gateway.remote.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "gateway.remote.token",
"configFile": "openclaw.json",
"path": "gateway.remote.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "memory.search.remote.apiKey",
"configFile": "openclaw.json",
"path": "memory.search.remote.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "models.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.headers.*",
"configFile": "openclaw.json",
"path": "models.providers.*.headers.*",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.auth.token",
"configFile": "openclaw.json",
"path": "models.providers.*.request.auth.token",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.auth.value",
"configFile": "openclaw.json",
"path": "models.providers.*.request.auth.value",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.headers.*",
"configFile": "openclaw.json",
"path": "models.providers.*.request.headers.*",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.proxy.tls.ca",
"configFile": "openclaw.json",
"path": "models.providers.*.request.proxy.tls.ca",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.proxy.tls.cert",
"configFile": "openclaw.json",
"path": "models.providers.*.request.proxy.tls.cert",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.proxy.tls.key",
"configFile": "openclaw.json",
"path": "models.providers.*.request.proxy.tls.key",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.proxy.tls.passphrase",
"configFile": "openclaw.json",
"path": "models.providers.*.request.proxy.tls.passphrase",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.tls.ca",
"configFile": "openclaw.json",
"path": "models.providers.*.request.tls.ca",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.tls.cert",
"configFile": "openclaw.json",
"path": "models.providers.*.request.tls.cert",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.tls.key",
"configFile": "openclaw.json",
"path": "models.providers.*.request.tls.key",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "models.providers.*.request.tls.passphrase",
"configFile": "openclaw.json",
"path": "models.providers.*.request.tls.passphrase",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.acpx.config.mcpServers.*.env.*",
"configFile": "openclaw.json",
"path": "plugins.entries.acpx.config.mcpServers.*.env.*",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.brave.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.brave.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.codex.config.appServer.authToken",
"configFile": "openclaw.json",
"path": "plugins.entries.codex.config.appServer.authToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.codex.config.appServer.headers.*",
"configFile": "openclaw.json",
"path": "plugins.entries.codex.config.appServer.headers.*",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.comfy.config.headers.*",
"configFile": "openclaw.json",
"path": "plugins.entries.comfy.config.headers.*",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.exa.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.exa.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.firecrawl.config.webFetch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.firecrawl.config.webFetch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.firecrawl.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.firecrawl.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.google-meet.config.realtime.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.google-meet.config.realtime.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.google.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.google.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.google.config.webSearch.headers.*",
"configFile": "openclaw.json",
"path": "plugins.entries.google.config.webSearch.headers.*",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.imap.config.accounts.*.password",
"configFile": "openclaw.json",
"path": "plugins.entries.imap.config.accounts.*.password",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.minimax.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.minimax.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.moonshot.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.moonshot.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.parallel.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.parallel.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.perplexity.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.perplexity.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.tavily.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.tavily.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.voice-call.config.realtime.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.voice-call.config.realtime.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.voice-call.config.streaming.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.voice-call.config.streaming.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.voice-call.config.tts.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.voice-call.config.tts.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.voice-call.config.twilio.authToken",
"configFile": "openclaw.json",
"path": "plugins.entries.voice-call.config.twilio.authToken",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.webhooks.config.routes.*.secret",
"configFile": "openclaw.json",
"path": "plugins.entries.webhooks.config.routes.*.secret",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "plugins.entries.xai.config.webSearch.apiKey",
"configFile": "openclaw.json",
"path": "plugins.entries.xai.config.webSearch.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "skills.entries.*.apiKey",
"configFile": "openclaw.json",
"path": "skills.entries.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "talk.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "talk.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "talk.realtime.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "talk.realtime.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
},
{
"id": "tts.providers.*.apiKey",
"configFile": "openclaw.json",
"path": "tts.providers.*.apiKey",
"secretShape": "secret_input",
"optIn": true
}
]
}