Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions sdk/guides/agent-acp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

> A ready-to-run example is available [here](#ready-to-run-example)!

`ACPAgent` lets you use any [Agent Client Protocol](https://agentclientprotocol.com/protocol/overview) 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.

Check warning on line 8 in sdk/guides/agent-acp.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L8

Did you really mean 'subprocess'?

## Basic Usage

Expand All @@ -29,7 +29,7 @@
**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.
</Note>

### What ACPAgent Does Not Support

Check warning on line 32 in sdk/guides/agent-acp.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L32

Did you really mean 'ACPAgent'?

Because the ACP server manages its own tools and context, these `AgentBase` features are not available on `ACPAgent`:

Expand All @@ -43,7 +43,7 @@

## How It Works

- **Subprocess delegation**: `ACPAgent` spawns the ACP server and communicates via JSON-RPC over stdin/stdout

Check warning on line 46 in sdk/guides/agent-acp.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L46

Did you really mean 'Subprocess'?
- **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`
Expand Down Expand Up @@ -84,7 +84,7 @@

## Cleanup

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

Check warning on line 87 in sdk/guides/agent-acp.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L87

Did you really mean 'subprocess'?

```python icon="python"
agent = ACPAgent(acp_command=["npx", "-y", "claude-code-acp"])
Expand All @@ -106,9 +106,7 @@
"""Example: Using ACPAgent with Claude Code ACP server.

This example shows how to use an ACP-compatible server (claude-code-acp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical: The docstring in the upstream example file still mentions and demonstrates ask_agent(). This is a real feature that was added in PR #2145 and is actively used in the example.

Removing this documentation diverges from the source file. The upstream docstring says: "It also demonstrates ask_agent() — a stateless side-question that forks the ACP session and leaves the main conversation untouched."

as the agent backend instead of direct LLM calls. It also demonstrates
``ask_agent()`` — a stateless side-question that forks the ACP session
and leaves the main conversation untouched.
as the agent backend instead of direct LLM calls.

Prerequisites:
- Node.js / npx available
Expand All @@ -124,25 +122,17 @@
from openhands.sdk.conversation import Conversation


agent = ACPAgent(acp_command=["npx", "-y", "@zed-industries/claude-code-acp"])
agent = ACPAgent(acp_command=["npx", "-y", "claude-code-acp"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical: Wrong package name. The actual example file uses @zed-industries/claude-agent-acp (verified at https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/40_acp_agent_example.py#L22).

The package you changed to (claude-code-acp) is a different, less maintained package (last updated Sept 2025 at v0.1.1), while @zed-industries/claude-agent-acp is actively maintained (updated Mar 4, 2026 at v0.20.2).

Suggested change
agent = ACPAgent(acp_command=["npx", "-y", "claude-code-acp"])
agent = ACPAgent(acp_command=["npx", "-y", "@zed-industries/claude-agent-acp"])


try:
cwd = os.getcwd()
conversation = Conversation(agent=agent, workspace=cwd)

# --- Main conversation turn ---
conversation.send_message(
"List the Python source files under openhands-sdk/openhands/sdk/agent/, "
"then read the __init__.py and summarize what agent classes are exported."
)
conversation.run()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical: The upstream example file includes the ask_agent() demonstration (lines 35-40). This PR removes it, which contradicts the goal of "aligning" with the example.

The removed code demonstrates an important feature:

# --- ask_agent: stateless side-question via fork_session ---
print("\n--- ask_agent ---")
response = conversation.ask_agent(
    "Based on what you just saw, which agent class is the newest addition?"
)
print(f"ask_agent response: {response}")

This should be kept to match the actual example file.


# --- ask_agent: stateless side-question via fork_session ---
print("\n--- ask_agent ---")
response = conversation.ask_agent(
"Based on what you just saw, which agent class is the newest addition?"
)
print(f"ask_agent response: {response}")
finally:
# Clean up the ACP server subprocess
agent.close()
Expand Down
Loading