Skip to content
Cisco AI Defense logo
CiscoAI Security

LLM provider keys — DefenseClaw

Overview

DefenseClaw does not hold provider secrets in config.yaml. Every credential lives either in the process environment (for CI) or in ~/.defenseclaw/.env (for workstations) at mode 0600. The defenseclaw keys command group is the operator UX for inspecting, setting, and auditing these values. The registry itself (defenseclaw.credentials.CREDENTIALS) is compiled in, so keys list always reflects exactly what the current config actually needs — there is no drift between documentation and runtime.

For internal or self-hosted LLMs whose domain is not shipped in the baked-in internal/configs/providers.json, DefenseClaw also supports an additive overlay at ~/.defenseclaw/custom-providers.json managed by defenseclaw setup provider.

The defenseclaw keys commands

CommandPurpose
defenseclaw keys listPrint every credential the registry knows about with REQUIRED / OPTIONAL / NOT USED status and source (env, dotenv, or unset)
defenseclaw keys list --jsonMachine-readable equivalent; stable schema for CI gates
defenseclaw keys list --missing-onlyOnly show REQUIRED-but-unset credentials
defenseclaw keys set ENV_NAMEPrompt for a value and write it atomically to ~/.defenseclaw/.env
defenseclaw keys set ENV_NAME --value $TOKENWrite without prompting (non-interactive/CI)
defenseclaw keys fill-missingWalk every REQUIRED-but-unset credential and prompt for each; ideal for first-time setup
defenseclaw keys checkExit 0 if all REQUIRED are set, non-zero otherwise — use in preflight hooks

Canonical credential patterns

CredentialWhere it's consumedResolution order
OPENCLAW_GATEWAY_TOKENWebSocket auth with OpenClaw gatewayos.environ~/.defenseclaw/.env → auto-detected from ~/.openclaw/openclaw.json during init
DEFENSECLAW_LLM_KEYUnified LLM key (judge, local models, general fallbacks)os.environ.env
CISCO_AI_DEFENSE_API_KEYRemote scanner mode in guardrail.scanner_mode=remote|bothos.environ.env
DEFENSECLAW_SPLUNK_HEC_TOKENSplunk HEC sinkos.environ.env
DEFENSECLAW_PD_ROUTING_KEYPagerDuty webhookos.environ.env
DEFENSECLAW_WEBEX_TOKENWebex bot webhookos.environ.env
DEFENSECLAW_WEBHOOK_SECRETGeneric HMAC-signed webhookos.environ.env

The full list is exposed by defenseclaw keys list — every row is classified against the currently-loaded config, so a credential will appear as NOT USED when the corresponding feature is disabled (e.g. Splunk token when no HEC sink is configured).

~/.defenseclaw/.env format

# Auto-generated by defenseclaw init / keys set.
# Never check in to source control.
OPENCLAW_GATEWAY_TOKEN=op_live_7a...
DEFENSECLAW_LLM_KEY=sk-ant-api03-...
DEFENSECLAW_SPLUNK_HEC_TOKEN=01234567-89ab-cdef-...

The file is created with mode 0600 and is never read from any path other than the operator's data_dir. The gateway daemon loads it through godotenv at startup; keys set performs an atomic tmp+rename so the file is never observed in a half-written state by the running sidecar.

First-time credential setup

The most efficient path for a fresh install:

defenseclaw keys list --missing-only
defenseclaw keys fill-missing --yes
defenseclaw keys check && echo "ready"
defenseclaw-gateway restart   # reload .env

fill-missing prompts only for the REQUIRED rows the current config actually needs. Skipping a prompt (empty value) leaves the credential unset and moves to the next one.

Custom provider overlay

When you run an internal or self-hosted LLM (e.g. llm.corp.example.com), the built-in provider list will not recognize it and the gateway will either block the request (strict mode) or flag it as a silent bypass in egress telemetry (default). Extend the registry in place:

defenseclaw setup provider add \
  --name corp-llm \
  --domain llm.corp.example.com \
  --env-key CORP_LLM_TOKEN \
  --profile-id corp
FlagRequiredEffect
--nameyesCanonical provider name; case-insensitively merges with any existing baseline entry
--domainyes (repeatable)Domains to treat as LLM traffic. URLs are accepted and scheme/path stripped.
--env-keyno (repeatable)API key env var names for defenseclaw keys discovery
--profile-idnoMatches openclaw auth-profiles.json profile ID
--ollama-portno (repeatable)Extra Ollama-style loopback port
--no-reloadnoSkip the POST /v1/config/providers/reload call to the guardrail proxy

Writes go to ~/.defenseclaw/custom-providers.json via atomic tmp+rename with a .bak. On success the CLI calls the sidecar's reload endpoint; on failure (401, 403, connection refused) the file is still on disk — restart the sidecar for the overlay to take effect.

defenseclaw setup provider remove --name NAME deletes an overlay entry but cannot remove baked-in baseline providers. defenseclaw setup provider list prints the overlay only; defenseclaw setup provider show prints the merged view as reported by the live guardrail proxy (GET /v1/config/providers on port 4000) with an overlay-only fallback when the proxy is unreachable.

Verify it worked

defenseclaw keys list
cat ~/.defenseclaw/custom-providers.json
curl -s http://127.0.0.1:4000/v1/config/providers | jq '.providers | length'

Troubleshooting

SymptomCauseFix
MISSING in keys list but value is exported in your shelldefenseclaw-gateway inherited a different env (e.g. started by systemd)Add to systemd unit's Environment= or write to ~/.defenseclaw/.env
sidecar rejected reload: unauthorizedOPENCLAW_GATEWAY_TOKEN unset or staledefenseclaw keys set OPENCLAW_GATEWAY_TOKEN and defenseclaw-gateway restart
refusing to use DEFENSECLAW_CUSTOM_PROVIDERS_PATHOverlay path outside allowed rootsUnset the env var or point it under ~/.defenseclaw/
cannot parse existing overlayHand-edit produced invalid JSONMove the file aside and let setup provider add rewrite it

Related