Provider reference A provider supplies authentication and transport. A model selects the model identifier and its tool dialect. Changing one does not guarantee that the other provider exposes the same tools, context limit, or billing method. Provider identifiers Identifier | Connection | Before starting | openai | OpenAI | Connect a supported account or API credential through the login interface | xai | xAI / Grok | Connect a supported Grok account or API credential | openrouter | OpenRouter | Connect credentials; OPENROUTER_API_KEY is recognized | gemini | Google Gemini | Use Google sign-in, or GOOGLE_API_KEY / GEMINI_API_KEY for API billing | claude-code | Claude Code SDK | Install Claude Code, run claude auth login, and select the provider explicitly | Without --provider, the CLI detects a provider from available authentication. Claude Code requires explicit selection. Use the current /model catalog rather than assuming that a model name offered by one provider works with another. OpenAI / ChatGPT - Open /login and connect the OpenAI account using the offered login flow. - For API billing, add the API credential through the account interface rather than placing it in a prompt. - Start agent-cli --provider openai, select an OpenAI model, and inspect /session-info. The coding credential loader also reads CODEX_ACCESS_TOKEN, CODEX_AUTH_JSON, and ~/.codex/auth.json. CODEX_HOME changes the directory containing that file. These are credential sources, not model catalog settings. A plain access token cannot provide the same refresh information as a complete OAuth login. Enabled managed accounts are combined with external accounts; managed accounts suppress duplicates with the same account identity. When subscription accounts exist, the automatic OpenAI pool uses subscription accounts rather than mixing them with API-billed accounts. Do not assume that exporting OPENAI_API_KEY selects coding API billing: that variable is also used by separate functionality such as dictation. Use the login interface to configure coding credentials explicitly. xAI / Grok - Open /login and connect your Grok account, or use /meta connect my Grok account. - Complete the browser flow and return to the terminal. - Start agent-cli --provider xai and choose a Grok model from /model. External credentials are also discovered from GROK_AUTH_JSON, GROK_ACCESS_TOKEN, and ~/.grok/auth.json. Managed credentials are considered before external sources. Use a complete login when refresh is required; do not repeatedly reuse an expired bearer token. OpenRouter Create a key in your OpenRouter account, then either add it through /login or supply OPENROUTER_API_KEY in the environment of the process that starts Haskell Agent. A managed credential takes precedence over the external environment credential when no specific external account was selected. agent-cli --provider openrouter Select the exact OpenRouter model identifier from /model. To add another OpenRouter model, invoke $add-model with its identifier. OpenRouter has its own API billing and model availability; a direct-provider subscription does not fund this route. Google Gemini Choose a Gemini entry in /model to initiate Google sign-in when no credential exists. For AI Studio API billing, supply GOOGLE_API_KEY or GEMINI_API_KEY before starting. Among those environment variables, GOOGLE_API_KEY takes precedence. Managed Gemini credentials are considered first, so an existing managed connection can explain why adding an environment variable did not change the account. Meta Model API The shipped catalog also includes a direct Meta connection. Supply MODEL_API_KEY to the process and select agent-cli --model muse-spark-1.2. The separate meta/muse-spark-1.2 catalog entry uses OpenRouter instead. Select by model identifier; do not infer a new --provider value from a connection name. Claude Code SDK Authenticate the installed Claude Code executable with claude auth login, then run agent-cli --provider claude-code --model sonnet. This provider is never chosen by automatic credential detection. Its SDK tools and authentication differ from the Responses connections; a custom Responses URL does not configure Claude Code. Automatic provider detection When no provider is selected and credential detection is used, the order is OpenAI, xAI, OpenRouter, then Gemini. This checks available authentication, not the cheapest provider or the fastest model. An explicit --provider avoids ambiguity. A custom catalog model selects its own connection instead of adding a provider to this order. Example: choose and verify Gemini agent-cli --provider gemini Complete Google sign-in if prompted, select a Gemini model, then inspect the session: /model /session-info Expected result: the session reports your selected model and its available tools. If login fails, use /login to inspect connections. Do not paste credentials into a normal prompt. Connection diagnostics Symptom | Check | No credentials found | Connect the intended provider with /login. Environment variables must be present in the launching process, not another terminal. | Unexpected account or billing | Inspect the login dashboard and managed accounts before changing keys; explicit provider selection does not itself select an API billing account. | 401 / expired token | Reauthorize the selected account. After changing an external credential file, use /reload-auth. | Model unavailable | Confirm the exact catalog identifier and that the selected account has access; similarly named direct and OpenRouter models use different connections. | 429 / usage exhausted | Inspect /usage and the provider reset time. Reauthentication does not replenish quota. | For credential and direct-transport overrides, use the environment reference. Those variables do not override every managed account or gateway routing decision. Multiple accounts and remembered selection Provider-local usage ranking is available for direct OpenAI, xAI and OpenRouter accounts. It is not used for gateway authentication, Gemini or Claude Code. Among candidates with a known positive remaining capacity, a usable remembered account wins. Otherwise the candidate with greatest capacity wins; ties keep discovery order. An account with unknown capacity is not treated as verified available by this ranking procedure. Remembered account identities live in checkout lastAccounts, separate from credentials. Clearing that preference does not disconnect an account. See account records before changing saved selection data. For OpenAI, enabled managed accounts are considered first, followed by external token, environment JSON and auth-file sources. Managed account identities suppress matching external duplicates; the remaining list is deduplicated. An existing subscription pool is not silently mixed with API-billed credentials. Example: diagnose the wrong account - Open /login and identify the provider, account and enabled state. Do not assume --provider pins one account. - Use /usage to inspect quota before assigning work. A remembered account is useful only while it remains usable. - If testing a different managed account, disable the unintended managed connection through the login interface; do not delete all credentials. - After replacing an external authentication file, run /reload-auth. Restart after changing the launching process's environment. - Inspect /session-info, then send a small non-mutating request. Check the reported route and account rather than asking the model to identify itself. Failure | Recovery | Browser login cancelled | Return to the account interface and start the intended connection again; cancellation is not a successful authorization. | Expired static bearer token | Replace the token or use a complete login with refresh information; reload the matching source. | Revoked OAuth grant | Reconnect the account and review the provider's account/scopes before continuing. | Quota exhausted or cooldown | Inspect reset/capacity information; waiting or choosing another eligible account is different from reauthentication. | Unknown capacity | Inspect usage/service errors; unknown is not positive remaining quota. | Duplicate-looking account | Inspect managed versus external sources and account identities; do not assume identical labels mean different billing accounts. | External credential document formats CODEX_AUTH_JSON and the Codex auth file accept an object with string access_token and account_id, plus optional string refresh_token and id_token. The same object may be nested under tokens, which takes precedence over flat fields. A nonempty array of these documents is accepted, but only its first entry is selected: it is not a way to add multiple accounts. Every array element must decode. Missing required fields, an empty array or malformed JSON reject that source. Use managed connections to register multiple accounts. GROK_AUTH_JSON and the Grok auth file accept a flat object or a one-level nested object with key or access_token strings; key wins when both exist. A valid flat object wins over nested objects. Avoid multiple nested token objects: this is one credential, not an account list. Optional fields are refresh_token, id_token, expires_at, expires_in, oidc_client_id, principal_type, principal_id and email. All are strings except expires_in (integer seconds) and expires_at (ISO timestamp or numeric Unix seconds). Expiry uses expires_at, then load time plus expires_in, then the access token's JWT expiry. A valid environment JSON credential wins over GROK_ACCESS_TOKEN; otherwise the token is tried. The file is discovered separately. These formats describe interoperability with credential-producing programs, not templates to paste into chat. Keep the original private file and its permissions; never put tokens in project configuration or example prompts. Token rotation and recovery outcomes OpenAI and Grok refresh under locks and re-read the credential source to avoid rotating stale tokens concurrently. OpenAI rejects a refresh that changes account identity. Managed OAuth credentials write back to the protected store; external file credentials write back to their original file. Environment JSON refresh is in-memory only: it does not update the parent shell or survive a new process. Static bearer credentials cannot refresh. Grok retains the old refresh token when the provider does not return a replacement. File rotation preserves the supported nested token container and surrounding profile fields. If persistence fails, the refresh reports an error rather than presenting the rotation as successfully saved. Restore access to the original private store/file, then reload or reconnect; do not solve this by making a token file world-readable. OpenAI authentication rejection triggers immediate refresh recovery. If it remains broken, the account's authentication cooldown is 60 seconds. Rate-limit cooldown is separate: successful authentication refresh does not erase quota exhaustion. When all accounts are unavailable, inspect the reported retry/reset time. The CLI can briefly count down before retrying; Esc cancels that wait. Reconnecting does not reset provider quota. Gemini subscription eligibility and endpoint failures - Confirm whether you intend API-key access or Google subscription sign-in. Managed credentials are consulted before environment keys. - For subscription sign-in, finish Google authorization and any validation presented by Code Assist. An OAuth token alone is not proof of model access. - Code Assist loads the current tier and project; without a current tier, it selects an allowed default tier and runs onboarding. Free-tier onboarding does not send a configured project. Other tiers can require one. - If onboarding is ineligible, unfinished or missing a required project, resolve the Google account/project entitlement with your administrator. Repeatedly changing model names or endpoint URLs does not grant eligibility. - After successful setup, inspect the active account/model and make a small request. API-key authentication failures concern the direct Gemini endpoint; subscription setup failures concern Code Assist. Use the endpoint-specific error to distinguish authorization, onboarding and model access. The harness reports provider eligibility and onboarding failures rather than granting organization permissions. If changing to an API key instead, review the separate API billing route before reconnecting. Organization gateway credentials A saved gateway credential takes precedence over local provider discovery. The credential's base URL and WebSocket URL must use the same origin; mismatched or invalid credentials fail rather than silently becoming direct requests. The gateway bearer is not a direct OpenAI, xAI or Claude API key. With a gateway active, no explicit provider or openai uses gateway routing; xai and claude-code use their gateway routes. Other explicit providers require disconnecting the gateway first. Inspect the gateway account label/origin, not just the model's display label. Local-account operations and dictation use their separate credential boundaries. Disconnect the gateway through the login account interface and restart the agent to apply the route change immediately. Disconnection invalidates local credential ownership and removes the saved gateway credential; it is not a promise that the remote server revoked every issued bearer. For compromise or organization-wide revocation, use the gateway administrator's server-side revocation procedure. For an expired/revoked gateway credential, reconnect to the intended organization rather than exporting direct-provider keys and assuming they replace the gateway. Connect and disconnect a gateway from the shell agent-cli gateway connect --url https://gateway.example.com agent-cli gateway status Replace the example with your organization's gateway. The URL must have a host, no embedded username/password, query or fragment, and use HTTPS. HTTP is accepted only for localhost or loopback addresses. Connect prints a verification URL and device code, attempts to open the browser, then waits for authorization. If opening the browser fails, visit the printed URL yourself and enter the code. Only enter it on the expected gateway. After authorization and validation of advertised MCP servers, success prints Gateway connection saved.. The credential lives in ~/.haskell-agent/credentials/gateway.json; do not paste or commit it. The connection also installs gateway MCP entries and invalidates MCP runtimes. A failed authorization or save is not a successful connection: inspect the error, verify the URL and local file permissions, and restart authorization if the code expired or was denied. Status prints Connected to followed by the saved base URL, then Responses WebSocket: and its saved endpoint. This inspects local credentials, not server health or token validity. Not connected to a gateway. means no saved credential; malformed/unreadable credentials produce an error rather than this disconnected result. agent-cli gateway disconnect agent-cli gateway status agent-cli --provider openrouter Successful disconnect prints Gateway connection removed., removes the local gateway credential and gateway MCP entries, and invalidates MCP runtimes. Status should then report disconnected. Start a new direct-provider session with separately configured credentials, as in the OpenRouter example. Disconnect does not revoke the server-side token or manufacture direct-provider credentials; contact the administrator for revocation. Claude Code executable diagnostics The harness uses a nonblank, trimmed CLAUDE_CODE_EXECUTABLE override, otherwise searches PATH for claude. It probes claude auth status --json. “Not found” means install the executable or fix the override; launch failure means inspect executable permissions/path; nonzero status or unreadable JSON means run that diagnostic directly and repair the Claude installation/login. Do not substitute an arbitrary script that prints a success value. Claude Code is an SDK subprocess integration, not a native Responses transport. Native provider fallback excludes it, and OpenAI/xAI/OpenRouter account usage ranking does not select its credentials. Its own login, supported SDK behavior and subscription policy remain authoritative. Account usage and billing Read usage, pacing and reset information /usage For direct OpenAI accounts this fetches ChatGPT Codex usage windows. Each account block can show its short account identifier, plan, remaining percentage, window duration and reset countdown/time. A line such as 20% reserve means 80% of that reported window is used, not that 20% of your monetary balance remains. At zero reserve the wording becomes exhausted until reset in. pacing until is the local account cooldown, which can differ from the provider's reset time. couldn't load usage: reports a fetch error; no rate-limit windows means the response supplied none. Neither means unlimited usage or zero remaining quota. Run /usage again for a new snapshot if an earlier display is stale; provider reporting itself can lag. Gateway sessions report that usage is organization-managed. Claude Code reports its account/subscription and directs you to claude /status for live limits. xAI, OpenRouter and Gemini do not expose account usage through this command's ChatGPT window API. Missing OpenAI credentials or an empty pool are reported explicitly; connect an account instead of treating missing data as available capacity. A subscription login and an API key can use different quotas and billing systems. Check /usage before a long task. Provider account cooldowns can delay work; changing a model is not proof that a rate limit or billing restriction has been removed. For Claude Code, check the provider's current SDK subscription policy linked in Authentication. Technical integration does not override provider terms. Custom endpoints Configure custom Responses-compatible connections in ~/.haskell-agent/models.json. These are model-catalog connections, not additional built-in values for --provider. Select the configured model with --model. The Models guide includes a complete JSON example and explains endpoint compatibility, secret environment variables, and context limits.