# ACP Kit

[![CI](https://github.com/vcoderun/acpkit/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/vcoderun/acpkit/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/vcoderun/acpkit/branch/main/graph/badge.svg?token=ZQL4NY4FK6)](https://codecov.io/gh/vcoderun/acpkit) [![PyPI version](https://img.shields.io/pypi/v/acpkit.svg)](https://pypi.org/project/acpkit/) [![Python versions](https://img.shields.io/pypi/pyversions/acpkit.svg)](https://pypi.org/project/acpkit/) [![GitHub release](https://img.shields.io/github/v/release/vcoderun/acpkit)](https://github.com/vcoderun/acpkit/releases) [![License](https://img.shields.io/github/license/vcoderun/acpkit)](https://github.com/vcoderun/acpkit/blob/main/LICENSE)


ACP Kit is the adapter toolkit and monorepo for exposing existing agent runtimes through ACP without inventing runtime features that are not really there.

> **ACP Kit v1:** `1.0.0` is the first stable release of the synchronized
> adapter, helper, and transport packages. See the
> [release notes](https://vcoderun.github.io/acpkit/releases/acpkit-1.0.0/)
> and [versioning policy](https://vcoderun.github.io/acpkit/versioning/).

Today the repo ships two maintained adapter families:

- `pydantic-acp`
- `langchain-acp`

Supporting packages sit alongside those adapters:

- `acpkit`
- `codex-auth-helper`
- `acpremote`

Package map:

- `pydantic-acp`
  Production-grade ACP adapter for `pydantic_ai.Agent`.
- `langchain-acp`
  Production-grade ACP adapter for LangChain, LangGraph, and DeepAgents compiled graphs.
- `acpkit`
  Root CLI, target resolver, and launch helpers.
- `codex-auth-helper`
  Helper package for building Codex-backed Pydantic AI Responses models from a local Codex login.
- `acpremote`
  Generic WebSocket transport helper for exposing any ACP agent remotely and mirroring a remote ACP server back into a local ACP boundary.

ACP Kit is not a new agent framework. The intended workflow is:

1. Keep your existing agent surface.
2. Expose it through ACP with `run_acp(...)` or `create_acp_agent(...)`.
3. Add only the ACP-visible state your runtime can actually honor: models, modes, plans, approvals, projection maps, MCP metadata, and host-backed tools.

## Installation

Every maintained integration:

```bash
uv add "acpkit[all]>=1.0.0,<2.0.0"
```

```bash
pip install "acpkit[all]>=1.0.0,<2.0.0"
```

Latest stable Pydantic integration:

```bash
uv add "acpkit[pydantic]"
```

```bash
pip install "acpkit[pydantic]"
```

LangChain and LangGraph support:

```bash
uv add "acpkit[langchain]"
```

```bash
pip install "acpkit[langchain]"
```

DeepAgents compatibility on top of `langchain-acp`:

```bash
uv add "acpkit[deepagents]"
```

```bash
pip install "acpkit[deepagents]"
```

Remote transport helpers:

```bash
uv add "acpkit[remote]"
```

```bash
pip install "acpkit[remote]"
```

With `acpkit launch` support:

```bash
uv add "acpkit[pydantic,launch]"
```

```bash
pip install "acpkit[pydantic,launch]"
```

Contributor setup:

```bash
uv sync --extra dev --extra docs --extra pydantic --extra langchain
```

```bash
pip install -e ".[dev,docs,pydantic,langchain]"
```

Contributor setup and validation commands are documented in [CONTRIBUTING.md](https://github.com/vcoderun/acpkit/blob/main/CONTRIBUTING.md).

Release validation and artifact smoke testing are documented in the
[release process](https://vcoderun.github.io/acpkit/release-process/).

## Quickstart

ACP Kit has two primary adapter entry points. Pick the one that matches the runtime you already have.

Pydantic path:

```python
from pydantic_ai import Agent
from pydantic_acp import run_acp

agent = Agent("openai:gpt-5", name="weather-agent")


@agent.tool_plain
def get_weather(city: str) -> str:
    return f"Weather in {city}: sunny"


run_acp(agent=agent)
```

LangChain or LangGraph path:

```python
from langchain.agents import create_agent
from langchain_acp import run_acp

graph = create_agent(model="openai:gpt-5", tools=[])

run_acp(graph=graph)
```

If ACP session state should influence what gets built, both adapters expose a factory seam:

- `pydantic-acp`: `agent_factory=session -> Agent`
- `langchain-acp`: `graph_factory=session -> CompiledStateGraph`

`acpremote` is not an adapter. It is a transport/helper package for exposing or consuming any existing `acp.interfaces.Agent`.

Docs:

- Overview: <https://vcoderun.github.io/acpkit/>
- Installation: <https://vcoderun.github.io/acpkit/getting-started/installation/>
- Quickstart hub: <https://vcoderun.github.io/acpkit/getting-started/quickstart/>
- Pydantic quickstart: <https://vcoderun.github.io/acpkit/getting-started/pydantic-quickstart/>
- LangChain quickstart: <https://vcoderun.github.io/acpkit/getting-started/langchain-quickstart/>
- Pydantic ACP overview: <https://vcoderun.github.io/acpkit/pydantic-acp/>
- LangChain ACP overview: <https://vcoderun.github.io/acpkit/langchain-acp/>
- Helpers overview: <https://vcoderun.github.io/acpkit/helpers/>
- `acpremote` package: <https://vcoderun.github.io/acpkit/acpremote/>

## CLI

Expose a supported target through ACP:

```bash
acpkit run my_agent
acpkit run my_agent:agent
acpkit run app.agents.demo:agent -p ./examples
```

Mirror a remote ACP WebSocket endpoint back into a local stdio ACP server:

```bash
acpkit run --addr ws://127.0.0.1:8080/acp/ws
acpkit run --addr ws://agents.example.com/acp/ws --token-env ACPREMOTE_BEARER_TOKEN
```

`acpkit` resolves `module` or `module:attribute` targets, auto-detects supported runtime objects, and dispatches them to the installed adapter package. If only the module is given, it selects the last defined supported target instance in that module.

Launch a target through Toad ACP:

```bash
acpkit launch my_agent
acpkit launch my_agent:agent -p ./examples
```

If the script already starts its own ACP server and should be launched directly:

```bash
acpkit launch -c "python3.11 finance_agent.py"
```

`launch TARGET` and `launch --command ...` are mutually exclusive. `-p/--path` only applies to `TARGET` mode.

The maintained LangChain and DeepAgents examples export configured native ACP
targets so their graph factories, sessions, modes, plans, and projections stay
intact:

```bash
acpkit run examples.langchain.workspace_graph:acp_agent
acpkit run examples.langchain.deepagents_graph:acp_agent
```

If the module omits `:attribute`, `acpkit` selects the last defined supported target instance in that module, regardless of whether it is a Pydantic AI agent or a LangGraph graph.

Expose any supported target through the remote WebSocket transport:

```bash
acpkit serve examples.pydantic.finance_agent:acp_agent
acpkit serve examples.langchain.workspace_graph:acp_agent --host 0.0.0.0 --port 8080
```

If you already have a native ACP agent object, `acpkit run module:agent` can dispatch that directly too.

## What `acpremote` Supports

`acpremote` is transport-only. It does not require ACP Kit adapters on either side as long as an ACP agent already exists.

Core surfaces include:

- `serve_acp(...)` for exposing any `acp.interfaces.Agent` over WebSocket
- `serve_command(...)` for exposing any stdio ACP command over WebSocket
- `connect_acp(...)` for turning a remote ACP WebSocket endpoint back into a local ACP agent proxy
- `acpkit serve ...` for serving supported ACP Kit targets remotely
- `acpkit run --addr ...` for mirroring a remote ACP endpoint into a local stdio ACP server
- `/acp` metadata and `/healthz` HTTP routes alongside the WebSocket endpoint
- optional bearer-token protection for the WebSocket endpoint
- optional latency logging through `TransportOptions(emit_latency_meta=True, emit_latency_projection=True)`

`acpremote` guides:

- docs: <https://vcoderun.github.io/acpkit/acpremote/>
- docs: <https://vcoderun.github.io/acpkit/examples/remote-hosting/>

For the end-to-end remote flow, the common split is:

- remote host: `acpkit serve ...` or `acpremote.serve_command(...)`
- local client: `acpkit run --addr ...` or `acpremote.connect_acp(...)`
- launcher integration: `toad acp "acpkit run --addr ..."`

## What `pydantic-acp` Supports

`AdapterConfig` is the main runtime surface. Common ownership seams include:

- session stores and lifecycle
- model selection
- mode and config state
- approval bridges
- native plan state or host-owned plan providers
- capability bridges
- projection maps and tool classification
- prompt-model override providers

Prompt resource support includes:

- ACP text blocks
- resource links
- embedded text resources
- image blocks
- audio blocks
- embedded binary resources

Host-facing utilities include:

- `HostAccessPolicy` for typed filesystem and terminal guardrails
- `ClientHostContext` for ACP client-backed host access
- `BlackBoxHarness` for ACP boundary integration tests
- `CompatibilityManifest` for documenting the ACP surface an integration truly supports

## ACP Client Provider Bridge

`pydantic-acp` also includes the inverse bridge: an ACP agent can be consumed as a Pydantic AI v2 model via `create_acp_model(...)`, or manually through `AcpProvider` and `AcpModel`.

```python
from pydantic_ai import Agent
from pydantic_acp import create_acp_agent, create_acp_model

inner_acp = create_acp_agent(agent=some_pydantic_agent)
model = create_acp_model(acp_agent=inner_acp, cwd="/workspace")
agent = Agent(model)

result = await agent.run("Summarize the current workspace state.")
print(result.output)
```

`acp_command` is for child processes that speak ACP JSON-RPC on stdin/stdout. It is not an arbitrary CLI wrapper.

```python
from pydantic_ai import Agent
from pydantic_acp import create_acp_model

model = create_acp_model(
    acp_command=("npx", "@zed-industries/codex-acp"),
    cwd="/workspace",
    stderr_mode="inherit",
)
agent = Agent(model)
```

For lower-level ownership, construct the provider directly:

```python
from pydantic_ai import Agent
from pydantic_acp import AcpProvider

# `remote_acp_agent` can be any object implementing the ACP Agent interface.
provider = AcpProvider(acp_agent=remote_acp_agent, cwd="/workspace")
model = provider.model()
agent = Agent(model)

result = await agent.run("Summarize the current workspace state.")
print(result.output)
```

This keeps ownership boundaries explicit:

- Pydantic AI owns the outer agent run, output validation, and normal model/provider lifecycle.
- ACP owns the delegated agent session, ACP-visible updates, and any editor or host capabilities requested by that agent.
- `create_acp_model(...)` and `provider.model()` leave ACP model selection to the wrapped agent's session default; pass `model_name="zed-agent"` or `provider.model("zed-agent")` only when the ACP agent accepts that concrete `session/set_model` ID.
- `AcpHostBridge` records ACP `session_update` messages and can delegate filesystem, terminal, approval, and extension callbacks to a real ACP host client when one is supplied.
- Pydantic AI function tools are intentionally not executed directly by `AcpModel`; register tools on the ACP agent or expose host capabilities through ACP.

Use this bridge when the thing you have is already an ACP agent and you want it to participate in code that expects a Pydantic AI provider/model. It is not another ACP server adapter and it does not replace `create_acp_agent(...)`.

## What `langchain-acp` Supports

`langchain-acp` keeps ACP Kit's adapter seams intact while staying graph-centric on the upstream side.

Core surfaces include:

- `graph`, `graph_factory`, and `graph_source`
- session stores and transcript replay
- model, mode, and config-option providers
- native ACP plan state with `TaskPlan`
- approval bridging from LangChain `HumanInTheLoopMiddleware`
- capability bridges and graph-build contributions
- projection maps and event projection maps
- DeepAgents compatibility through `DeepAgentsCompatibilityBridge` and `DeepAgentsProjectionMap`

Prompt and event handling covers:

- resource and multimodal prompt conversion for ACP inputs
- streamed text handling from LangChain and LangGraph events
- structured event projection when graph output should stay visible in ACP clients
- richer tool projection presets for filesystem, browser, HTTP, search, finance, and DeepAgents-style tool families

Maintained integration paths include:

- plain LangChain `create_agent(...)` graphs
- compiled LangGraph graphs
- DeepAgents graphs through the compatibility bridge
- session-aware `graph_factory(session)` builds when ACP session state should influence graph construction

That lets the adapter expose plain LangChain graphs, compiled LangGraph graphs, and DeepAgents graphs without collapsing everything into one bespoke runtime.

## Native Plan Mode And `TaskPlan`

`pydantic-acp` now uses `TaskPlan` as the structured native plan output surface.

Native plan mode is typically enabled through `PrepareToolsBridge`:

```python
from pydantic_ai import Agent
from pydantic_ai.tools import RunContext, ToolDefinition
from pydantic_acp import (
    AdapterConfig,
    PrepareToolsBridge,
    PrepareToolsMode,
    run_acp,
)


def read_only_tools(
    ctx: RunContext[None],
    tool_defs: list[ToolDefinition],
) -> list[ToolDefinition]:
    del ctx
    return list(tool_defs)


agent = Agent("openai:gpt-5", name="plan-agent")

run_acp(
    agent=agent,
    config=AdapterConfig(
        capability_bridges=[
            PrepareToolsBridge(
                default_mode_id="plan",
                default_plan_generation_type="structured",
                modes=[
                    PrepareToolsMode(
                        id="plan",
                        name="Plan",
                        description="Return a structured ACP task plan.",
                        prepare_func=read_only_tools,
                        plan_mode=True,
                    ),
                ],
            ),
        ],
    ),
)
```

Key rules:

- `plan_generation_type="structured"` is the default native plan-mode behavior.
- In `structured` mode, the adapter expects structured `TaskPlan` output instead of exposing `acp_set_plan`.
- Switch to `plan_generation_type="tools"` when you explicitly want tool-based native plan recording.
- Keep `plan_tools=True` for progress tools such as `acp_update_plan_entry` and `acp_mark_plan_done`.
- Native plan state and a host-owned `plan_provider` are separate seams. Use one truth source per workflow.

## Projection Maps

Projection maps decide how known tool families render into ACP-visible updates instead of raw text blobs.

Built-in projection helpers:

- `FileSystemProjectionMap`
  Filesystem reads, writes, and command previews into ACP diffs and rich status cards.
- `HookProjectionMap`
  Re-label or hide selected `Hooks(...)` lifecycle events.
- `WebToolProjectionMap`
  Rich rendering for web-search and web-fetch style tool families.
- `BuiltinToolProjectionMap`
  Rich rendering for built-in upstream capability tools such as web search, web fetch, image generation, and upstream MCP capability calls.

Example:

```python
from pydantic_acp import (
    AdapterConfig,
    BuiltinToolProjectionMap,
    FileSystemProjectionMap,
    HookProjectionMap,
    run_acp,
)

run_acp(
    agent=agent,
    config=AdapterConfig(
        projection_maps=[
            FileSystemProjectionMap(
                default_read_tool="read_file",
                default_write_tool="write_file",
            ),
            HookProjectionMap(
                hidden_event_ids=frozenset({"after_model_request"}),
                event_labels={"before_model_request": "Preparing Request"},
            ),
            BuiltinToolProjectionMap(),
        ],
    ),
)
```

## Capability Bridges

Capability bridges extend runtime behavior without hard-coding one product shape into the adapter core.

Current built-in bridges include:

- `ThinkingBridge`
- `PrepareToolsBridge`
- `ThreadExecutorBridge`
- `SetToolMetadataBridge`
- `IncludeToolReturnSchemasBridge`
- `WebSearchBridge`
- `WebFetchBridge`
- `ImageGenerationBridge`
- `McpCapabilityBridge`
- `SessionMcpBridge`
- `ToolsetBridge`
- `PrefixToolsBridge`
- `OpenAICompactionBridge`
- `AnthropicCompactionBridge`

Use bridges when the runtime should gain upstream Pydantic AI capabilities and ACP-visible metadata without rewriting the adapter core.

## Maintained Examples

The maintained example set is intentionally small. Each example is broad enough to be useful on its own instead of only demonstrating one narrow helper.

- [Finance Agent](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/finance_agent.py)
  Session-aware finance workspace with ACP plans, approvals, mode-aware tool shaping, and projected note diffs.
- [Travel Agent](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/travel_agent.py)
  Travel planning runtime with hook projection, approval-gated trip files, and prompt-model override behavior for media prompts.
- [Workspace Graph](https://github.com/vcoderun/acpkit/blob/main/examples/langchain/workspace_graph.py)
  Plain LangChain graph wiring with a module-level `graph`, session-aware `graph_from_session(...)`, and filesystem read/write projection.
- [DeepAgents Graph](https://github.com/vcoderun/acpkit/blob/main/examples/langchain/deepagents_graph.py)
  DeepAgents compatibility wiring through `langchain-acp`, approvals, and projection presets.
- [ACP Remote Hosting](https://vcoderun.github.io/acpkit/examples/remote-hosting/)
  Documented remote-host pattern for both maintained adapters plus direct ACP command transport.

Run them with:

```bash
uv run python -m examples.pydantic.finance_agent
uv run python -m examples.pydantic.travel_agent
uv run python -m examples.langchain.workspace_graph
uv run python -m examples.langchain.deepagents_graph
```

## Documentation Map

Top-level docs:

- [Getting Started](https://vcoderun.github.io/acpkit/getting-started/quickstart/)
- [CLI](https://vcoderun.github.io/acpkit/cli/)
- [Pydantic ACP Overview](https://vcoderun.github.io/acpkit/pydantic-acp/)
- [LangChain ACP Overview](https://vcoderun.github.io/acpkit/langchain-acp/)
- [Helpers](https://vcoderun.github.io/acpkit/helpers/)
- [acpremote Overview](https://vcoderun.github.io/acpkit/acpremote/)
- [Security Guidance](https://vcoderun.github.io/acpkit/security/)
- [Production Deployment](https://vcoderun.github.io/acpkit/production-deployment/)
- [AdapterConfig](https://vcoderun.github.io/acpkit/pydantic-acp/adapter-config/)
- [Plans, Thinking, and Approvals](https://vcoderun.github.io/acpkit/pydantic-acp/plans-thinking-approvals/)
- [Prompt Resources and Context](https://vcoderun.github.io/acpkit/pydantic-acp/prompt-resources/)
- [Session State and Lifecycle](https://vcoderun.github.io/acpkit/pydantic-acp/session-state/)
- [Models, Modes, and Slash Commands](https://vcoderun.github.io/acpkit/pydantic-acp/runtime-controls/)
- [Bridges](https://vcoderun.github.io/acpkit/bridges/)
- [Providers](https://vcoderun.github.io/acpkit/providers/)
- [Host Backends and Projections](https://vcoderun.github.io/acpkit/host-backends/)
- [Projection Cookbook](https://vcoderun.github.io/acpkit/projection-cookbook/)
- [Examples](https://vcoderun.github.io/acpkit/examples/)
- [LangChain Workspace Graph](https://vcoderun.github.io/acpkit/examples/langchain-workspace/)
- [DeepAgents Compatibility Example](https://vcoderun.github.io/acpkit/examples/deepagents/)
- [Remote ACP Hosting](https://vcoderun.github.io/acpkit/examples/remote-hosting/)
- [Dynamic Factory Agents](https://vcoderun.github.io/acpkit/examples/dynamic-factory/)
- [Testing](https://vcoderun.github.io/acpkit/testing/)

Reference docs:

- [`acpkit` API](https://vcoderun.github.io/acpkit/api/acpkit/)
- [`langchain_acp` API](https://vcoderun.github.io/acpkit/api/langchain_acp/)
- [`pydantic_acp` API](https://vcoderun.github.io/acpkit/api/pydantic_acp/)
- [`codex_auth_helper` API](https://vcoderun.github.io/acpkit/api/codex_auth_helper/)

## ACP Kit Skill

This repo also ships an `acpkit-sdk` skill package for Codex.

Use it when you want Codex to help integrate ACP into an existing agent surface, especially for:

- exposing an existing `pydantic_ai.Agent` through ACP
- choosing between `run_acp(...)`, `create_acp_agent(...)`, providers, bridges, and `AgentSource`
- wiring plans, approvals, session stores, thinking, MCP metadata, and host-backed tools
- keeping docs and examples aligned with the real SDK surface

Install with just one command:

```bash
npx ctx7 skills install /vcoderun/acpkit acpkit-sdk
```

Canonical skill package:

- [`.agents/skills/acpkit-sdk/`](https://github.com/vcoderun/acpkit/tree/main/.agents/skills/acpkit-sdk)

Example prompts:

- `Use $acpkit-sdk to expose my existing pydantic_ai.Agent through ACP.`
- `Use $acpkit-sdk to add ACP plans, approvals, slash-command mode switching, and projection maps to this agent.`
