Skip to content
qqthe agent runtime
DocsProviders and credentials

Providers and credentials

Connect OpenAI, Anthropic, Google, xAI, Codex, Bedrock, or a gateway, and where credentials are kept.

A provider is where model requests go. A credential is how QQ authenticates there. QQ keeps credentials in your operating system’s secret store and never writes them into configuration.

These exist without any configuration. Store a credential once and use any of their models.

Provider idStore a credentialEnvironment variableNotes
openaiqq auth login openaiOPENAI_API_KEYResponses API
anthropicqq auth login anthropicANTHROPIC_API_KEYMessages API; prompt caching used automatically
googleqq auth login googleGEMINI_API_KEY or GOOGLE_API_KEY (GEMINI_API_KEY wins when both are set)key sent in the x-goog-api-key header, never the URL; tool schemas are reduced to Gemini’s schema subset (unsupported JSON Schema keywords such as additionalProperties, $ref, and oneOf are dropped) so MCP tools with rich schemas still declare
xaiqq auth login xai or qq auth login xai --oauthXAI_API_KEYOAuth uses a device code and refreshes itself
openai-codexqq auth login openai-codex or qq auth login openai-codex --device-auth—ChatGPT Plus/Pro/Business subscription; loopback browser by default, device code when explicitly selected
bedrockAWS credential chainAWS_PROFILE, AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, web identity, container credentialsConverse API; needs a region, see below
bedrock-mantleAWS credential chain or ApiKeyas aboveOpenAI/Anthropic wire protocols on Bedrock

Resolution order for a built-in: an explicit api_key: in providers, then the stored credential PROVIDER/default, then the environment variable.

Terminal window
qq auth login anthropic # prompts, no echo
printenv ANTHROPIC_API_KEY | qq auth login anthropic # from a pipe
qq auth login openai --profile work # a second key under openai/work
qq auth list # names, backend, kind, endpoint; never secrets
qq auth status openai/default
qq auth logout openai/default

qq auth login accepts only the built-in provider ids above. For anything else use qq auth set NAME, which stores an arbitrary named secret you can reference as Stored("NAME"):

Terminal window
qq auth set gateway/default --endpoint https://llm.example.com

--endpoint binds the secret to one host so a misconfigured base_url can never send it elsewhere.

PlatformBackend
LinuxSecret Service (GNOME Keyring, KWallet, KeePassXC…)
macOSKeychain
WindowsCredential Manager; entries above its size limit go to a DPAPI-encrypted file bound to your user and machine

If no keyring is available (a container, a headless server), pass --allow-file to store a user-only plaintext file under the data directory. Prefer environment variables in CI.

PROVIDER/PROFILE. default is what the built-in providers use unless you declare otherwise:

providers: {
"openai": OpenAi(api_key: Stored("openai/work")),
"openai-codex": OpenAiCodex(profile: "work"),
}

QQ ships a catalog with context windows, output limits, and pricing so cost tracking and --max-cost-usd work out of the box. Any model not listed can still be used by declaring it under the provider’s models.

ProviderRoutes
openaigpt-6.1-sol, gpt-6-sol, gpt-6-luna, gpt-6-astra, gpt-5.6, gpt-5.6-sol, gpt-5.6-luna, gpt-5.6-terra, gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.4-nano, gpt-5.3-codex-spark, gpt-5.2, gpt-5-mini, gpt-5-nano, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-4o, gpt-4o-mini
openai-codexthe OpenAI routes your subscription includes
anthropicclaude-opus-5-5, claude-opus-5, claude-sonnet-5, claude-fable-5, claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-opus-4-5, claude-sonnet-4-6, claude-sonnet-4-5, claude-haiku-4-5
googlegemini-3.6-flash, gemini-3.5-flash, gemini-3.5-flash-lite, gemini-3.1-pro-preview, gemini-3.1-flash-lite, gemini-3-flash-preview, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite
xaigrok-4.7, grok-4.6, grok-4.5, grok-4.3
bedrock, bedrock-mantlethe same Anthropic and OpenAI models under their Bedrock ids

