Skip to content
AGH RuntimeAgents

Providers

Built-in provider IDs, launch commands, config overrides, and custom provider setup for AGH agents.

Audience
Operators running durable agent work
Focus
Agents guidance shaped for scanability, day-two clarity, and operator context.

A provider is the ACP-compatible command AGH launches for an agent. The provider owns the actual LLM integration. AGH owns definition resolution, process lifecycle, workspace boundaries, permissions, MCP server wiring, and event persistence.

Provider IDs appear in AGENT.md:

---
name: implementation
provider: codex
---
You implement scoped changes and verify them before handoff.

Or they can be selected globally:

[defaults]
agent = "general"
provider = "claude"

Built-in providers

The built-in registry lives in internal/config/provider.go.

Provider IDHarnessRuntime providerCommandmodels.defaultAuth modeCredential target
claudeacpclaudenpx -y @agentclientprotocol/claude-agent-acp@latestclaude-sonnet-4-6native_cliprovider login
codexacpcodexnpx -y @zed-industries/codex-acp@latestgpt-5.4native_cliprovider login
geminiacpgeminigemini --acpgemini-3.1-pro-previewnative_cliprovider login
opencodeacpopencodenpx -y opencode-ai@latest acpnonenative_cliprovider login
copilotacpcopilotcopilot --acp --stdiononenative_cliprovider login
cursoracpcursorcursor-agent acpnonenative_cliprovider login
kiroacpkirokiro-cli-chat acpnonenative_cliprovider login
blackboxacpblackboxblackbox --experimental-acpnonenative_cliprovider login
clineacpclinenpx -y cline@latest --acpnonenative_cliprovider login
gooseacpgoosegoose acpnonenative_cliprovider login
hermesacphermeshermes acpnonenative_cliprovider login
junieacpjuniejunie --acp truenonenative_cliprovider login
kimi-cliacpkimi-clikimi acpnonenative_cliprovider login
openclawacpopenclawopenclaw acpnonenative_cliprovider login
openhandsacpopenhandsopenhands acpnonenative_cliprovider login
qoderacpqodernpx -y @qoder-ai/qodercli@latest --acpnonenative_cliprovider login
qwen-codeacpqwen-codenpx -y @qwen-code/qwen-code@latest --acp --experimental-skillsqwen3.6-plusnative_cliprovider login
pipi_acpanthropicnpx -y pi-acp@latestclaude-opus-4-7native_cliPi /login
openrouterpi_acpopenrouternpx -y pi-acp@latestopenai/gpt-5.4bound_secretOPENROUTER_API_KEY
zaipi_acpzainpx -y pi-acp@latestglm-4.6bound_secretZAI_API_KEY
moonshotpi_acpkimi-codingnpx -y pi-acp@latestkimi-k2-thinkingbound_secretKIMI_API_KEY
vercel-ai-gatewaypi_acpvercel-ai-gatewaynpx -y pi-acp@latestanthropic/claude-opus-4-7bound_secretAI_GATEWAY_API_KEY
xaipi_acpxainpx -y pi-acp@latestgrok-4-fast-non-reasoningbound_secretXAI_API_KEY
minimaxpi_acpminimaxnpx -y pi-acp@latestMiniMax-M2.1bound_secretMINIMAX_API_KEY
mistralpi_acpmistralnpx -y pi-acp@latestdevstral-medium-latestbound_secretMISTRAL_API_KEY
groqpi_acpgroqnpx -y pi-acp@latestopenai/gpt-oss-120bbound_secretGROQ_API_KEY

Authentication modes

Provider authentication is explicit. AGH does not infer that every provider needs an AGH-managed API key.

ModeOwnerRuntime behavior
native_cliThe provider CLIAGH launches the provider without preflight key checks. The CLI uses its own login/session store.
bound_secretAGH config or AGH VaultAGH resolves credential_slots and injects the bound values into the provider subprocess.
noneNo authentication at AGH sideAGH launches the provider without native auth diagnostics or secret injection.

Direct ACP providers and the direct pi provider default to native_cli. Pi-backed API-key wrappers default to bound_secret because their public provider contract is an API key managed by AGH. Custom providers with credential_slots default to bound_secret; custom providers without slots default to native_cli unless auth_mode = "none" is set explicitly.

native_cli providers cannot define credential_slots. If you intentionally want AGH to inject a key into a native ACP command, set auth_mode = "bound_secret" in the provider override and define the slots there. This keeps secret injection opt-in and prevents daemon shell variables from silently overriding a provider's own login state.

Provider config fields

Provider overrides and custom providers are configured in config.toml.

