Agent Client Protocol · stable protocol v1

Bring coding agents into your product—or bring your agent into the editor.

ACP gives a coding interface and a coding agent a shared way to open a project, exchange prompts, stream progress, ask for approval, cancel work, and continue the same session. ADK-Rust implements both sides of that relationship.

Official SDK wire formatClient + agent rolesPersistent sessionsLive typed updatesAsync human approvalCancellationLifecycle persistence

ADK-Rust ACP architecture

One protocol, two useful directions.

The program with the interface is the ACP client. The program doing the coding work is the ACP agent. ADK-Rust can sit on either side of that relationship.

01 · ADK-Rust is the ACP client / host

ADK-Rust uses an external coding agent

choose this direction

ADK coordinator

Decides that a repository task needs a coding specialist.

tool call

AcpAgentTool · AcpSession

Starts the process, chooses the workspace, keeps context, and applies permission policy.

ACP v1 · stdio

External ACP agent

Inspects code, proposes edits, invokes tools, and streams its progress.

The shared ACP v1 contract

Both directions use the same message vocabulary.

initializesession/newsession/promptsession/updaterequest_permissioncancelclose · list · resume · delete

02 · ADK-Rust is the ACP agent / server

An editor uses an ADK-Rust agent

choose this direction

Editor or ACP client

Owns the conversation UI and starts the ADK-Rust binary.

ACP v1 · stdio

Official SDK + session handler

Negotiates capabilities, validates sessions, streams updates, and handles cancellation.

typed invocation

Runner + ADK agent

Uses models, Rust tools, workflows, sessions, memory, and artifacts to complete the turn.

Session service

One ACP session maps to one persisted ADK-Rust session.

Permission boundary

The client selects an option the agent actually offered.

Typed updates

Text, thoughts, tool starts, and tool completion stream as session/update.

Process boundary

Stable ACP v1 uses a local subprocess and JSON-RPC over stdio.

ACP does not merge the editor and coding agent into one application. It gives them a shared session contract while each side keeps its own interface, runtime, tools, and security responsibilities.

Start with the relationship

What problem does ACP solve?

A coding agent can reason about a repository and use tools, but people still need an interface where they can describe the job, see what the agent is doing, answer questions, approve sensitive actions, and stop a turn. Without a standard, every editor and every coding agent needs a custom integration for those basics.

ACP defines that missing conversation. The client owns the interface and the working environment it chooses to provide. The agent owns the coding intelligence. They agree on sessions, prompts, content, live updates, tool calls, permission choices, cancellation, and completion without needing to share implementation code.

ADK-Rust supports both practical directions. An ADK agent can delegate work to an external ACP coding agent as a tool. With the server feature, an editor can start an ADK-Rust binary and use its Runner, models, tools, sessions, memory, and workflows through the same ACP v1 contract.

Client / host

The application people interact with

Usually an editor, desktop app, CLI, or ADK-Rust coordinator. It starts the coding agent, opens a project session, shows progress, and decides how permission questions reach the user.

ACP agent

The process that performs coding work

It receives prompts, reasons about the repository, reports tool activity, asks before sensitive actions, and returns a stop reason when the turn ends.

Session

The shared working conversation

A session has an ID, an absolute working directory, optional workspace roots, several prompts, streamed updates, and a clear close or resume lifecycle.

Permission

A decision at the point of action

The agent describes the exact tool call and offers choices. The client returns one of those choices, so the application—not the agent—controls whether the action proceeds.

One ACP turn

The interface stays responsive while the agent works.

Read from top to bottom. Initialization establishes the contract once. A session then carries several prompts, live updates, approval questions, cancellation, and a final stop reason.

Client / host

Editor or ADK-Rust

ACP agent

Coding process or ADK-Rust

initialize

protocolVersion: 1

capabilities

What this agent really supports

session/new

Absolute cwd + workspace roots

session/prompt

Typed content blocks

session/update

Text · thought · tool call

session/request_permission

Choose from offered options

permission response

Allow once · always · reject

PromptResponse

end_turn · cancelled

Cancellation is part of the conversation. ADK-Rust forwards session/cancel into the Runner cancellation token and returns a typed cancelled stop reason.

Direction one · ADK-Rust is the client

Let an ADK agent delegate repository work to a coding agent.

The external ACP process appears inside ADK-Rust as a named tool. Your coordinator can decide when to use it, choose the project directory, preserve context when the work spans several turns, stream progress into your interface, and keep approval policy outside the coding agent.

