Gateway
Auth credential semantics
These semantics keep selection-time and runtime auth behavior aligned. They are shared by:
resolveAuthProfileOrder(profile ordering)resolveApiKeyForProfile(runtime credential resolution)openclaw models status --probeopenclaw doctorauth checks (doctor-auth)
Stable probe reason codes
Probe results carry a status bucket (ok, auth, rate_limit, billing, timeout, format, unknown, no_model) plus a stable reasonCode when the probe never reached a model call:
reasonCode |
Meaning |
|---|---|
excluded_by_auth_order |
Profile omitted from the explicit auth order for its provider. |
missing_credential |
No inline credential or SecretRef is configured. |
expired |
Token expires is in the past. |
invalid_expires |
expires is not a valid positive Unix ms timestamp. |
unresolved_ref |
Configured SecretRef could not be resolved. |
ineligible_profile |
Profile is incompatible with provider config (includes malformed key input). |
no_model |
Credentials exist but no probeable model candidate resolved. |
Eligibility checks report ok as the reason code for usable credentials.
Token credentials
Token credentials (type: "token") support inline token and/or tokenRef.
Eligibility rules
- A token profile is ineligible when both
tokenandtokenRefare absent (missing_credential). expiresis optional. When present it must be a finite number of Unix epoch milliseconds greater than0and no larger than the maximum JavaScriptDatetimestamp (8640000000000000).- If
expiresis invalid (wrong type,NaN,0, negative, non-finite, or beyond that maximum), the profile is ineligible withinvalid_expires. - If
expiresis in the past, the profile is ineligible withexpired. tokenRefdoes not bypassexpiresvalidation.
Resolution rules
- Resolver semantics match eligibility semantics for
expires. - For eligible profiles, token material may be resolved from the inline value or
tokenRef. - Unresolvable refs produce
unresolved_refinmodels status --probeoutput.
Agent copy portability
Agent auth inheritance is read-through. When an agent has no local profile, it resolves profiles from the shared auth store at runtime without copying secret material into its own credential store (agents/<agentId>/agent/openclaw-agent.sqlite). The shared store lives in state/openclaw.sqlite after openclaw doctor --fix performs the one-time relocation. Until then, doctor reports the legacy agents/main/agent/openclaw-agent.sqlite owner and leaves that agent undeletable.
Explicit copy flows, such as openclaw agents add, use this portability policy:
api_keyandtokenprofiles are portable unlesscopyToAgents: false.oauthprofiles are not portable by default because refresh tokens can be single-use or rotation-sensitive.- Provider-owned OAuth flows may opt in with
copyToAgents: trueonly when copying refresh material across agents is known safe; the opt-in only applies when the profile carries inline access/refresh material.
Non-portable profiles remain available through the shared read-through base unless the target agent signs in separately and creates its own local profile.
openclaw agent exec preserves the original shared-store root when switching to temporary run state. Its bounded credential scope reads portable api_key and token profiles from that shared store without persisting copies; the configured agent's local profiles still win. Shared OAuth profiles are excluded from this temporary scope, even with copyToAgents: true, so the run does not acquire another refresh owner. --auth-env-only disables stored credential access entirely.
Auth writes that explicitly select a state directory, including isolated QA staging, use that directory's shared store for ownership and OAuth deduplication. Their runtime publication and rollback retain the same owner; another process-local state root is not an inherited base. An unrelated outer database may be older, newer, or unreadable without blocking an isolated write, but an unreadable or newer database in the selected target still fails closed. Writes without an explicit state directory retain the normal ambient state and agent-directory configuration.
Config-only auth routes
auth.profiles entries with mode: "aws-sdk" are routing metadata, not stored credentials. They are valid when the target provider uses models.providers.<id>.auth: "aws-sdk", the route the plugin-owned Amazon Bedrock setup writes. These profile ids may appear in auth.order and session overrides even when no matching entry exists in the credential store.
Do not write type: "aws-sdk" into the credential store; stored credentials are only api_key, token, or oauth. If a legacy auth-profiles.json has such a marker, openclaw doctor --fix moves it to auth.profiles and removes the marker from the store.
Explicit auth order filtering
- When
auth.order.<provider>or the auth-store order override is set for a provider,models status --probeonly probes profile ids that remain in the resolved auth order for that provider. The stored override wins overauth.orderconfig. - A stored profile for that provider that is omitted from the explicit order is not silently tried later. Probe output reports it with
reasonCode: excluded_by_auth_orderand the detailExcluded by auth.order for this provider. - A valid session user pin is an explicit per-session exception: OpenClaw tries that profile first even when it is omitted from the provider order, then uses the ordered same-provider profiles as retry candidates. A cooldown or disabled window applies only to the affected profile; it does not suppress its eligible siblings.
Probe target resolution
- Probe targets can come from auth profiles, environment credentials, or
models.json(resultsource:profile,env,models.json). - If a provider has credentials but OpenClaw cannot resolve a probeable model candidate for it,
models status --probereportsstatus: no_modelwithreasonCode: no_model.
External CLI credential discovery
- Runtime-only credentials owned by external CLIs (Claude CLI for
claude-cli, Codex CLI foropenai, MiniMax CLI forminimax-portal) are discovered only when the provider, runtime, or auth profile is in scope for the current operation, or when a stored local profile for that external source already exists. - Auth-store callers choose an explicit external-CLI discovery mode:
nonefor persisted/plugin auth only,existingfor refreshing already stored external CLI profiles, orscopedfor a concrete provider/profile set. - Read-only/status paths pass
allowKeychainPrompt: false; they use file-backed external CLI credentials only and do not read or reuse macOS Keychain results.
OAuth SecretRef Policy Guard
SecretRef input is for static credentials only. OAuth credentials are runtime-mutable (refresh flows persist rotated tokens), so SecretRef-backed OAuth material would split mutable state across stores.
- If a profile credential is
type: "oauth", SecretRef objects are rejected for any credential material field on that profile. - If
auth.profiles.<id>.modeis"oauth", SecretRef-backedkeyRef/tokenRefinput for that profile is rejected. - Violations are hard failures (thrown errors) in startup/reload secret preparation and profile resolution paths.
Legacy-Compatible Messaging
For script compatibility, probe errors keep this first line unchanged:
Auth profile credentials are missing or expired.
Human-friendly detail and the stable reason code follow on subsequent lines in the form ↳ Auth reason [code]: ....