Guides
Model credentials
Which model credential an office should use, how to store it, and which one a run picks.
Every agent run is a Claude Code process, so the office needs a model credential. It lives in the office's encrypted secret store, never in office.yaml, never on a command line, and never on screen.
Which credential to use#
A Claude subscription token (from claude setup-token) is fine for one person using an office for their own work.
When a company runs an office for its business, use Anthropic API keys: create them in a Console workspace with a spend limit.
Read the terms that apply to you: Consumer Terms and Commercial Terms. This page is not legal advice.
The same note is printed by officectl init, officectl secrets set (for any models.* secret) and officectl doctor, and shown on the Settings page.
The three secrets#
| Secret | Kind | Passed to the run as |
|---|---|---|
models.anthropic_key.<slug> | API key for one agent | ANTHROPIC_API_KEY |
models.anthropic_key | API key for the whole office | ANTHROPIC_API_KEY |
models.claude_oauth_token | Claude subscription token from claude setup-token | CLAUDE_CODE_OAUTH_TOKEN |
models.anthropic_key is the default name; models.key_secret in office.yaml changes it, and the per-agent name follows it (<key_secret>.<slug>).
Which one a run uses#
When a run is admitted, the office takes the first credential that exists:
- the agent's own API key,
models.anthropic_key.<slug> - the office API key,
models.anthropic_key - the subscription token,
models.claude_oauth_token
If none exists, the run is refused with the reason model key missing (ledger run.refused). The kind used (api_key or subscription) is recorded in the run.started and run.finished ledger entries, never the value.
A per-agent key lets you give one agent its own Console workspace and spend limit, separate from the rest of the office.
Store a credential#
At setup, officectl init can store it for you:
officectl init … --model-credential-kind api_key \
--model-credential-file ./api-key.txt
officectl init … --model-credential-kind subscription \
--model-credential-file ./setup-token.txt
--model-credential-kind subscription stores the file's contents as models.claude_oauth_token; api_key stores it as models.anthropic_key. Pass - as the file to read stdin. Run interactively without these flags, init asks for a credential (input hidden; blank skips it).
Any time later, as the office user:
# office API key
officectl secrets set models.anthropic_key
# API key for the agent "cos" only
officectl secrets set models.anthropic_key.cos
# personal use: create a subscription token, then store it
claude setup-token
officectl secrets set models.claude_oauth_token
# names only, never values
officectl secrets list
secrets set reads the value from a hidden prompt, or from stdin when piped (printf '%s' "$KEY" | officectl secrets set models.anthropic_key). Values never go in argv.
Check what is in use#
officectl doctorreportsmodel credential: API keyormodel credential: Subscription — personal use, and fails with a fix if there is none.- The Settings page (admins,
settings.read) shows the credential as a label, Subscription — personal use or API key (or Not set), and never the value. In this release it looks only at the office key secret (models.key_secret), so an office that usesmodels.claude_oauth_tokenalone shows Not set there even though runs work; trustofficectl doctor. officectl initends with aModel credential:line in its summary.
Spend#
Each agent also has a daily budget in its personnel file. With hard_stop: true, a run is refused once the day's spend reaches it, and an admitted run gets the remaining budget as a cap. A Console spend limit is a second, provider-side ceiling.