Catalog
Native wires are driven directly by an adapter written for that agent. ACP
agents share one adapter that speaks the
Agent Client Protocol.
Capability matrix
What each adapter reports afteropen. Read it from
session.info().details.capabilities at runtime; never hardcode this table.
- handshake: the ACP
initializeresponse says whether the agent takes images, loads sessions, and accepts steering. Cursor, for example, reports images and resume; Antigravity’s server reports no steer. - on first sight: ACP has no handshake flag for these. The capability is
added, with a
SessionUpdated, the first time the agent sends one.
UnsupportedFeature instead of misbehaving.
TurnEnded.usage (the turn’s token counts) is not a capability: claude,
codex, opencode, pi, and antigravity over agy fill it; ACP agents leave it
None. A compaction turn carries the summary’s tokens on opencode and none on
pi, which reports no model call for it.
Config options by agent
On claude, codex, and opencode each
model choice also carries that model’s
own effort and fast in options (opencode: effort only). Other agents
leave it empty.
Answers by agent
WhatAnswer::Deny { message } and Answer::Cancel send. Where the wire
takes no message, the message is dropped.
Per-agent notes
Claude Code
Claude Code
The fullest native adapter.
fast appears when the selected model reports
supportsFastMode; switching it resumes the process under the hood with the
same Session handle and conversation. Rollback can restore files. A tool a
permissions.deny rule or the CLI’s own mode refuses ends Denied; a hook’s
refusal still shows as Failed (the CLI sends no denial frame for it).
Client MCP servers ride the mcp_set_servers control request after
initialize, so their header and env values never appear in argv. A server
that fails to connect, or a CLI that refuses the request, is a Warning
diagnostic. While a declared server is still connecting (up to 30 s for an
unreachable one) the CLI holds later input, so the first turn and the answers
to cancel, configure and usage requests wait for it. A running Bash reports
ToolProgress only when the CLI runs with CLAUDE_CODE_CONTAINER_ID or
CLAUDE_CODE_REMOTE set (2.1.283); a subagent’s Bash sent none when probed.
An output schema rides --json-schema; the CLI’s StructuredOutput call
arrives as a text message of its own holding the JSON, after any text the
model wrote first.Codex
Codex
Opts into the app-server’s experimental API. Approval policy and sandbox
switch live.
mode: plan is codex’s plan collaboration mode and keeps the
last approval policy; to leave it, select an approval policy and prompt
again. Images ride as localImage items. Client MCP servers ride as
launch overrides (stdio and HTTP; no SSE). Header and env values ride env
vars the overrides name, never argv. codex forwards stdio MCP env by name, so
a declared name is also set on codex itself; PATH, or a name codex’s
environment already has with another value, is refused. Two server names that differ
only by case or -/_ are refused too: they would share env vars. rollback maps to
thread/revert; files are never restored. Questions are translated
defensively but the capability stays off until observed live. MCP progress
maps to ToolProgress, but 0.154.0 did not forward a stdio server’s progress
when probed. probe opens no thread: it reads config/read and
skills/list, so the user’s MCP servers and hooks never start. It may miss
skills codex loads about 0.5 s after it starts (0.154.0: marketplace plugins;
forceReload does not wait for them). An output schema rides every
turn/start as outputSchema; the model API takes only strict schemas
(every object additionalProperties: false) and fails the turn otherwise.
A subagent’s child thread nests under the subAgentActivity item or the
spawnAgent call that names it (0.154.0 sends either); the spawn call also
names the child’s model.opencode
opencode
anyagent starts
opencode serve on a private localhost port per session,
gated by a per-session secret, and drives its HTTP + SSE wire. Task-tool
child sessions nest as subagents; the task names the child’s role
(subagent_type) and model. No steer (mid-turn prompts queue) and no
plan quota. Pass a model as configure("model", "provider/id"); opencode’s
free opencode/… models need no key. Client MCP servers (stdio, HTTP, SSE)
are added with POST /mcp at open. opencode keeps them per server process,
and each session has its own, so they last for that session. A server
opencode cannot connect fails open with InvalidConfiguration. To drive it
over ACP instead: AgentInstallation::acp("opencode", path, ["acp"]).pi
pi
Provider-key based: log in with
/login <provider> inside the CLI, or set the
provider’s API-key variable. generate launches with --no-tools --no-session,
so it is text-only and nothing is saved.Antigravity: two ways in
Antigravity: two ways in
Discovery picks the richer wire that is installed:The headless Force the headless CLI with
agy wire cannot prompt: in Ask and AcceptEdits mode every
permission-gated tool is denied by the agent itself (the tool shows as
failed), AutoApprove launches with --dangerously-skip-permissions,
questions are skipped with a diagnostic, and a mid-turn prompt queues. Cancel
kills the process and resumes the conversation in a fresh one, about two
seconds.The ACP server is Google’s own (antigravity-acp in the
ACP registry,
a 314 MB download). It reuses the agy login: anyagent calls its
authenticate once per open (about 2 s, no browser), or set auth.type in
~/.gemini/antigravity-acp/settings.json to skip that. When only agy is
found, the installation carries upgrade: Some(MissingAgent) with the
download hint:ANYAGENT_ANTIGRAVITY_BIN=~/.local/bin/agy.
Google’s terms restrict third-party tools driving a personal Antigravity
login; the ACP server is the sanctioned path. Surface that choice to users.Cursor CLI
Cursor CLI
Runs over
cursor-agent acp. Permission requests gate shell commands outside
its allowlist; file edits never ask, so sandbox accordingly. Before the
handshake anyagent runs cursor-agent about for the version and account and
fails typed with cursor-agent login when logged out. A model switch adopts
that model’s own options (effort, fast, thinking, context). Cursor’s
extension requests are answered: ask_question becomes a Question,
update_todos drives the plan, task (a subagent run) is surfaced as a
header only. Cursor reports no context usage, so each turn ends with an
estimate (4 chars ≈ 1 token) labelled anyagent/estimated in extensions.Kiro CLI
Kiro CLI
Its credential lives in a sqlite row that exists logged out too, so discovery
reports
Unknown and probe answers for real. effort is exposed as a live
option even though ACP advertises none: the adapter reads the level from
kiro’s metadata and switches it by running /effort <level> as a hidden
prompt between turns.Hermes Agent
Hermes Agent
Only its file tools ask permission. Its terminal tool runs without asking, so
a denied write does not stop it from writing via shell. Hermes never sends
tool status updates. No
effort option.Grok and Qwen Code
Grok and Qwen Code
Plain ACP. Grok exposes
effort from the model’s reasoningEfforts; qwen
exposes none. Both log in through their own TUI.Compaction is native-adapter only. ACP has no compaction in schema 1.7, so
ACP agents refuse with
UnsupportedFeature.Any other ACP agent
No catalog entry needed. Build the installation yourself:Pointing at a specific binary
Every catalog entry readsANYAGENT_<AGENT>_BIN first:
AgentInstallation::at(id, executable).
Windows
Every catalog agent ships for Windows and every installer below puts its directory onPATH, so discovery finds them without extra configuration.
npm installs are .cmd shims; discovery skips the bare bash shim next to
them. Cursor’s Windows installer is irm 'https://cursor.com/install?win32=true' | iex.
Several logins of the same agent
CLAUDE_CONFIG_DIR,
CODEX_HOME, …) for that process. An agent with no such variable fails with
InvalidConfiguration; an isolation request is never silently dropped.
Launch options
env reaches every agent process, side processes included, after
config_home’s variable: on the same name, yours wins.