Skip to main content
A ready-to-run example is available here!
ACPAgent lets you use any Agent Client Protocol server as the backend for an OpenHands conversation. Instead of calling an LLM directly, the agent spawns an ACP server subprocess and communicates with it over JSON-RPC. The server manages its own LLM, tools, and execution — your code just sends messages and collects responses.

Basic Usage

The acp_command is the shell command used to spawn the server process. The SDK communicates with it over stdin/stdout JSON-RPC.
Key difference from standard agents: With ACPAgent, you don’t need an LLM_API_KEY in your code. The ACP server handles its own LLM authentication and API calls. This is delegation — your code sends messages to the ACP server, which manages all LLM interactions internally.

Prompt Context (AgentContext)

ACPAgent supports agent_context for prompt-only extensions — skills, repository context, current datetime, and system/user message suffixes are appended to the user message before it reaches the ACP server. This lets you inject the same skill catalog and repo-specific guidance that the built-in Agent receives, without interfering with the server’s own tools or execution model.
The prompt assembly works as follows:
  1. The conversation layer builds the user MessageEvent, including any per-turn extended_content (e.g. triggered-skill injections).
  2. ACPAgent._build_acp_prompt() collects all text blocks from the message and appends the rendered AgentContext prompt (datetime, repo context, available skills, system suffix) via to_acp_prompt_context().
  3. The combined text is sent as a single user message to the ACP server.
user_message_suffix is an ACP-compatible field, but it is not duplicated in to_acp_prompt_context() because the conversation layer already applies it through MessageEvent.to_llm_message().

Compatible AgentContext Fields

Each AgentContext field is tagged as ACP-compatible or not. At initialization, validate_acp_compatibility() rejects any context that uses unsupported fields. Any AgentContext field marked acp_compatible: False raises NotImplementedError at initialization.

What ACPAgent Does Not Support

Because the ACP server manages its own tools, context window, and execution, these AgentBase features are not available on ACPAgent:
  • tools / include_default_tools — the server has its own tools
  • mcp_config — configure MCP on the server side
  • condenser — the server manages its own context window
  • critic — the server manages its own evaluation
Passing any of these raises NotImplementedError at initialization.

ACPAgent with RemoteConversation

ACPAgent also works with remote agent-server deployments such as APIRemoteWorkspace, DockerWorkspace, and other RemoteWorkspace-backed setups. When RemoteConversation detects an ACPAgent, it automatically uses the ACP-capable conversation routes for:
  • conversation creation
  • conversation info reads
  • conversation counting
The rest of the lifecycle, including events, runs, pauses, and secrets, continues to use the standard agent-server routes. This keeps the existing remote execution flow intact while isolating the schema-sensitive ACP contract under /api/acp/conversations.
If you attach to an existing conversation by conversation_id, use ACPAgent for ACP-backed conversations. Attaching with a regular Agent to an ACP conversation ID is rejected explicitly to avoid mixing the standard and ACP conversation contracts.

How It Works

  • Subprocess delegation: ACPAgent spawns the ACP server and communicates via JSON-RPC over stdin/stdout
  • Server-managed execution: The ACP server handles its own LLM calls, tools, and context — your code just sends messages
  • Auto-approval: Permission requests from the server are automatically granted, so ensure you trust the ACP server you’re running
  • Metrics collection: Token usage and costs from the server are captured into the agent’s LLM.metrics

Configuration

Server Command and Arguments

Environment Variables and Credentials

Pass the environment variables and credentials the ACP server needs through the conversation’s secrets (or agent_context.secrets). They flow into the conversation’s secret registry, are injected into the ACP subprocess environment, and are masked if the server echoes them back into its output:
acp_env still works but is deprecated and will be removed in 1.29.0; prefer the secret-registry channels above for environment variables and credentials.

Authentication

When the ACP server advertises authentication methods, ACPAgent automatically selects a credential source:
  1. ChatGPT subscription login — If the server supports a chatgpt auth method and ~/.codex/auth.json exists (created by LLM.subscription_login()), this is selected first. This enables ACP-backed workflows to use device-code login credentials without an explicit API key.
  2. API key environment variables — Falls back to checking for ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY depending on which auth methods the server supports.
If no supported credential source is found, the server may proceed without authentication (some servers don’t require it).

Metrics

Token usage and cost data are automatically captured from the ACP server’s responses. You can inspect them through the standard LLM.metrics interface:
Usage data comes from two ACP protocol sources:
  • PromptResponse.usage — per-turn token counts (input, output, cached, reasoning tokens)
  • UsageUpdate notifications — cumulative session cost and context window size

Cleanup

Always call agent.close() when you are done to terminate the ACP server subprocess. A try/finally block is recommended:

Ready-to-run Example

This example is available on GitHub: examples/01_standalone_sdk/40_acp_agent_example.py
examples/01_standalone_sdk/40_acp_agent_example.py
This example uses ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY environment variables to configure the Claude Code ACP server.
Running the Example

Remote Runtime Example

This example shows how to run an ACPAgent in a remote sandboxed environment via the Runtime API, using APIRemoteWorkspace:
examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py
Running the Example
On the agent-server side, the ACP-capable REST surface lives under /api/acp/conversations, including POST, GET, search, batch get, and count.

Next Steps