AcpAgentTool

One task, fresh process

Best when an ADK agent occasionally delegates a self-contained repository task. Each call starts an ACP process and returns its text as normal tool output.

AcpToolset

Several coding specialists

Give a coordinator named review, test, migration, or documentation agents. Their tool descriptions help the model route each task to the right process.

AcpSession

One continuing conversation

Keep the process and ACP session alive across prompts. The agent remembers what it already inspected, and a cancellation handle can stop an in-flight turn.

stream_prompt

Live product UI

Receive text, thought, tool-call, permission, completion, and error chunks as they happen instead of waiting for one combined string.

orchestrator.rsONE-SHOT DELEGATION
use adk_acp::{AcpAgentTool, PermissionPolicy};

let coder = AcpAgentTool::new("my-coding-agent --acp")
    .name("repository_coder")
    .description("Inspect and improve this Rust project")
    .working_dir("/absolute/path/to/project")
    .permission_policy(PermissionPolicy::DenyAll);

let coordinator = LlmAgentBuilder::new("coordinator")
    .model(model)
    .tool(Arc::new(coder))
    .build()?;
session.rsPERSISTENT + CANCELLABLE
let mut session = AcpSession::start(
    AcpAgentConfig::new("my-coding-agent --acp")
        .working_dir("/absolute/path/to/project"),
    Arc::new(permission_policy),
).await?;

let cancel = session.cancellation_handle()?;
tokio::spawn(async move {
    shutdown.cancelled().await;
    cancel.cancel().await
});

let result = session
    .prompt("Trace the failing test and propose a fix")
    .await?;

The client can provide the working environment

Choose what the coding agent can reach.

ACP does not assume that a coding agent can read your disk or run commands directly. The client declares the services it is prepared to provide, handles each request, and keeps the security rules close to the product and the user.

ADK-Rust now exposes typed file and terminal host interfaces and passes client-supplied MCP servers into session creation. Nothing is enabled by default. A read-only documentation tool, a desktop editor with unsaved buffers, and an isolated build worker can each publish a different, accurate capability set.

AcpFileSystem

Files from the real workspace

Your editor or application decides how reads and writes work. It can return an unsaved buffer, enforce approved roots, reject a symlink escape, or make the session read-only.

AcpTerminal

Managed command execution

The coding agent can start a command, collect output, wait, stop it, and release it through the client. Terminal support stays disabled until the host implements the complete lifecycle.

MCP over stdio

Tools supplied for this session

Attach an MCP server when the ACP session opens. ADK-Rust starts it inside the selected project, exposes its tools only to that session, and cancels it when the session closes.

Why MCP appears in ACP session setup

The client can lend a tool server to one coding session.

For example, an editor can attach its issue tracker or repository search MCP server when it opens the session. The coding agent receives those tools without owning their credentials or configuration. ADK-Rust supports the stdio transport required by stable ACP v1, starts each server with a bounded handshake, and removes it with the session. Optional HTTP and SSE transports are accepted by the client only when the external agent advertises them.

Approval belongs to the host

Make the decision where the user and policy live.

A coding agent may need to edit a file, execute a command, install a dependency, or delete generated output. ACP sends that proposed operation back to the client with a menu of valid choices. ADK-Rust preserves the security-relevant details and denies requests by default.

For a trusted local workflow, a rule can approve known operations. For an interactive product, PermissionPolicy::async_custom can wait for a desktop dialog, a web approval screen, or an organisation policy service. ADK-Rust returns the exact opaque option ID supplied by the agent; it never invents an approval value.

01

Agent describes the operation

The request carries the session ID, tool-call ID, title, tool kind, raw input, and every response option the agent supports.

02

Your application applies policy

Deny by default, use a synchronous rule, or await a human dialog or remote policy service through async_custom.

03

ADK-Rust selects a real option

Allow and reject choices are matched by ACP meaning, then the original opaque option ID is returned. A fabricated ID becomes a cancellation.

04

The agent continues or stops

The coding agent receives the decision in the same session and can continue the tool call, choose another path, or finish the turn.

permissions.rsASYNC HUMAN APPROVAL
let policy = PermissionPolicy::async_custom(|request| async move {
    let choice = approval_ui.ask(ApprovalPrompt {
        title: request.title,
        kind: request.kind,
        input: request.raw_input,
        options: request.options,
    }).await;

    match choice {
        Approval::Once => PermissionDecision::AllowOnce,
        Approval::Always => PermissionDecision::AllowAlways,
        Approval::Reject => PermissionDecision::Deny,
    }
});