FieldTypeRequiredRuntime behavior
commandstringyes for custom providersLaunch command for the ACP subprocess. Overrides a built-in command when set.
display_namestringnoOperator-facing label shown in settings and provider pickers.
modelstablenoNested model config block (models.default, models.curated, models.discovery). See "Provider models".
harnessstringnoacp for direct ACP launch or pi_acp for providers launched through the Pi ACP adapter. Defaults to acp.
runtime_providerstringnoDownstream provider id used by harnesses such as Pi. Defaults to the AGH provider id.
transportstringnoOptional Pi model-provider API family hint for custom providers.
base_urlstringnoOptional Pi model-provider base URL for custom gateways.
auth_modestringnonative_cli, bound_secret, or none. Defaults from configured credential slots.
none_securitystringnoSafety rationale for auth_mode = "none": local_transport, external_identity, or public_readonly.
env_policystringnofiltered strips secret-shaped daemon env vars; isolated keeps only an operational allowlist.
home_policystringnooperator uses the daemon user's home; isolated uses $AGH_HOME/providers/<provider>.
auth_status_commandstringnoOptional native CLI status probe used by agh provider auth status.
auth_login_commandstringnoOptional native CLI login command used by agh provider auth login.
credential_slotsarraynoBound launch-time secrets. Allowed only with auth_mode = "bound_secret".
mcp_serversarraynoProvider-level MCP servers merged before agent-level MCP servers.

auth_mode = "none" is an explicit No auth required contract, not an authenticated state. Set none_security to describe why the provider is safe without credentials: local_transport for local-only transports, external_identity when another system authenticates the caller, or public_readonly for public read-only providers. No-auth providers cannot define credential_slots, auth_status_command, or auth_login_command; AGH rejects those combinations at config load time.

AGH overlays provider config on top of a built-in provider when the name matches. Unknown provider names are accepted only when they have a [providers.<name>] entry.

Built-in provider aliases are intentionally small and resolve before launch. Common aliases such as claude-code, ai-gateway, vercel, kimi, glm, x.ai, grok, open-code, and qwen resolve to their canonical provider IDs. Provider-scoped model aliases resolve the same way: sonnet, opus, and haiku under claude; gpt5, gpt-5, and mini under codex; kimi under moonshot; glm under zai; grok under xai; qwen under qwen-code; and opus under vercel-ai-gateway. AGH stores and displays the resolved provider/model IDs in session diagnostics and catalog rows.

The old providers.<id>.aliases config key was removed for v1. Reference providers by canonical name only; config files that set aliases = [...] under a provider are rejected during load.

The flat keys default_model, supported_models, and supports_reasoning_effort are no longer accepted. Config that still sets them is rejected at load time with a deterministic hard-cut error that names the exact path. Move every value into the nested [providers.<id>.models] block below.

Provider models

Each provider declares pre-session model defaults and curated metadata under [providers.<id>.models]. Pre-session model selection is served by the daemon-owned model catalog. The catalog merges builtin defaults, the operator config, the optional models.dev enrichment source, live provider discovery sources, and extension model sources, then projects them through HTTP, UDS, CLI, the OpenAI-compatible projection, the Host API, and the web. Active ACP configOptions continue to govern model and reasoning controls inside a running session.

FieldTypeRequiredRuntime behavior
models.defaultstringnoDefault model when an AGENT.md omits model. Free-form: it does not need to appear in models.curated.
models.curatedarraynoCurated entries shown in pickers and projected as config rows in the catalog. Not an allowlist.
models.curated[].idstringyes per entryProvider model identifier sent to the runtime. Must be unique inside the provider.
models.curated[].display_namestringnoOptional human label.
models.curated[].context_windowintegernoContext window in tokens.
models.curated[].max_input_tokensintegernoMaximum input tokens.
models.curated[].max_output_tokensintegernoMaximum output tokens.
models.curated[].supports_toolsboolnoWhether the model supports tool calls.
models.curated[].supports_reasoningboolnoWhether the model supports reasoning effort.
models.curated[].reasoning_effortsarraynoAllowed reasoning levels (minimal, low, medium, high, xhigh). Blank entries are rejected.
models.curated[].default_reasoning_effortstringnoPer-model default reasoning level. Must appear in reasoning_efforts when both are set.
models.curated[].cost_input_per_millionnumbernoDisplay-only input cost per million tokens.
models.curated[].cost_output_per_millionnumbernoDisplay-only output cost per million tokens.
models.discovery.enabledboolnoEnables the side-effect-free discovery adapter for this provider. Defaults to false for providers without a built-in safe path.
models.discovery.commandstringrequired for some providersSide-effect-free discovery command (mutually exclusive with endpoint unless the adapter documents both).
models.discovery.endpointstringrequired for some providersSide-effect-free discovery endpoint URL.
models.discovery.timeoutstringnoPer-discovery timeout duration (defaults to the model catalog timeout).

