Coding agents
Point coding agents like Pi, OpenCode, and Codex at Ada AI so every request flows through your proxy key, your upstreams, and your routing rules.
Ada AI is OpenAI-compatible, so coding agents that already speak the Chat
Completions API work unchanged — point the agent at https://api.ada.ai/v1,
use a proxy key (sk-rc-…) as the API key, and pick a model you've enabled on
at least one upstream. Codex speaks the Responses API instead; Ada serves that
too.
You need a proxy key first
If you haven't already, mint one in the dashboard under Keys → New key and add an upstream whose model list is synced. See the Quickstart if you're starting from scratch. The key screen shows a ready-to-paste snippet for each agent on this page.
The two pieces you always set
| Setting | Value |
|---|---|
| Base URL | https://api.ada.ai/v1 |
| API key | Your proxy key, sk-rc-… — not a provider key. The proxy already holds your provider keys. |
Put the key in your environment once and let every tool read it from there:
export ADA_API_KEY="sk-rc-..."The model you select must be present on at least one of your enabled upstreams,
or be one of your invokers. Run GET /v1/models to see the union across them
(see Models & routing).
Pi
The @adaai/cli package adds Ada AI to Pi as a first-class provider: it
registers ada, discovers your models from /v1/models (invokers included),
enriches them with capability metadata so reasoning and context limits behave
per model, and keeps the catalog fresh across sessions.
Install it once:
pi install npm:@adaai/cliWith ADA_API_KEY exported, Pi is ready — no config file:
pi -m ada:glm-4.7 "Reply with exactly: ok"Inside a session, /model lists the ada:* models, and /ada forces a
catalog refresh (for example right after you sync a new upstream). Run
pi extensions to confirm the ada provider is loaded.
Signing in from the terminal
The extension also implements Ada's device flow: /login ada
opens your browser, you approve the request and pick the owner (personal or an
organization), and Pi stores the minted key itself. Sign out with
/logout ada.
Device flow availability
/login ada needs the gateway's device-flow routes, which are backed by
Redis. Until that is enabled in production the command returns
404 page not found; use ADA_API_KEY instead.
Keep the key out of your shell profile (macOS)
An exported env var is readable by every process your shell starts. On macOS you can keep the key in Keychain instead and let Pi read it at startup. Store it once:
security add-generic-password -s ada-api-key -a "$USER" -w 'sk-rc-...'Then put the credential in ~/.pi/agent/auth.json, Pi's credential store, and
point its key at a command that reads it back:
{
"ada": {
"type": "api_key",
"key": "!security find-generic-password -s ada-api-key -a \"$USER\" -w"
}
}Pi resolves an auth.json command once per process and caches it, prefers it
over environment variables, and creates the file with 0600 permissions. The
first time Pi reads the item, macOS may prompt to allow access — click
Always Allow.
Without the extension
Plain Pi can talk to Ada AI through a provider entry in
~/.pi/agent/models.json. You list the models yourself and there is no
/login ada, but nothing else is needed:
{
"providers": {
"ada": {
"baseUrl": "https://api.ada.ai/v1",
"api": "openai-completions",
"apiKey": "$ADA_API_KEY",
"models": [
{ "id": "glm-4.7", "name": "GLM 4.7" },
{ "id": "Qwen/Qwen3.6-35B-A3B-FP8", "name": "Qwen 3.6 35B A3B", "reasoning": true }
]
}
}
}The file reloads every time you open /model. apiKey accepts "$VAR", a
"!command" whose stdout is the key, or a literal. If an upstream rejects the
developer role or reasoning_effort, add
"compat": { "supportsDeveloperRole": false, "supportsReasoningEffort": false }
to the provider so Pi falls back to a system message and omits the field.
OpenCode
OpenCode reads providers from ~/.config/opencode/opencode.json (global) or
opencode.json in your project root. Add an ada provider backed by the
@ai-sdk/openai-compatible package — the package OpenCode uses for any
OpenAI-compatible API:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"ada": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ada AI",
"options": {
"baseURL": "https://api.ada.ai/v1",
"apiKey": "{env:ADA_API_KEY}"
},
"models": {
"Qwen/Qwen3.6-35B-A3B-FP8": { "name": "Qwen 3.6 35B A3B" },
"moonshotai/Kimi-K2.7-Code": { "name": "Kimi K2.7 Code" },
"glm-4.7": { "name": "GLM 4.7" }
}
}
}
}| Field | Notes |
|---|---|
ada | The provider ID — any string. You'll select models as ada/<model-id>. |
npm | The AI SDK package. @ai-sdk/openai-compatible works for any OpenAI-compatible API. |
name | Display name in the /models picker. |
options.baseURL | The Ada AI endpoint, https://api.ada.ai/v1. |
options.apiKey | Your proxy key. {env:VAR} reads it from the environment at load time; an unset variable becomes an empty string, so export it before starting OpenCode. |
models | A map of model IDs (from GET /v1/models, invoker names included) to display names. |
You can also run /connect in the TUI and paste the key; it's stored in
~/.local/share/opencode/auth.json.
Select a model with /models and pick ada/<model-id>, set a default in the
config with "model": "ada/glm-4.7", or override for one run:
opencode run -m "ada/glm-4.7" "Reply with exactly: ok"Codex
OpenAI's Codex CLI speaks the Responses API, and its custom providers accept
only wire_api = "responses". Ada exposes POST /v1/responses for exactly
this: the request is routed like every other call (your upstreams, invokers,
a,b chains, failover, usage), passed through unchanged to upstreams that
implement the Responses API natively (OpenAI, Azure OpenAI), and translated to
chat completions for every other upstream, with the answer synthesised back
into Responses events. A chain like gpt-6-astra,claude-fable-5-1 fails over
across both kinds.
Custom providers are only honoured in the user-level file:
model_provider = "ada"
model = "gpt-6-astra" # any model your upstreams serve, an invoker name, or "a,b"
[model_providers.ada]
name = "Ada AI"
base_url = "https://api.ada.ai/v1"
env_key = "ADA_API_KEY"
wire_api = "responses"
request_max_retries = 2 # Ada already fails over across upstreams
stream_idle_timeout_ms = 300000Then run codex with ADA_API_KEY exported. Codex's "Sign in with ChatGPT"
is not involved and is not supported through Ada.
What to expect:
- Stateless. Ada stores nothing:
storeis forced tofalseon the way out andprevious_response_idis refused with a400. Codex sends the full input each turn for custom providers, so this does not affect it. - Translation limits. OpenAI's built-in tools (
web_search,file_search,computer_use, …) have no chat-completions equivalent; a request carrying them to a chat-only upstream gets a400naming the tool. - Headers and usage are the same as chat completions:
X-Ada-Resolved-Model,X-Ada-Attempts,X-Ada-Failover-Attempts; tokens land in usage from the Responsesusageblock.
A one-shot check outside Codex:
curl -s https://api.ada.ai/v1/responses \
-H "Authorization: Bearer $ADA_API_KEY" -H 'Content-Type: application/json' \
-d '{"model":"gpt-6-astra","input":"Say OK."}' | jq '.output[-1].content[0].text, .usage'Recommended models for coding
Ada AI exposes many models across upstreams; these are well-suited to agentic coding tasks and accept the standard chat-completions shape:
| Model | Strengths |
|---|---|
Qwen/Qwen3.6-35B-A3B-FP8 | Reasoning-heavy refactors. Use a thinking level (high, max) when the task needs planning. |
moonshotai/Kimi-K2.7-Code | Strong tool-calling and long-context code comprehension. |
swiss-ai/Apertus-70B-Instruct-2509 | Large instruction-following model for broad tasks. |
glm-4.7 | Fast, general-purpose. |
An invoker is often the better choice than any single model: it gives the agent
one stable name (provider-best, say) while you change the chain behind it
in the dashboard. See Models & routing.
The exact set depends on which upstreams you've enabled and synced. Run
curl https://api.ada.ai/v1/models -H "Authorization: Bearer $ADA_API_KEY"
to see exactly what your key can address right now.
Verify it works
A one-shot check that the agent reaches Ada AI and routes correctly — the
model echoed back in the response confirms the proxy selected your upstream:
pi -m ada:glm-4.7 --no-tools --no-session --print "Reply with exactly: ok"Troubleshooting
model not found / 400 from the proxy
The model ID isn't on any of your enabled upstreams. Either the upstream needs
Sync models run (in the dashboard, or POST /me/upstreams/{id}/sync-models),
or the ID doesn't match what that upstream exposes. Model IDs are exact and
case-sensitive — Qwen/Qwen3.6-35B-A3B-FP8 is not qwen3.6-35b. In Pi, run
/ada after syncing so the catalog picks the model up. See
Models & routing.
401 / invalid_api_key
You're using a provider key instead of an Ada AI proxy key, or the proxy key
was revoked. Proxy keys start with sk-rc-. Mint a new one under Keys → New
key (see API keys).
/login ada says 404 page not found
The gateway's device-flow routes are not enabled. Export ADA_API_KEY with a
key from the dashboard instead; the extension picks it up on the next start.
Reasoning leaks into the response, or developer role errors
Some OpenAI-compatible upstreams don't understand the developer role or the
reasoning_effort field that coding agents send by default. With the Pi
extension this is handled per model from the catalog metadata; with a manual
models.json entry, add the compat flags shown above. The proxy passes
these through unchanged.
Requests hit the wrong upstream
Routing follows upstream priority, descending — the highest number is tried first, and the proxy fails over to the next on errors it classifies as retryable. If two upstreams expose the same model, raise the priority on the one you want first, or make an invoker whose member order says exactly what you want. See Models & routing.
Next steps
Chat completions API
The endpoint Pi and OpenCode call under the hood — streaming, tools, and the full request/response reference.
Models & routing
How model IDs are discovered across upstreams, and how priority, invokers, and failover pick one.
API keys
Scoping proxy keys to yourself or an organization, and rotating them.
CLI authentication
The device flow behind /login ada, for tools that mint their own key.