Skip to content
Merged
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
23 changes: 19 additions & 4 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 Down Expand Up @@ -58,7 +58,7 @@
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()`.

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L61

Did you really mean 'datetime'?
3. The combined text is sent as a single user message to the ACP server.

<Note>
Expand All @@ -78,11 +78,11 @@
| `load_user_skills` | ✅ | Load skills from `~/.openhands/skills/` |
| `load_public_skills` | ✅ | Load skills from the public extensions repo |
| `marketplace_path` | ✅ | Filter public skills via marketplace JSON |
| `secrets` | | ACP subprocesses do not use OpenHands secret injection |
| `secrets` | | Injected into the ACP subprocess environment (and masked if the server echoes them back) |

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L81

Did you really mean 'subprocess'?

Passing `secrets` (or any future field marked `acp_compatible: False`) raises `NotImplementedError`.
Any `AgentContext` field marked `acp_compatible: False` raises `NotImplementedError` at initialization.

### What ACPAgent Does Not Support

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L85

Did you really mean 'ACPAgent'?

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

Expand All @@ -93,7 +93,7 @@

Passing any of these raises `NotImplementedError` at initialization.

## ACPAgent with RemoteConversation

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L96

Did you really mean 'ACPAgent'?

`ACPAgent` also works with remote agent-server deployments such as `APIRemoteWorkspace`, `DockerWorkspace`, and other `RemoteWorkspace`-backed setups.

Expand All @@ -111,7 +111,7 @@

## How It Works

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

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L114

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 All @@ -124,15 +124,30 @@
agent = ACPAgent(
acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"],
acp_args=["--profile", "my-profile"], # extra CLI args
acp_env={"ANTHROPIC_API_KEY": "sk-..."}, # extra env vars
)
```

| Parameter | Description |
|-----------|-------------|
| `acp_command` | Command to start the ACP server (required) |
| `acp_args` | Additional arguments appended to the command |
| `acp_env` | Additional environment variables for the server process |
| `acp_env` | **Deprecated** (removed in 1.29.0). Route env/credentials through the conversation's `secrets` or `agent_context.secrets` instead — see below. |

### 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:

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L138

Did you really mean 'subprocess'?

```python icon="python"
conversation = Conversation(
agent=agent,
workspace="./my-project",
secrets={"ANTHROPIC_API_KEY": "sk-..."},
)
```

<Note>
`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.
</Note>

### Authentication

Expand Down Expand Up @@ -161,7 +176,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 179 in sdk/guides/agent-acp.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L179

Did you really mean 'subprocess'?

```python icon="python"
agent = ACPAgent(acp_command=["npx", "-y", "@agentclientprotocol/claude-agent-acp"])
Expand Down Expand Up @@ -248,7 +263,7 @@
This example is available on GitHub: [examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py)
</Note>

This example shows how to run an ACPAgent in a remote sandboxed environment via the Runtime API, using `APIRemoteWorkspace`:

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L266

Did you really mean 'ACPAgent'?

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

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/agent-acp.mdx#L266

Did you really mean 'sandboxed'?

```python icon="python" expandable examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py
"""Example: ACPAgent with Remote Runtime via API.
Expand Down
Loading