Discovery uses the resolved provider auth, env, and home policy and never creates an ACP session. When a discovery path is unavailable or fails, the model catalog records a source status and falls back to stale or lower-priority rows; session creation never depends on a successful discovery.

Session creation can override provider, model, and reasoning_effort for one launch. model is free-form: models.curated is operator metadata, not an allowlist, so a manual model ID outside the curated list is accepted. Reasoning effort is validated against minimal, low, medium, high, and xhigh. The effective model catalog uses explicit source/config reasoning_efforts when they exist, supplies the canonical effort list when a model advertises supports_reasoning without levels, and applies the same fallback to known GPT and Claude model families when upstream metadata is incomplete; explicit supports_reasoning=false disables that fallback. After the session starts, AGH switches to active ACP configOptions (or legacy session/set_model when the agent does not advertise config options); the catalog informs pre-session selection, while live ACP options govern controls inside the running session.

Native provider auth state belongs to the provider. Run the provider's own login command, such as claude auth login, codex login, opencode auth login, or Pi's /login, outside AGH or through a configured auth_login_command. The built-in claude, codex, opencode, and pi providers expose those login commands through agh provider auth login <provider>. By default, that command executes the configured login command locally and attaches the terminal when stdin, stdout, and stderr are TTYs, so OAuth URLs and provider prompts remain visible. Use agh provider auth login <provider> --print-command when automation needs one copyable shell command without executing it, --no-tty for deterministic non-interactive runs, and --timeout when scripts need a bounded login attempt. When a provider uses home_policy = "isolated", the resolved command includes the required HOME/provider-home environment prefix so the native login writes credentials where AGH will read them. Remote HTTP/UDS surfaces never run login commands; they only run non-interactive auth_status_command probes. Wrapped API-key providers use their configured credential_slots instead of Pi login. Custom providers should set auth_mode to match the runtime's real authentication contract.

Override a built-in provider

Use this when you need to pin a different adapter command or change the default model used by agents that omit model.

[providers.claude]
auth_mode = "native_cli"
auth_status_command = "claude auth status"
auth_login_command = "claude auth login"

[providers.claude.models]
default = "claude-sonnet-4-6"

[[providers.claude.models.curated]]
id = "claude-sonnet-4-6"
display_name = "Claude Sonnet 4.6"

[[providers.claude.models.curated]]
id = "claude-haiku-4-5"
display_name = "Claude Haiku 4.5"

[[providers.claude.mcp_servers]]
name = "github"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
secret_env = { GITHUB_TOKEN = "env:GITHUB_TOKEN" }

Only non-empty scalar fields replace the built-in values. MCP servers merge by name.

Configure wrapped API-key providers

OpenRouter, z.ai, Moonshot/Kimi, Vercel AI Gateway, xAI, MiniMax, Mistral, and Groq are built-in wrapped providers. Operators select them directly, and AGH uses Pi only as the underlying ACP adapter. These built-ins default to auth_mode = "bound_secret" with required provider-key slots. Override the slot when you want AGH Vault, rather than the daemon environment, to own the launch-time credential.

[providers.openrouter]
display_name = "OpenRouter"
harness = "pi_acp"
auth_mode = "bound_secret"
runtime_provider = "openrouter"
command = "npx -y pi-acp@latest"

[providers.openrouter.models]
default = "openai/gpt-5.4"

[[providers.openrouter.models.curated]]
id = "openai/gpt-5.4"
display_name = "OpenAI GPT-5.4"

[[providers.openrouter.credential_slots]]
name = "api_key"
target_env = "OPENROUTER_API_KEY"
secret_ref = "env:OPENROUTER_API_KEY"
kind = "api_key"
required = true

For AGH-managed encrypted storage, use a vault:providers/<provider>/<slot> ref and save the value through the settings API or web provider editor. The <provider> and <slot> segments are lowercase provider/slot identifiers using letters, numbers, hyphens, underscores, or dots; path traversal, whitespace, and arbitrary vault paths are rejected.

[[providers.openrouter.credential_slots]]
name = "api_key"
target_env = "OPENROUTER_API_KEY"
secret_ref = "vault:providers/openrouter/api-key"
kind = "api_key"
required = true

AGH never exposes provider secret values through settings reads. Status surfaces report only whether the bound credential is present.

Add a custom provider

A custom provider needs an ACP-compatible command. AGH will launch it the same way it launches the built-ins.

[providers.local-agent]
command = "local-agent --acp --stdio"
auth_mode = "native_cli"
auth_status_command = "local-agent auth status"
auth_login_command = "local-agent auth login"

