Companion to docs/runtimes.md. Where that doc explains the adapter
abstraction (how an executor plugs into the engine), this one answers
the operator question: I want to use provider X. How do I configure
DAP?
Two access modes per provider where it makes sense:
- API mode — single-shot SDK call via the
api-calladapter. Deterministic, no tools, fast, full cost tracking. Use for selection / planning / verification. - CLI mode — agentic loop via a dedicated adapter (
claude-code,gemini-cli, eventuallycodex/aider). Slower, more expensive, has tool use + file edits + MCP. Use for implementation.
Pipelines compose them: cheap API call decides which task to do, expensive CLI does the actual coding.
| Provider | API runtime | CLI runtime | Cost tracking |
|---|---|---|---|
| Anthropic | api-call (provider="anthropic") |
claude-code |
Full (Claude 4.x + cache) |
| OpenAI | api-call (provider="openai") |
codex |
Full (gpt-5, o-series) |
api-call (provider="gemini") |
gemini-cli |
Full (Gemini 2.x/3.x) | |
| GLM (z.ai) | api-call (provider="glm", first-class — see #115) |
— | None (3rd-party) |
| OpenRouter | api-call (provider="openrouter", first-class — see #449) |
— | None (3rd-party; per-model variable) |
| Together / Groq | api-call (provider="openai-compat") |
— | None (3rd-party) |
| Ollama / llama.cpp | http adapter |
bash (ollama run) |
n/a (local) |
openai-compat covers anything that speaks the OpenAI Chat Completions
shape — see the per-provider sections for base_url + env var hints.
Env vars: ANTHROPIC_API_KEY.
Models (cached pricing in _providers/_anthropic.py):
claude-opus-4-7— best, $5/$25 per 1M (in/out)claude-opus-4-6,claude-opus-4-5— $5/$25claude-sonnet-4-6,claude-sonnet-4-5— $3/$15claude-haiku-4-5— $1/$5
API mode runtime_config:
{
"provider": "anthropic",
"model_id": "claude-haiku-4-5",
"max_tokens": 4096,
"effort": "high",
"prompt_cache": true,
"enable_thinking": false
}CLI mode (claude-code): install via npm install -g @anthropic-ai/claude-code
or brew install claude (depending on platform). DAP reads
ANTHROPIC_API_KEY for both modes.
{
"model_id": "claude-opus-4-7",
"binary_path": "/opt/homebrew/bin/claude",
"extra_args": ["--allowed-tools", "Read,Edit,Bash"]
}Verify: curl http://127.0.0.1:7333/runtimes/api-call/health (API) or
/runtimes/claude-code/health (CLI).
Env vars: OPENAI_API_KEY.
Models: gpt-5, gpt-5-codex, gpt-5-mini, gpt-5-nano,
o1, o1-mini, o3, o3-mini (pricing in _providers/_openai.py).
API mode runtime_config:
{
"provider": "openai",
"model_id": "gpt-5-mini",
"max_tokens": 4096,
"temperature": 0.2
}CLI mode: the codex adapter is implemented — it shells out to the
codex CLI (needs the binary on PATH; ~/.codex/ OAuth or
OPENAI_API_KEY). Use API mode if you'd rather not install the CLI.
Env vars:
- API mode (
provider="gemini"viaapi-call):GEMINI_API_KEYonly. - CLI mode (
gemini-cliadapter):GEMINI_API_KEYorGOOGLE_API_KEY— the CLI accepts either.
Models: gemini-3.0-pro, gemini-3.0-flash, gemini-2.5-pro,
gemini-2.5-flash, gemini-2.0-flash.
API mode runtime_config:
{
"provider": "gemini",
"model_id": "gemini-3.0-pro",
"max_tokens": 8192,
"temperature": 0.2,
"thinking_budget": 8192
}CLI mode (gemini-cli): install via npm install -g @google/gemini-cli.
{
"model_id": "gemini-3.0-pro",
"binary_path": "/opt/homebrew/bin/gemini",
"thinking_budget": 8192
}GLM is a first-class registered provider as of #115. The agent only
needs model_id + GLM_API_KEY in env — base_url and
api_key_env are hardcoded inside the provider so you don't repeat
them on every agent.
Env var: GLM_API_KEY (canonical — Settings page picks this up
automatically).
Models: glm-4.5 (flagship coding model on the
/api/coding/paas/v4 endpoint), glm-4.5-air (cheaper/faster),
glm-4.5-flash, codegeex-4. Run
curl -H "Authorization: Bearer $GLM_API_KEY" https://api.z.ai/api/coding/paas/v4/models
for the authoritative list on your account.
runtime_config:
{
"provider": "glm",
"model_id": "glm-4.5",
"max_tokens": 4096,
"temperature": 0.2
}Cost is reported as null — pricing is per-account on z.ai and we
don't ship a table.
Legacy openai-compat recipe (still works, no migration needed
for existing agents):
{
"provider": "openai-compat",
"model_id": "glm-4.5",
"base_url": "https://api.z.ai/api/coding/paas/v4",
"api_key_env": "GLM_API_KEY"
}OpenRouter is a first-class registered provider as of #449. The agent
only needs model_id + OPENROUTER_API_KEY in env — base_url and
identification headers are hardcoded inside the provider. Same recipe
as the glm entry above.
Env var: OPENROUTER_API_KEY (canonical — Settings page picks
this up automatically). Generate at https://openrouter.ai/keys.
Models: OpenRouter is a multi-model gateway — model_id is a
slash-namespaced id like anthropic/claude-3.5-sonnet,
deepseek/deepseek-v3-pro, meta-llama/llama-3.1-405b-instruct.
The full catalogue lives at https://openrouter.ai/models; the
/api/v1/models endpoint returns the authoritative list with current
pricing.
runtime_config:
{
"provider": "openrouter",
"model_id": "anthropic/claude-3.5-sonnet",
"max_tokens": 4096,
"temperature": 0.2
}DAP injects two identification headers on every request (HTTP-Referer
X-Title=DAP) so traffic shows up labelled in the OpenRouter dashboard — no auth or billing impact, just attribution.
Cost is reported as null — pricing is per-model on OpenRouter and we
don't ship a table. If you need cost tracking, read the value off the
generation endpoint that OpenRouter exposes per-request, or use the
http adapter with a response_extractor.
Legacy openai-compat recipe (still works, no migration needed
for existing agents):
{
"provider": "openai-compat",
"model_id": "anthropic/claude-3.5-sonnet",
"base_url": "https://openrouter.ai/api/v1",
"api_key_env": "OPENROUTER_API_KEY"
}Two ways: native http adapter, or shell out via bash.
Via http adapter — best when you want structured cost/token tracking and proper cancellation:
{
"url": "http://localhost:11434/api/generate",
"request_template": {
"model": "{{ runtime_config.model_id }}",
"prompt": "{{ prompt_xml }}",
"stream": false
},
"response_extractor": {
"output": "$.response",
"tokens_used": "$.eval_count"
},
"model_id": "llama3.2"
}No env var needed for local Ollama. For a remote / authenticated
deployment, add an auth: {"type": "bearer", "env": "OLLAMA_API_KEY"}.
Via bash — quick and dirty for ollama run:
{
"command": "ollama run llama3.2 < /dev/stdin"
}(Token counts and cost won't be captured.)
Three concrete agents matching common roles. Drop them into the
dashboard via the New Agent form, or POST /agents directly.
{
"name": "DeveloperJr",
"role": "implementer",
"runtime_id": "api-call",
"runtime_config": {
"provider": "glm",
"model_id": "glm-4.5",
"max_tokens": 4096
},
"prompt_template": "<agent_prompt><role>implementer</role><task>Implement: {{ implementation_notes }}</task></agent_prompt>"
}Needs GLM_API_KEY in the engine's environment. The legacy
openai-compat recipe (with explicit base_url + api_key_env)
still works for existing agents.
Runs via api-call — single-shot, no tools. Best for trivial tasks
where speed and cost matter more than agentic exploration.
{
"name": "DeveloperSenior",
"role": "implementer",
"runtime_id": "claude-code",
"runtime_config": {
"model_id": "claude-opus-4-7",
"extra_args": ["--allowed-tools", "Read,Edit,Bash,Grep"]
},
"prompt_template": "<agent_prompt><role>senior_dev</role><task>{{ implementation_notes }}</task></agent_prompt>"
}Runs via claude-code CLI — gets the full agentic loop. Use for
non-trivial implementation where the agent needs to read files, edit,
run tests.
{
"name": "DeveloperFrontend",
"role": "implementer",
"runtime_id": "gemini-cli",
"runtime_config": {
"model_id": "gemini-3.0-pro",
"thinking_budget": 8192
},
"prompt_template": "<agent_prompt><role>frontend_dev</role><task>Build a React component for: {{ implementation_notes }}</task></agent_prompt>"
}Runs via gemini-cli — Google's agentic CLI, fits front-end work
where the model excels at component generation.
If your service speaks Chat Completions, you don't need code — set
provider="openai-compat" with a base_url and api_key_env. Done.
For everything else (custom JSON shape, non-OpenAI semantics):
-
Create a provider module in
packages/runtimes/src/dap_runtimes/adapters/_providers/. Mirror_anthropic.py: exposeID,DEFAULT_ENV_VAR,validate_config,env_var_for, asynccall,healthcheck. Each function has a 30-line doc-of-truth in the existing modules — copy the shape. -
Register in the registry: add a
ProviderInfoentry toPROVIDER_REGISTRYin_providers/__init__.py. The lazy-load path handles SDK imports — only loaded whenget_provider(id)is called. -
Add pricing table: keep it next to the call site (per-module). Unknown models return
cost_usd=None; known ones get full numbers. -
Tests: copy
tests/smoke/test_provider_openai.pyshape. Mock the SDK client, cover validation + happy path + error mapping. -
Update the dashboard schema: add the new provider value to the
providerselect inapps/dashboard/src/components/agents/runtime-config-schemas.ts.
For a brand new runtime (not just a new LLM provider — a new
executor type, like a sandboxed VM or a different agentic CLI), see
docs/runtimes.md.
runtimes.md— runtime adapter abstraction (engine perspective).packages/runtimes/README.md— per-runtime configuration reference.- Engine
/settingspage — live healthchecks per runtime + per provider env-var presence.