Skip to main content

Crate aion_integration_acp

Crate aion_integration_acp 

Source
Expand description

The first-party Agent Client Protocol (ACP) adapter for Aion.

This crate implements the aion-integrations AgentHarness / AgentSession seam against any agent that speaks ACP over its stdio. Where aion-integration-norn adapts one specific harness and aion-integration-cli adapts the observability-only tier, this one adapts a protocol: a single implementation reaches every agent that has an ACP mode — Claude Code, Codex, Gemini CLI, OpenCode, and whatever ships next.

§The invariant this crate exists to preserve

The aion platform crates (aion-core, aion-worker, aion-server, …) stay ACP-blind: everything ACP-specific — the method namespace, the session/update shapes, the permission handshake — is confined to protocol, translate, and messages here, behind the neutral trait. Nothing above this adapter references an ACP type.

§Shape

§Four rulings worth knowing before you use it

  1. Cancel is the only intervention primitive advertised. It is the only one ACP v1 can actually deliver; the other four have no protocol mechanism, and advertising a control that silently does nothing would be worse than advertising none. A live session gates on translate::negotiated_capabilities; a composition root advertising this adapter at worker REGISTRATION — before any agent process exists — publishes the same ceiling through registration_capabilities, which is documented with why the two coincide for ACP and pinned against what translate::intervention_to_notification can actually build.
  2. The permission policy is required, with no default. An unanswered session/request_permission blocks the agent until the activity times out, and an Aion activity is unattended, so the answer is decided when the harness is built. See permission.
  3. No filesystem or terminal callbacks are offered. Those exist for editors with unsaved buffers and embedded panels; a worker has neither, and the agent has direct disk access. An inbound fs/* or terminal/* request is still ANSWERED (with -32601) and recorded, because an unanswered peer request wedges the run. See protocol.
  4. The event stream ending is the end-of-run signal, and it does not wait for the process. A real ACP agent is a persistent stdio server: it answers session/prompt and keeps running. The platform’s agent driver takes the terminal result only once the event stream yields None, so the adapter closes the transcript at the answer rather than at the child’s exit. See pump.

§Two limitations to read before you rely on this

  • The session working directory is per-HARNESS, not per-attempt. Two agent activities running concurrently through one AcpHarness share a workspace root and can overwrite each other’s files. Per-attempt workspace provisioning is a separate design; see harness for the full statement and why nothing is invented here.
  • A completed turn may legitimately carry no text. An agent that ends end_turn having emitted only tool calls yields a SUCCESSFUL result whose text is "". That is honest, not a bug: the agent finished and said nothing, and its work is on the transcript as tool events. See outcome.

§Wire types

The ACP request/response/notification types come from the published agent-client-protocol-schema crate, pinned exactly. That is deliberate: a hand-written mirror of a moving external protocol is a fossil waiting to happen, and a protocol bump should be a compile error rather than a silent wire mismatch. Only the schema is taken — not the full agent-client-protocol SDK, which carries its own async stack and would drag a second runtime into this tokio codebase.

Re-exports§

pub use catalogue::CATALOGUE;
pub use catalogue::CatalogueHarness;
pub use containment::ProcessGroup;
pub use harness::AcpHarness;
pub use harness::registration_capabilities;
pub use mcp::McpServerSpec;
pub use outcome::PromptOutcome;
pub use permission::PermissionPolicy;
pub use session::AcpConfigValue;
pub use session::AcpSession;
pub use session::TurnHandle;

Modules§

catalogue
The agents this build knows how to launch, as data — id, launch line, install hint. The harness catalogue: which ACP agents this build knows how to launch.
containment
Process-group containment for a spawned agent, so a session takes its whole tree with it. Process-group containment for a spawned ACP agent.
harness
The ACP adapter implementing aion_integrations::AgentHarness. AcpHarness — the AgentHarness implementation that drives any ACP agent subprocess.
mcp
The MCP servers an agent is handed when a session opens. The MCP servers this adapter hands an agent on session/new and session/load.
messages
Reassembly of ACP’s per-chunk message stream into durable messages and the run’s final text. The streamed-message accumulator: turns ACP’s per-chunk session/update streams into a transcript that is both live and durable, and into the run’s final text.
outcome
Interpretation of the terminal session/prompt Response as the activity’s result. Interpretation of the terminal session/prompt Response as the activity’s result.
permission
The required policy for answering session/request_permission. The permission policy an AcpHarness must be constructed with — how this adapter answers session/request_permission.
protocol
ACP’s on-wire contract — the ONLY module naming its method strings and protocol version. The Agent Client Protocol wire contract — the ONLY module naming ACP’s method strings, its protocol version, and the client capabilities this adapter advertises.
pump
The reader pump that handles every inbound frame for a live session. The reader pump: the one task that owns the connection’s reader and handles every inbound frame.
session
The live ACP session implementing aion_integrations::AgentSession. AcpSession — a live ACP prompt turn behind the AgentSession seam.
translate
The pure translation between ACP’s wire shapes and the neutral aion-core types. The translation point — the single place ACP’s native shapes meet the neutral aion-core types.