Auth Credential Semantics for Consistent Authentication
This page defines canonical credential eligibility and resolution semantics for auth profiles. Developers and integrators need it to ensure consistent authentication behavior between credential selection and runtime usage.
Read this when
- Working on auth profile resolution or credential routing
- Debugging model auth failures or profile order
These semantics ensure that authentication behavior stays consistent between credential selection and actual runtime usage. The following components all rely on them:
resolveAuthProfileOrder(profile ordering)resolveApiKeyForProfile(runtime credential resolution)openclaw models status --probeopenclaw doctorauth checks (doctor-auth)
Stable probe reason codes
When a probe never reaches a model call, its results include a status bucket (ok, auth, rate_limit, billing, timeout, format, unknown, no_model) together with a stable reasonCode:
reasonCode | Meaning |
|---|---|
excluded_by_auth_order | The profile was left out of the explicit auth order defined for its provider. |
missing_credential | No inline credential or SecretRef has been set up. |
expired | The token's expires has already expired. |
invalid_expires | expires does not represent a valid positive Unix ms timestamp. |
unresolved_ref | The configured SecretRef could not be resolved. |
ineligible_profile | The profile does not match the provider configuration (malformed key input is one cause). |
no_model | Credentials are present but no probeable model candidate could be determined. |
When credentials are usable, eligibility checks return ok as the reason code.
Token credentials
Token credentials (type: "token") support inline token and/or tokenRef.
Eligibility rules
- A token profile is ineligible if both
tokenandtokenRefare missing (missing_credential). expiresis not required. If supplied, it must be a finite count of Unix epoch milliseconds that exceeds0and does not exceed the maximum JavaScriptDatetimestamp (8640000000000000).- When
expiresis invalid (wrong type,NaN,0, negative, non-finite, or above that maximum), the profile becomes ineligible and receivesinvalid_expires. - A profile is ineligible with
expiredwhenexpiresis already expired. - Providing
tokenRefdoes not skipexpiresvalidation.
Resolution rules
- For
expires, resolver semantics are identical to eligibility semantics. - For profiles that are eligible, token material can be resolved either from the inline value or from
tokenRef. - References that cannot be resolved result in
unresolved_refinsidemodels status --probeoutput.
Agent copy portability
Agent auth inheritance operates as a read-through mechanism. When an agent lacks a local profile, it resolves profiles from the default or main agent store during runtime without copying secret data into its own credential store (agents/<agentId>/agent/openclaw-agent.sqlite).
Explicit copy operations, such as openclaw agents add, follow this portability policy:
api_keyandtokenprofiles are portable unlesscopyToAgents: false.oauthprofiles are not portable by default, since refresh tokens may be single-use or sensitive to rotation.- Provider-owned OAuth flows can opt in with
copyToAgents: trueonly when copying refresh material between agents is known to be safe; this opt-in applies solely when the profile contains inline access and refresh material.
Non-portable profiles stay accessible through read-through inheritance unless the target agent authenticates separately and builds its own local profile.
Config-only auth routes
auth.profiles entries that include mode: "aws-sdk" act as routing metadata rather than stored credentials. They remain valid whenever the target provider relies on models.providers.<id>.auth: "aws-sdk", the route automatically created by the plugin-owned Amazon Bedrock setup. Such profile identifiers can show up in auth.order and session overrides even if the credential store contains no matching entry.
Never write type: "aws-sdk" into the credential store; only api_key, token, or oauth are acceptable stored credentials. When a legacy auth-profiles.json contains this marker, openclaw doctor --fix relocates it to auth.profiles and deletes the marker from the store.
Explicit auth order filtering
- If
auth.order.<provider>or the auth-store order override is configured for a provider,models status --probeexamines only those profile ids that remain in the resolved auth order for that provider. The stored override takes precedence overauth.orderconfig. - A stored profile for that provider that is absent from the explicit order is never attempted later. The probe output flags it with
reasonCode: excluded_by_auth_orderand the detailExcluded by auth.order for this provider..
Probe target resolution
- Probe targets may originate from auth profiles, environment credentials, or
models.json(producing resultsource:profile,env,models.json). - When a provider holds credentials but OpenClaw cannot identify a probeable model candidate for it,
models status --probereturnsstatus: no_modelalong withreasonCode: no_model.
External CLI credential discovery
- Runtime-only credentials belonging to external CLIs (Claude CLI for
claude-cli, Codex CLI foropenai, MiniMax CLI forminimax-portal) are detected only when the provider, runtime, or auth profile falls within the current operation's scope, or when a stored local profile for that external source already exists. - Auth-store callers select an explicit external-CLI discovery mode:
nonefor persisted or plugin auth only,existingfor refreshing already stored external CLI profiles, orscopedfor a specific provider or profile set. - Read-only and status paths pass
allowKeychainPrompt: false; they rely solely on file-backed external CLI credentials and do not read or reuse macOS Keychain results.
OAuth SecretRef Policy Guard
SecretRef input applies exclusively to static credentials. OAuth credentials change at runtime (refresh flows persist rotated tokens), so SecretRef-backed OAuth material would split mutable state across multiple stores.
- When a profile credential is
type: "oauth", SecretRef objects are refused for any credential material field on that profile. - If
auth.profiles.<id>.modeis"oauth", SecretRef-backedkeyRefortokenRefinput for that profile is refused. - Violations result in hard failures (thrown errors) during startup, reload secret preparation, and profile resolution paths.
Legacy-Compatible Messaging
For script compatibility, probe errors preserve this first line unchanged:
Auth profile credentials are missing or expired.
Human-readable detail and the stable reason code appear on subsequent lines using the format ↳ Auth reason [code]: ....