[providers.local-agent.models]
default = "local-default"

[[providers.local-agent.models.curated]]
id = "local-default"
display_name = "Local Default"

[[providers.local-agent.mcp_servers]]
name = "filesystem-index"
command = "local-index-mcp"
args = ["serve"]

Then point an agent at the custom provider:

---
name: local-operator
provider: local-agent
permissions: approve-reads
---
You inspect this repository with the local agent runtime.
Report risks and cite exact files.

If the custom provider has no authentication at all, set auth_mode = "none" and document the reason with none_security:

[providers.local-readonly]
command = "local-readonly-agent --acp"
auth_mode = "none"
none_security = "local_transport"

No-auth providers render as No auth required in status, doctor, web, and CLI output. They cannot define credential slots or login/status commands. If a custom provider requires an AGH-managed key, use auth_mode = "bound_secret" and define credential_slots:

[providers.team-gateway]
command = "team-gateway acp"
auth_mode = "bound_secret"

[[providers.team-gateway.credential_slots]]
name = "api_key"
target_env = "TEAM_GATEWAY_API_KEY"
secret_ref = "vault:providers/team-gateway/api-key"
kind = "api_key"
required = true

Command parsing

Provider commands are parsed with shell-style quoting, then launched without a shell. That means:

  • quoted arguments are preserved
  • shell expansion is not performed
  • the executable must be available on the daemon process PATH
  • npx-based built-ins can download and run their adapter package through the local Node toolchain

For example, this is valid:

[providers.reviewer]
command = "reviewer-acp --profile \"team default\""

But shell-only behavior is not applied:

[providers.bad-example]
command = "MY_FLAG=1 reviewer-acp"

Set environment variables before starting the daemon instead.

Models and authentication

model and models.default are resolved and exposed as runtime metadata. Direct acp providers receive the normal ACP startup flow. Native pi sessions receive the resolved runtime_provider/model through ACP model selection. Wrapped Pi-backed API-key providers receive session-local Pi settings.json and models.json so Pi can run with the AGH-selected provider, model, and injected credential while the operator-facing provider remains OpenRouter, z.ai, Moonshot/Kimi, Vercel AI Gateway, xAI, MiniMax, Mistral, or Groq.

The practical rule is:

  • use model in AGENT.md when you want AGH metadata and provider-specific wrappers to agree on the intended model
  • use native_cli when the provider command owns login state, session files, or browser/device auth
  • use bound_secret plus credential_slots when AGH should inject a specific API key into the subprocess
  • use env: refs for service-manager-owned secrets and vault:providers/<provider>/<slot> refs for AGH-managed encrypted provider credentials

MCP server merge order

MCP servers can be declared at several levels. Startup uses this order:

  1. Top-level mcp_servers from resolved config
  2. Provider mcp_servers
  3. Agent mcp_servers
  4. Active skill MCP servers

Config/provider/agent merges are field overlays by server name. Agent-local mcp.json sidecars replace same-name inline servers as whole objects before that cross-scope merge happens. Configured MCP env values are passed through as literal strings. Pi-backed providers are launched through pi-acp; current Pi ACP support does not wire AGH MCP server declarations into Pi's own MCP configuration.

Choosing a provider

Use the provider that already owns your credentials and preferred operating path:

If you useStart with
Claude Codeclaude
Codexcodex
Gemini CLIgemini
OpenCodeopencode
GitHub Copilot CLIcopilot
Cursor Agentcursor
Kiro CLIkiro
BLACKBOX AIblackbox
Clinecline
Goosegoose
Hermeshermes
Juniejunie
Kimi CLIkimi-cli
OpenClawopenclaw
OpenHandsopenhands
Qoder CLIqoder
Qwen Codeqwen-code
Pipi
OpenRouteropenrouter
z.ai / GLMzai
Moonshot / Kimi APImoonshot
Vercel AI Gatewayvercel-ai-gateway
xAIxai
MiniMaxminimax
Mistralmistral
Groqgroq
A local or team ACP wrappera custom provider

Then keep provider-specific behavior in the provider command or provider config, and keep the agent's role, permissions, MCP servers, and startup prompt in AGENT.md.

  • Agent Definitions explains the AGENT.md fields that reference providers.
  • Spawning shows exactly how the resolved provider command becomes a running ACP process.
  • Provider Model Catalog covers the daemon-owned catalog, sources, refresh lifecycle, OpenAI-compatible projection, and extension model.source.
  • CLI agent reference lists the current agh agent inspection commands.
  • agh provider models CLI inspects and refreshes the catalog without a UI.

On this page