The project directory is context, not a sandbox.

ACP tells both sides which project and additional roots belong to the session. It does not create an operating-system security boundary. If the coding process must be isolated from the rest of the machine, run it through adk-sandbox, a container, or another process policy.

Keep credentials in the process environment or the client's secret store. Protocol stdout must contain only ACP JSON-RPC messages.

Direction two · ADK-Rust is the ACP agent

Expose a complete ADK-Rust runtime to an editor.

The editor starts your Rust binary as an ACP subprocess. The official SDK owns JSON-RPC framing, request IDs, typed decoding, and stdio. The session handler maps one ACP session to one ADK-Rust session, then the Runner streams model and tool events back as live session/update notifications.

This direction is useful when your agent has domain-specific instructions, Rust tools, workflow agents, memory, or internal services that should be available from a coding interface. The editor does not need to understand those internals; it sees the capabilities and lifecycle the binary honestly publishes.

main.rsEXPOSE THE AGENT
use adk_acp::server::{
    AcpServer, AcpServerConfigBuilder
};

let config = AcpServerConfigBuilder::new()
    .agent(Arc::new(repository_agent))
    .session_service(Arc::new(session_service))
    .agent_name("repository-guide")
    .agent_description("Explains and improves this workspace")
    .max_sessions(16)
    .build()?;

let server = AcpServer::run(config).await?;
server.wait().await?;
acp-agent.jsonEDITOR PROCESS CONFIG
{
  "name": "repository-guide",
  "command": "/absolute/path/to/repository-guide",
  "args": [],
  "env": {
    "MODEL_API_KEY": "from-the-editor-secret-store"
  }
}
session-prompt.jsonREQUEST
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "session/prompt",
  "params": {
    "sessionId": "session-7f2a",
    "prompt": [{
      "type": "text",
      "text": "Explain error handling in src/main.rs"
    }]
  }
}
stdout.jsonlLIVE UPDATE + FINAL RESPONSE
{"jsonrpc":"2.0","method":"session/update","params":{
  "sessionId":"session-7f2a",
  "update":{"sessionUpdate":"agent_message_chunk","content":{
    "type":"text","text":"The entry point uses..."
  }}
}}
{"jsonrpc":"2.0","id":3,"result":{
  "stopReason":"end_turn"
}}

Verified scope

Know exactly what is ready before you design the integration.

ADK-Rust now uses the official agent-client-protocol crate for both roles. The table separates the interoperable v1 surface from features that still need implementation, so an editor or product does not discover a missing capability after integration work has started.

Protocol and transport

ACP protocol v1 · official Rust SDK 1.2 · JSON-RPC over local stdio

Implemented

ADK-Rust as client

Initialize, new session, prompt, live updates, tool permissions, one-shot, persistent, streaming

Implemented

Client cancellation

Cloneable handle sends session/cancel while another task awaits the prompt

Implemented

ADK-Rust as agent

Initialize, new, prompt, update, cancel, close, list, resume, delete

Implemented

Prompt content

Text and resource links; unsupported media types are rejected and not advertised

Implemented scope

Client filesystem / terminal callbacks

Opt-in host traits advertise only the file and terminal operations the application implements

Implemented API

Client-supplied MCP servers

Typed session configuration, required stdio server support, per-session ADK toolsets, bounded startup and cleanup

Implemented · stdio

ADK tool approval → ACP

The runtime can await an exact-call decision; the server bridge is held back because the official SDK currently loses the outer prompt response in the nested-request test

SDK limitation

Remote transport

HTTP or WebSocket ACP between machines

Protocol work is evolving; stdio only

Interoperability gate

Tested as a conversation, not as disconnected JSON.

An official SDK client connects to the ADK-Rust SDK agent through an in-memory transport and completes initialize → new → prompt → update → close → list → resume → close → delete. Cancellation tests cover both ACP session/cancel and JSON-RPC request cancellation, then prove the session can accept another prompt after cleanup. Permission tests cover reject-first menus, opaque IDs, fabricated selections, and an awaited human decision. A separate live gate starts a real stdio MCP child and discovers its tool catalog through the same McpToolset used by ACP sessions.

Build with the role you need

Add a coding specialist—or make your ADK agent available where developers already work.

Start with stdio, one absolute workspace, and DenyAll. Add a custom approval experience, persistent sessions, and stronger process isolation as the product's trust boundary becomes clear.