Skip to main content

Providers

Atomic supports subscription-based providers via OAuth and API-key providers via environment variables or the auth file. Built-in catalogs ship with Atomic; configured and native providers may refresh newer catalogs independently and cache them in ~/.atomic/agent/models-store.json for offline use.

Table of Contents

Subscriptions

Use /login in interactive mode, then select a provider:
  • ChatGPT Plus/Pro (Codex)
  • Claude Pro/Max
  • GitHub Copilot
  • OpenRouter
  • Kimi Code
  • xAI (Grok/X subscription)
  • Radius
Use /login <provider> (for example /login openrouter or /login kimi-coding) to jump directly to a provider, then select subscription or API-key authentication when both are available. OpenRouter opens its provider-owned browser PKCE flow and asks whether it should mint a new API key; complete the browser redirect before returning to Atomic. On a remote or headless machine the browser cannot reach the loopback callback, so the OpenRouter login also accepts a pasted value: give it the final redirect URL, or the authorization code on its own. Claude and ChatGPT (Codex) offer the same paste fallback, as does an extension provider that sets usesCallbackServer. Kimi Code displays its provider-owned device URL/code and polls until approval, then refreshes expired tokens automatically. Built-in and extension-provided OAuth use the same direct and isolated-session lifecycle: engine-only extensions expose only safe display metadata to the terminal, while acquisition, transactional persistence, and logout remain engine-owned. Credentials and executable provider functions never cross to the isolated frontend; model-catalog refresh is separate bounded background work. Escape or Ctrl+C quietly cancels the matching login, including immediate/pre-device native aborts, and leaves the previously committed credential and catalog unchanged. Provider denial, device expiry, timeout, browser/network/protocol failure, malformed responses, token exchange, and persistence failures remain visible. Atomic claims success when the provider flow and credential persistence complete; it does not wait for model-catalog or ambient-availability refresh work. Use /logout to clear credentials. Logout immediately invalidates authentication in the active interactive engine and removes the selected provider from both ~/.atomic/agent/auth.json and any effective legacy ~/.pi/agent/auth.json, so the provider remains logged out after restart. Environment variables, command-line credentials, and models.json configuration cannot be cleared by Atomic; when one of those sources still authenticates the provider, the logout status names the remaining source.

Token Refresh

A stored OAuth token is refreshed once fewer than five minutes of validity remain, rather than at expiry, so a long turn is not started on a credential that dies mid-request. The refresh runs inside the auth.json lock and re-checks the stored expiry after taking it, so concurrent sessions sharing one credential file — subagents, workflow stages, RPC children — refresh it once between them rather than once each, and a session that arrives after the rotation finds nothing to do. A token still outside the window is not touched.

Verify Readiness Before a Session

Run atomic auth check --provider <provider> to verify the effective credential a provider would use without starting a session. You can pass --model <model> instead, including a provider/model ID, when that is the value your automation already has. The command prints ready, not_ready, or invalid; --json adds the resolved provider when one is found, credential type, and reason for a non-ready result. Checks refresh expired OAuth credentials by default through the ordinary locked auth.json path. Use --no-refresh for a read-only probe: it neither creates nor mutates an auth file and reads Atomic’s primary ~/.atomic/agent/auth.json plus legacy ~/.pi/agent/auth.json paths with the normal precedence. Readiness output contains no credential material unless you explicitly ask for --credentials with --provider or an exact --model target. That opt-in treats stdout or the JSON credentials field as a credential export; it refuses an OAuth token with less than 30 minutes of life when --no-refresh prevents a refresh.

OpenAI Codex

  • Requires ChatGPT Plus or Pro subscription
  • Officially endorsed by OpenAI: Codex for OSS