The TUI’s /models lists authenticated providers and includes live discovery. For Codex, a successful response replaces implicit bundled entries: hidden or retired models no longer linger in the picker. Explicit models declarations and the currently selected route remain visible; neither grants account access. Failed discovery falls back to the bundled catalog. Results are cached for five minutes. For discovery QQ sends the Codex client version it was built for, not its own version or that of a Codex CLI you have installed: 0.159.0, the latest stable upstream release when GPT-6.1 Sol shipped.

GPT-6 Sol/Luna support none, low, medium, high, xhigh, and max. GPT-6 Astra supports low through max, but not none or minimal. Direct Claude Sonnet 5 / Opus 4.7 and 4.8 support low, medium, high, xhigh, and max; Opus/Sonnet 4.6 omit xhigh, and Opus 4.5 stops at high. The picker shows only the selected model’s advertised choices. Unknown models show only Configured and Default. Configured inherits the configuration/profile setting; Default explicitly overrides that setting and omits effort from the provider request. Neither is the explicit none level (which disables reasoning only on models that advertise it). Anthropic uses output_config.effort, never an OpenAI reasoning field.

The complete stack uses protocol 32 and session-store schema 44 for the new effort vocabulary, replay envelopes, persisted checkpoint notices, the prune watermark and side questions; older binaries cannot open upgraded stores. Back up the store before upgrading if rollback is needed.

Anthropic discovery now follows bounded pagination before replacing implicit bundled model entries, preserving configured routes and failure fallback. GPT-6 Sol/Luna pricing is currently unknown in the bundled catalog; cost-budget behavior therefore remains conservative. Codex uses the conservative bundled 272K context limit, distinct from the direct API’s 1.05M limit.

Opus 5.5 supports low, medium, high, xhigh, and max. QQ retains signed thinking and redacted blocks for successful tool turns, including session restart. Replay is bounded and bound to the endpoint, semantic headers, model, conversation prefix and assistant content. Changed prompts/tools, compaction, model changes or invalid/incomplete turns omit incompatible replay. Always-on thinking is left to the provider; QQ does not send disabled/manual thinking or forced tool choice. Authenticated account access has not been smoke-tested; deterministic loopback coverage verifies the signed tool loop and SQLite reopen path.

Live Codex and Anthropic effort capabilities override implicit bundled ladders; explicit model declarations retain their configured metadata. Older GPT-5 mini/ nano, GPT-5.2/5.4, and GPT-5.6 use separate bundled ladders rather than one global set. Unknown discovery capabilities fall back to known route metadata.

(
version: 1,
model: "bedrock/anthropic.claude-sonnet-5",
providers: {
"bedrock": AmazonBedrock(region: "us-east-1", auth: Aws(DefaultChain)),
},
)

auth is Aws(DefaultChain), Aws(Profile("NAME")), or a Bedrock API key ApiKey(Env("BEDROCK_API_KEY")). Profiles that use credential_process are rejected: QQ cannot guarantee the subprocess terminates on a timeout.

Bedrock Mantle exposes the same models over the OpenAI Responses, OpenAI Chat Completions, or Anthropic Messages protocols:

providers: {
"bedrock-mantle": AmazonBedrockMantle(region: "us-east-1", api: AnthropicMessages, auth: Aws(DefaultChain)),
}

Both need the default build; --no-default-features builds refuse Bedrock with an error naming the missing provider-bedrock feature.

Anything that speaks one of the four wire protocols works as a Custom provider:

providers: {
"local": Custom(
connection: (
base_url: "http://127.0.0.1:11434/v1", // loopback may use http
api: OpenAiChatCompletions,
auth: NoAuth,
),
models: { "qwen3:32b": (name: "Qwen 3 32B", context_window: 32768) },
),
"gateway": Custom(
connection: (
base_url: "https://llm.example.com/v1",
api: AnthropicMessages,
auth: Bearer(Env("GATEWAY_TOKEN")),
),
),
"litellm": LiteLlm(
connection: (base_url: "https://litellm.example.com/v1", api: OpenAiChatCompletions, auth: ApiKey(Env("LITELLM_API_KEY"))),
),
}

Non-loopback http:// is rejected unless policy.require_https: false. Model routes are local/qwen3:32b; declare each model you want to use.

Terminal window
qq auth status anthropic/default # stored? which backend? bound endpoint?
qq ask --model anthropic/claude-sonnet-5 "Reply with pong"

If the second command fails, Troubleshooting lists each message and its fix.