refactor(auth): store auth profiles in sqlite (#89102)

This commit is contained in:
Peter Steinberger
2026-06-03 16:14:15 -07:00
committed by GitHub
parent 116bc2a0f0
commit e16ac04330
87 changed files with 2832 additions and 4849 deletions

View File

@@ -108,10 +108,10 @@ These notices are operational messages, not assistant content. They are delivere
OpenClaw uses **auth profiles** for both API keys and OAuth tokens.
- Secrets live in `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` (legacy: `~/.openclaw/agent/auth-profiles.json`).
- Runtime auth-routing state lives in `~/.openclaw/agents/<agentId>/agent/auth-state.json`.
- Secrets and runtime auth-routing state live in `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`.
- Config `auth.profiles` / `auth.order` are **metadata + routing only** (no secrets).
- Legacy import-only OAuth file: `~/.openclaw/credentials/oauth.json` (imported into `auth-profiles.json` on first use).
- Legacy import-only OAuth file: `~/.openclaw/credentials/oauth.json` (imported into the per-agent auth store on first use).
- Legacy `auth-profiles.json`, `auth-state.json`, and per-agent `auth.json` files are imported by `openclaw doctor --fix`.
More detail: [OAuth](/concepts/oauth)
@@ -127,7 +127,7 @@ OAuth logins create distinct profiles so multiple accounts can coexist.
- Default: `provider:default` when no email is available.
- OAuth with email: `provider:<email>` (for example `google-antigravity:user@gmail.com`).
Profiles live in `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` under `profiles`.
Profiles live in the per-agent `openclaw-agent.sqlite` auth profile store.
## Rotation order
@@ -141,7 +141,7 @@ When a provider has multiple profiles, OpenClaw chooses an order like this:
`auth.profiles` filtered by provider.
</Step>
<Step title="Stored profiles">
Entries in `auth-profiles.json` for the provider.
Per-agent SQLite auth profile entries for the provider.
</Step>
</Steps>
@@ -229,7 +229,7 @@ Cooldowns use exponential backoff:
- 25 minutes
- 1 hour (cap)
State is stored in `auth-state.json` under `usageStats`:
State is stored in the per-agent SQLite auth state under `usageStats`:
```json
{
@@ -253,7 +253,7 @@ Not every billing-shaped response is `402`, and not every HTTP `402` lands here.
Meanwhile temporary `402` usage-window and organization/workspace spend-limit errors are classified as `rate_limit` when the message looks retryable (for example `weekly usage limit exhausted`, `daily limit reached, resets tomorrow`, or `organization spending limit exceeded`). Those stay on the short cooldown/failover path instead of the long billing-disable path.
</Note>
State is stored in `auth-state.json`:
State is stored in the per-agent SQLite auth state:
```json
{

View File

@@ -87,13 +87,13 @@ This is a two-step setup:
If `claude` is not on `PATH`, either install Claude Code first or set
`agents.defaults.cliBackends.claude-cli.command` to the real binary path.
Manual token entry (any provider; writes `auth-profiles.json` + updates config):
Manual token entry (any provider; writes the per-agent SQLite auth store + updates config):
```bash
openclaw models auth paste-token --provider openrouter
```
`auth-profiles.json` stores credentials only. The canonical shape is:
The auth profile store keeps credentials only. Legacy `auth-profiles.json` files used this canonical shape:
```json
{
@@ -108,9 +108,9 @@ openclaw models auth paste-token --provider openrouter
}
```
OpenClaw expects the canonical `version` + `profiles` shape at runtime. If an older install still has a flat file such as `{ "openrouter": { "apiKey": "..." } }`, run `openclaw doctor --fix` to rewrite it as an `openrouter:default` API-key profile; doctor keeps a `.legacy-flat.*.bak` copy beside the original. Endpoint details such as `baseUrl`, `api`, model ids, headers, and timeouts belong under `models.providers.<id>` in `openclaw.json` or `models.json`, not in `auth-profiles.json`.
OpenClaw now reads auth profiles from each agent's `openclaw-agent.sqlite`. If an older install still has `auth-profiles.json`, `auth-state.json`, or a flat auth profile file such as `{ "openrouter": { "apiKey": "..." } }`, run `openclaw doctor --fix` to import it into SQLite; doctor keeps timestamped backups beside the original JSON files. Endpoint details such as `baseUrl`, `api`, model ids, headers, and timeouts belong under `models.providers.<id>` in `openclaw.json` or `models.json`, not in auth profiles.
External auth routes such as Bedrock `auth: "aws-sdk"` are also not credentials. If you want a named Bedrock route, put `auth.profiles.<id>.mode: "aws-sdk"` in `openclaw.json`; do not write `type: "aws-sdk"` into `auth-profiles.json`. `openclaw doctor --fix` moves legacy AWS SDK markers from the credential store into config metadata.
External auth routes such as Bedrock `auth: "aws-sdk"` are also not credentials. If you want a named Bedrock route, put `auth.profiles.<id>.mode: "aws-sdk"` in `openclaw.json`; do not write `type: "aws-sdk"` into the auth profile store. `openclaw doctor --fix` moves legacy AWS SDK markers from the credential store into config metadata.
Auth profile refs are also supported for static credentials:
@@ -225,7 +225,7 @@ Use `/model` (or `/model list`) for a compact picker; use `/model status` for th
### Per-agent (CLI override)
Set an explicit auth profile order override for an agent (stored in that agent's `auth-state.json`):
Set an explicit auth profile order override for an agent (stored in that agent's SQLite auth state):
```bash
openclaw models auth order get --provider anthropic