If the Codex backend reports that an OAuth/auth token was invalidated or revoked, retry the request once in case the rejection is transient. If it persists, run /logout and select OpenAI ChatGPT Plus/Pro, then run /login, authenticate that subscription again, and retry the request. Atomic displays these recovery steps with the provider error; it does not automatically delete the stored credential or repeatedly retry a definitive authentication rejection. GPT-6-Astra is selectable as openai-codex/gpt-6-astra. Atomic also derives the canonical openai-codex/gpt-6-astra-fast choice. The fast choice sends upstream model gpt-6-astra with service_tier: priority and keeps the first-party Codex transport identity described below. Codex currently marks Astra as hidden in its bundled catalog, so access can depend on the account, rollout, and minimum client policy even though Atomic lists the model. Codex describes Astra Fast as “2x speed, increased usage.” OpenAI prices Fast at twice the applicable API token rates. Pick the fast identity only when the latency reduction is worth the higher usage and price.

Fast models

Fast inference is a model choice, not a mode. Where a provider supports it, Atomic adds a second selectable model whose canonical ID is the base model ID plus -fast — for example openai-codex/gpt-5.6-sol-fast. It appears in /model, in atomic --list-models, and in workflow model catalogs alongside its normal sibling, and it is persisted and restored by that exact ID. Select it anywhere you name a model, including with a thinking suffix: openai-codex/gpt-5.6-sol-fast:medium. Two provider paths produce these variants:
  • Only first-party OpenAI openai/* and OpenAI Codex openai-codex/* models send the base upstream model ID plus the fixed service_tier: priority. A renamed provider, proxy, Azure OpenAI, OpenRouter, or generic OpenAI-compatible provider does not receive a synthetic fast variant.
  • GitHub Copilot exposes only the real fast sibling IDs the OAuth model catalog advertises for the signed-in account, and only when the corresponding base model exists in Atomic’s Copilot catalog. It sends those suffixed IDs verbatim with no OpenAI service-tier field. Copilot fast models require the account catalog metadata obtained through /login; a raw COPILOT_GITHUB_TOKEN does not provide that metadata.
The selection Atomic records stays the canonical -fast identity even when the outbound request carries the base upstream model ID, so sessions, usage rows, fallback attempts, workflow metadata, and subagent labels all keep normal and fast apart. There is no separate fast badge anywhere in the UI: the model ID already says it. A fast variant’s route owns two request fields: the upstream model ID and the service tier. A before_provider_request hook may rewrite anything else, but replacing the payload with a non-object or changing either route-owned field is refused with an error naming the model and the remedy, because a model recorded, persisted, and billed as -fast must not go out as a different model or at an ordinary tier. Select the normal sibling instead when a request needs different routing. A model without a fast variant keeps unrestricted hook freedom, and an explicit per-request service tier still applies to it without granting fast-model identity. Atomic does not publish a fast variant for a model whose API is served by an extension’s own stream function, including a natively registered provider: it cannot enforce the route through a transport it does not serialize. Such a provider keeps its normal models and its own transport untouched. Fast behavior comes from explicit route metadata attached when the variant is derived — never from the -fast suffix. If a provider, a models.json custom model, or an extension already defines that exact -fast ID, that model wins: it routes exactly as it is declared, Atomic suppresses the derived duplicate, and interactive startup and --list-models print a warning naming the model to rename or remove. Fast variants are not derived for Azure OpenAI, OpenRouter, or generic OpenAI-compatible providers. Provider-owned names that end in -fast remain ordinary exact IDs. The Vercel AI Gateway currently advertises openai/gpt-6-astra and openai/gpt-6-astra-fast; Atomic preserves both live-catalog records and their long-context prices without attaching fastRoute to the suffixed ID. OpenRouter independently advertises openai/gpt-6-astra and openai/gpt-6-astra-pro, also with request-wide long-context prices. If either live provider withdraws a record, the next generated catalog omits it rather than keeping a handwritten mirror. For first-party OpenAI Codex models on the shared ChatGPT Codex transport, explicit fast-route metadata — not the final payload tier, a caller flag, or the -fast suffix — selects the routing contract: originator: codex_cli_rs plus x-codex-routing-hint: model=<base-upstream-model>;tier=priority on both HTTP/SSE and WebSocket transports. Credential resolution preserves that identity when it resolves to the first-party ChatGPT endpoint; merely using api: "openai-codex-responses" under a renamed provider or proxy does not grant it. WebSocket fallback, reconnect, and HTTP retry attempts reuse the model route’s identity, and switching between normal and fast model routes drops a cached socket before reuse. Requests to the standard OpenAI API send only the tier. On a normal model Atomic keeps the normal originator: pi identity and sends no routing hint, even if a standalone caller explicitly requests serviceTier: priority. The same contract covers standalone modelRuntime.stream()/complete()/streamSimple()/completeSimple() requests. Pick fast variants deliberately in workflows: parallel fan-out multiplies provider usage, and priority-tier requests are billed at a higher rate.

Claude Pro/Max

Anthropic subscription auth is active for Claude Pro/Max accounts. Third-party harness usage draws from extra usage and is billed per token, not against Claude plan limits. For gateway-issued Anthropic bearer credentials, set ANTHROPIC_AUTH_TOKEN without ANTHROPIC_API_KEY or ANTHROPIC_OAUTH_TOKEN. A populated bearer token counts as configured Anthropic authentication, so /model, saved/default selection, cycling, RPC catalogs, and isolated model pickers keep Anthropic models available. Atomic sends it as Authorization: Bearer … for normal turns, branch summaries, and Verbatim Compaction without replacing caller-supplied custom headers. Claude Opus 5 is available from the bundled/dynamic Anthropic and Amazon Bedrock catalogs. With bearer-only Anthropic auth, select the exact anthropic/claude-opus-5-* entry through /model; Bedrock uses its catalog-advertised inference profile. xhigh appears only when the chosen entry advertises it. Bedrock requests retain adaptive thinking, prompt caching, and AWS validation/error details from the provider runtime. ANTHROPIC_AUTH_TOKEN is specifically for Anthropic-compatible gateways that require a bearer header. It does not synthesize an API key or x-api-key, and callers may still add independent custom headers/base URLs through models.json or an extension. Empty environment variables do not count as configured. If token and API-key sources are both configured, normal credential resolution rules apply; avoid setting both accidentally.

GitHub Copilot

  • Press Enter for github.com, or enter your GitHub Enterprise Server domain
  • COPILOT_GITHUB_TOKEN is read as an API key when you prefer an environment variable over /login
  • Models come from the bundled pi-ai GitHub Copilot catalog; an OAuth credential narrows the list to the ids your account can actually use
  • If you get “model not supported”, enable it in VS Code: Copilot Chat → model selector → select model → “Enable”
Atomic includes a provisional github-copilot/gpt-6-astra entry routed through Copilot’s Responses endpoint. Until Copilot publishes metadata, it uses Astra’s known text/image capabilities, 272,000 default context, 128,000 output limit, and low through max reasoning. Zero catalog costs mean Copilot pricing is unknown, not free. Copilot metadata takes precedence when present, and the OAuth account catalog still controls availability. This entry does not guarantee that Copilot has enabled Astra for your account. github-copilot/gpt-6-astra-fast appears only when the OAuth account catalog advertises that exact fast ID. It sends gpt-6-astra-fast unchanged with no service_tier, unlike first-party OpenAI’s priority route. A raw COPILOT_GITHUB_TOKEN cannot supply that fast entitlement.

Endpoint routing for COPILOT_GITHUB_TOKEN

OAuth logins get their Copilot host from the token GitHub issues during login. Environment-token auth has no such exchange, so Atomic resolves the host itself, highest precedence first:
  1. COPILOT_API_TARGET, then GITHUB_COPILOT_BASE_URL — an explicit host or full URL
  2. the proxy-ep= segment embedded in COPILOT_GITHUB_TOKEN
  3. GITHUB_SERVER_URL<tenant>.ghe.com routes to copilot-api.<tenant>.ghe.com; any other non-github.com host routes to https://api.enterprise.githubcopilot.com
  4. https://api.githubcopilot.com, the public routing hub, which resolves your plan’s host server-side
A models.json provider baseUrl for github-copilot overrides all of the above. Without COPILOT_GITHUB_TOKEN the provider is left exactly as upstream pi-ai defines it. Chat requests authenticated with a raw COPILOT_GITHUB_TOKEN (including github_pat_, ghp_, gho_, and ghu_ tokens) send Copilot-Integration-Id: copilot-developer-cli. A Copilot-Integration-Id supplied through models.json provider headers, modelOverrides, or per request always takes precedence, including an explicit vscode-chat value. Exchanged OAuth tokens containing a tid= segment keep the existing OAuth headers unchanged. The env-token routing implementation and its exported helpers now live in @bastani/pi-ai. Business and enterprise tokens sent to the individual host return 421 Misdirected Request; if you see that, set COPILOT_API_TARGET to the host your organization issues.

xAI (Grok/X subscription)

Run /login xai, then select Use a subscription. XAI_API_KEY remains available through Use an API key. Atomic defaults xAI sessions to grok-4.6. Built-in workflow and subagent fallback chains use xai/grok-4.6:xhigh, github-copilot/grok-4.6:xhigh, and openrouter/x-ai/grok-4.6; GitHub Copilot also exposes Grok 4.6 when the account’s model policy enables it. Network-backed catalogs refresh and cache these newer entries independently of the bundled catalog snapshot.

Radius

Radius is a dynamic pi-messages gateway. /login radius stores OAuth tokens in auth.json; its model catalog refreshes independently and is cached in models-store.json. API-key authentication is also available through /login radius or RADIUS_API_KEY. Custom Radius gateways can be declared in models.json with "oauth": "radius" and the gateway baseUrl.

API Keys

Environment Variables or Auth File

Use /login in interactive mode and select a provider to store an API key in auth.json, or set credentials via environment variable:
After a successful API-key or OAuth login, Atomic persists the credential and immediately marks that provider available against the model snapshot already loaded in the active session. It does not make login wait for cache restoration, ambient-availability checks, or another model-catalog request. Open /model to use that authenticated snapshot immediately; the selector restores and refreshes dynamic catalogs in the background with a 15-second deadline and keeps selection responsive if a provider is slow or unavailable. /logout follows the same transaction boundary in reverse: once the stored credential is deleted, Atomic immediately removes that stored-auth projection and returns to the editor without refreshing model catalogs. A short, bounded local probe preserves models when authentication still exists through an environment variable or runtime key. Refresh work that began before either login or logout cannot later overwrite the newer credential snapshot. On a remote or headless machine, paste the authorization code or final redirect URL into the login prompt when the provider offers manual entry. A completed exchange must either return to the editor or show an error; it does not require deleting ~/.atomic. Existing OAuth credentials use the same auth.json schema after the pi-ai model-runtime migration and are loaded in place. Remote pi.dev catalogs persist their ETag and are revalidated with If-None-Match; an empty 304 keeps the cached models and counts as a successful check. Atomic renders the cached snapshot immediately, preserves each provider’s last usable catalog on refresh failure, and prefers newer bundled data over stale remote overlays. See Custom Models. Z.AI and Z.AI Coding Plan (China) default to glm-5.3 (zai/glm-5.3 and zai-coding-cn/glm-5.3), and both direct providers also expose the multimodal glm-5.3-flash. Baseten defaults to its directly selectable zai-org/GLM-5.3 and also exposes zai-org/GLM-5.3-Fast and the multimodal zai-org/GLM-5.3-Flash; OpenRouter exposes z-ai/glm-5.3 and z-ai/glm-5.3-flash. The full and Flash entries support low, high, and max reasoning; Baseten’s Fast entry also supports off. Built-in workflow and subagent chains include the Z.AI, Z.AI Coding Plan, Baseten, and OpenRouter routes at :high. Use Baseten’s zai-org/GLM-5.2 or zai-org/GLM-5.3-Fast when fully disabled reasoning is required. Qwen Token Plan Individual defaults to qwen3.8-max and uses the international QWEN_TOKEN_PLAN_API_KEY shared with the existing Qwen Token Plan provider. These catalogs follow their upstream providers, so use --list-models for the current entries. Reference for environment variables and auth.json keys: findEnvKeys() / getEnvApiKey() in the installed @bastani/pi-ai dependency (node_modules/@bastani/pi-ai/dist/env-api-keys.d.ts). The private provider map those functions use is in node_modules/@bastani/pi-ai/dist/env-api-keys.js; Atomic does not include a separate packages/ai source directory in this monorepo.

Auth File

Store credentials in ~/.atomic/agent/auth.json:
qwen-token-plan-individual uses the same international endpoint and QWEN_TOKEN_PLAN_API_KEY as qwen-token-plan, but limits the picker to the models documented for Individual subscriptions. The existing provider keeps its broader catalog for backward compatibility. When using auth.json, store the credential under the provider you select; an environment variable is shared by both international providers. The file is created with 0600 permissions (user read/write only). Auth file credentials take priority over environment variables. API-key credentials may include provider-scoped env values. They take precedence over process environment variables while resolving the credential key, provider/model headers, and provider configuration such as Cloudflare account IDs, Azure settings, Vertex project/location, Bedrock settings, cache retention, and HTTP_PROXY/HTTPS_PROXY:
Use this when Atomic should use provider settings different from the project shell environment.

Key Resolution

The key field supports command execution, environment interpolation, and literals:
  • Shell command: "!command" at the start executes the whole value as a command and uses stdout (cached for process lifetime)
  • Environment interpolation: "$ENV_VAR" or "${ENV_VAR}" uses the value of the named variable. Interpolation works inside larger literals.
    $FOO_BAR is the variable FOO_BAR; use ${FOO}_BAR when BAR is literal text. Missing environment variables make the value unresolved.
  • Escapes: "$$" emits a literal "$"; "$!" emits a literal "!" without triggering command execution.
  • Literal value: Used directly
Legacy uppercase env-var-like values such as MY_API_KEY are migrated to $MY_API_KEY on startup only when that environment variable is present during migration; otherwise the value is preserved as a literal. The same explicit $ENV_VAR rule and guarded legacy migration apply to custom provider apiKey and header values in models.json; see Custom Models. OAuth credentials are also stored here after /login and managed automatically.

Cloud Providers

Azure OpenAI

Amazon Bedrock

Also supports ECS task roles (AWS_CONTAINER_CREDENTIALS_*) and IRSA (AWS_WEB_IDENTITY_TOKEN_FILE).
GPT-6-Astra uses three exact Bedrock IDs:
Select them under the single amazon-bedrock provider. Atomic passes the chosen ID unchanged to Bedrock Converse and sends the selected low, medium, high, xhigh, or max setting as the OpenAI reasoning_effort field. The unprefixed ID is Codex’s direct/Mantle entry; global. and us. are Bedrock Runtime inference profiles. Bedrock does not advertise Astra Fast, so Atomic derives no fast sibling for these models. AWS’s public region and pricing pages did not list Astra when this catalog entry was added. Availability can vary by account and region, and Atomic records zero catalog cost until AWS publishes an authoritative rate. Prompt caching is enabled automatically for Claude models whose ID contains a recognizable model name (base models and system-defined inference profiles). For application inference profiles (whose ARNs don’t contain the model name), set AWS_BEDROCK_FORCE_CACHE=1 to enable cache points:
If you are connecting to a Bedrock API proxy, the following environment variables can be used:

Cloudflare AI Gateway

CLOUDFLARE_API_KEY can be set via /login. The account ID and gateway slug must be set as environment variables.
Routes to OpenAI, Anthropic, and Workers AI through Cloudflare AI Gateway. Workers AI uses the Unified API (/compat) and prefixed model IDs (workers-ai/@cf/...). OpenAI uses the OpenAI passthrough route (/openai) with native OpenAI model IDs such as gpt-5.1. Anthropic uses the Anthropic passthrough route (/anthropic) with native Anthropic model IDs such as claude-sonnet-4-5. AI Gateway authentication uses CLOUDFLARE_API_KEY as cf-aig-authorization. Upstream authentication can be one of: For normal Atomic usage, prefer unified billing or stored BYOK. Inline BYOK requires configuring an additional upstream Authorization header for the Cloudflare AI Gateway provider, for example via a models.json provider/model override.

Workers AI binding (no API token)

When Atomic’s engine runs inside a Cloudflare Worker in the gateway’s own account, requests can route through the Workers AI binding (env.AI) instead of HTTPS. Binding calls are pre-authenticated in-account, so this path needs no CLOUDFLARE_API_KEY at all. Atomic re-exports the transport as createGatewayBindingFetch from @bastani/atomic. Declare the binding and gateway slug. The binding channel carries the account identity, so this route does not need an account ID:
Then register a provider override whose streamSimple swaps in the binding transport. The extension must be created where env is in scope — an inline extension factory passed to the resource loader does that:
Current Workers AI bindings expose fetch(). createGatewayBindingFetch forwards each request untouched to https://workers-binding.ai/ai-gateway/gateways/{gateway}/{provider}/.... baseUrl and gateway options are ignored. Methods, headers (including the auth sentinel), query strings, non-JSON bodies, request streams, and response streams retain native fetch semantics; Cloudflare’s gateway recognizes and strips the sentinel. Bindings that only expose gateway(id).run(...) are not supported. Repeat the same pattern with @bastani/pi-ai/api/openai-completions (or openai-responses), setting the model baseUrl to ${bindingPrefix}/openai (or ${bindingPrefix}/compat) for those provider routes.

Cloudflare Workers AI

CLOUDFLARE_API_KEY can be set via /login. CLOUDFLARE_ACCOUNT_ID must be set as an environment variable.
Atomic automatically sets x-session-affinity for prefix caching discounts.

Google Vertex AI

Uses Application Default Credentials:
Or set GOOGLE_APPLICATION_CREDENTIALS to a service account key file.

llama.cpp

For router-mode discovery, load/unload management, and Hugging Face downloads with a local llama.cpp server, see llama.cpp. Configure it with /login llama.cpp or LLAMA_BASE_URL and manage models with /llama.

Custom Providers

Via models.json: Add Ollama, LM Studio, vLLM, or any provider that speaks a supported API (OpenAI Completions, OpenAI Responses, Anthropic Messages, Google Generative AI). See Custom models. Via extensions: For providers that need custom API implementations or OAuth flows, create an extension. See Custom providers and examples/extensions/custom-provider-gitlab-duo.

Stop Reasons

Every provider reports why it ended a turn. Atomic stores one of stop, length, toolUse, error, or aborted; the provider’s own string (end_turn, MAX_TOKENS, tool_calls, and so on) is mapped onto it. A terminal reason the mapping does not recognise is now reported as a provider error naming the raw value, instead of being reported as an ordinary successful stop. The turn fails visibly rather than looking like a model that chose to stop early, which matters most for a truncation or safety stop a new provider version invents. Reasons that already mapped to a successful stop are unchanged, and a provider that stops on its own safety or refusal signal still surfaces the raw reason in the error text (for example Provider stopped with: SAFETY). While a response is still streaming the partial message carries the reason pending. It is replaced by the terminal reason before the message is finished, so pending is not a state a completed turn can be left in: a stream that ends while still pending is a provider error. See Custom providers for what this requires of a provider you implement yourself.

Resolution Order

When resolving credentials for a provider:
  1. CLI --api-key flag
  2. auth.json entry (API key or OAuth token)
  3. Environment variable
  4. Custom provider keys from models.json