Skip to content
Merged
Show file tree
Hide file tree
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
28 changes: 22 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
# Repository Guidelines

## Project Structure & Module Organization
The package code lives under `src/acp`, exposing the high-level Agent, transport helpers, and generated protocol schema. Generated artifacts such as `schema/` and `src/acp/schema.py` are refreshed via `scripts/gen_all.py` against the upstream ACP schema. Integration examples are in `examples/`, including `echo_agent.py` and the mini SWE bridge. Tests reside in `tests/` with async fixtures and doctests; documentation sources live in `docs/` and publish via MkDocs. Built distributions drop into `dist/` after builds.
- `src/acp/`: runtime package exposing agent/client abstractions, transports, and the generated `schema.py`.
- `schema/`: upstream JSON schema sources; regenerate Python bindings with `make gen-all`.
- `examples/`: runnable scripts (`echo_agent.py`, `client.py`, `gemini.py`, etc.) demonstrating stdio orchestration patterns.
- `tests/`: pytest suite, including opt-in Gemini smoke checks under `tests/test_gemini_example.py`.
- `docs/`: MkDocs content powering the hosted documentation.

## Build, Test, and Development Commands
Run `make install` to create a `uv` managed virtualenv and install pre-commit hooks. `make check` executes lock verification, Ruff linting, `ty` static checks, and deptry analysis. `make test` calls `uv run python -m pytest --doctest-modules`. For release prep use `make build` or `make build-and-publish`. `make gen-all` regenerates protocol models; export `ACP_SCHEMA_VERSION=<ref>` beforehand to fetch a specific upstream schema (defaults to the cached copy). `make docs` serves MkDocs locally; `make docs-test` ensures clean builds.
- `make install` — provision the `uv` virtualenv and install pre-commit hooks.
- `make check` — run Ruff linting/formatting, type analysis, dependency hygiene, and lock verification.
- `make test` — execute `pytest` (with doctests) inside the managed environment.
- `make gen-all` — refresh protocol artifacts when the ACP schema version advances (`ACP_SCHEMA_VERSION=<ref>` to pin an upstream tag).

## Coding Style & Naming Conventions
Target Python 3.10+ with type hints and 120-character lines enforced by Ruff (`pyproject.toml`). Prefer dataclasses/pydantic models from the schema modules rather than bare dicts. Tests may ignore security lint (see per-file ignores) but still follow snake_case names. Keep public API modules under `acp/*` lean; place utilities in internal `_`-prefixed modules when needed.
- Target Python 3.10+ with four-space indentation and type hints on public APIs.
- Ruff enforces formatting and lint rules (`uv run ruff check`, `uv run ruff format`); keep both clean before publishing.
- Prefer dataclasses or generated Pydantic models from `acp.schema` over ad-hoc dicts. Place shared utilities in `_`-prefixed internal modules.
- Prefer the builders in `acp.helpers` (for example `text_block`, `start_tool_call`) when constructing ACP payloads. The helpers instantiate the generated Pydantic models for you, keep literal discriminator fields out of call sites, and stay in lockstep with the schema thanks to the golden tests (`tests/test_golden.py`).

## Testing Guidelines
Pytest is the main framework with `pytest-asyncio` for coroutine tests and doctests activated on modules. Name test files `test_*.py` and co-locate fixtures under `tests/conftest.py`. Aim to cover new protocol surfaces with integration-style tests using the async agent stubs. Generate coverage reports via `tox -e py310` when assessing CI parity.
- Tests live in `tests/` and must be named `test_*.py`. Use `pytest.mark.asyncio` for coroutine coverage.
- Run `make test` (or `uv run python -m pytest`) prior to commits; include reproducing steps for any added fixtures.
- Gemini CLI coverage is disabled by default. Set `ACP_ENABLE_GEMINI_TESTS=1` (and `ACP_GEMINI_BIN=/path/to/gemini`) to exercise `tests/test_gemini_example.py`.

## Commit & Pull Request Guidelines
Commit history follows Conventional Commits (`feat:`, `fix:`, `docs:`). Scope commits narrowly and include context on affected protocol version or tooling. PRs should describe agent behaviors exercised, link related issues, and mention schema regeneration if applicable. Attach test output (`make check` or targeted pytest) and screenshots only when UI-adjacent docs change. Update docs/examples when altering the public agent API.
- Follow Conventional Commits (`feat:`, `fix:`, `docs:`, etc.) with succinct scopes, noting schema regenerations when applicable.
- PRs should describe exercised agent behaviours, link relevant issues, and include output from `make check` or focused pytest runs.
- Update documentation and examples whenever public APIs or transport behaviours change, and call out environment prerequisites for new integrations.

## Agent Integration Tips
Leverage `examples/mini_swe_agent/` as a template when bridging other command executors. Use `AgentSideConnection` with `stdio_streams()` for ACP-compliant clients; document any extra environment variables in README updates.
- Bootstrap agents from `examples/echo_agent.py` or `examples/agent.py`; pair with `examples/client.py` for round-trip validation.
- Use `spawn_agent_process` / `spawn_client_process` to embed ACP parties directly in Python applications.
- Validate new transports against `tests/test_rpc.py` and, when applicable, the Gemini example to ensure streaming updates and permission flows stay compliant.
121 changes: 106 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<a href="https://agentclientprotocol.com/" >
<img alt="Agent Client Protocol" src="https://zed.dev/img/acp/banner-dark.webp">
</a>

# Agent Client Protocol (Python)

Python SDK for the Agent Client Protocol (ACP). Build agents that speak ACP over stdio so tools like Zed can orchestrate them.
Expand All @@ -6,9 +10,11 @@ Python SDK for the Agent Client Protocol (ACP). Build agents that speak ACP over

**Highlights**

- Typed dataclasses generated from the upstream ACP schema (`acp.schema`)
- Async agent base class plus stdio transport helpers for quick bootstrapping
- Included examples that stream content updates and tool calls end-to-end
- Generated `pydantic` models that track the upstream ACP schema (`acp.schema`)
- Async base classes and JSON-RPC plumbing that keep stdio agents tiny
- Process helpers such as `spawn_agent_process` for embedding agents and clients directly in Python
- Batteries-included examples that exercise streaming updates, file I/O, and permission flows
- Optional Gemini CLI bridge (`examples/gemini.py`) for the `gemini --experimental-acp` integration

## Install

Expand All @@ -29,29 +35,75 @@ uv add agent-client-protocol

Prefer a step-by-step walkthrough? Read the [Quickstart guide](docs/quickstart.md) or the hosted docs: https://psiace.github.io/agent-client-protocol-python/.

### Launching from Python

Embed the agent inside another Python process without spawning your own pipes:

```python
import asyncio
import sys
from pathlib import Path

from acp import spawn_agent_process, text_block
from acp.schema import InitializeRequest, NewSessionRequest, PromptRequest


async def main() -> None:
agent_script = Path("examples/echo_agent.py")
async with spawn_agent_process(lambda _agent: YourClient(), sys.executable, str(agent_script)) as (conn, _proc):
await conn.initialize(InitializeRequest(protocolVersion=1))
session = await conn.newSession(NewSessionRequest(cwd=str(agent_script.parent), mcpServers=[]))
await conn.prompt(
PromptRequest(
sessionId=session.sessionId,
prompt=[text_block("Hello!")],
)
)


asyncio.run(main())
```

`spawn_client_process` mirrors this pattern for the inverse direction.

### Minimal agent sketch

```python
import asyncio

from acp import Agent, AgentSideConnection, PromptRequest, PromptResponse, SessionNotification, stdio_streams
from acp.schema import AgentMessageChunk, TextContentBlock
from acp import (
Agent,
AgentSideConnection,
InitializeRequest,
InitializeResponse,
NewSessionRequest,
NewSessionResponse,
PromptRequest,
PromptResponse,
session_notification,
stdio_streams,
text_block,
update_agent_message,
)


class EchoAgent(Agent):
def __init__(self, conn):
self._conn = conn

async def initialize(self, params: InitializeRequest) -> InitializeResponse:
return InitializeResponse(protocolVersion=params.protocolVersion)

async def newSession(self, params: NewSessionRequest) -> NewSessionResponse:
return NewSessionResponse(sessionId="sess-1")

async def prompt(self, params: PromptRequest) -> PromptResponse:
for block in params.prompt:
text = getattr(block, "text", "")
text = block.get("text", "") if isinstance(block, dict) else getattr(block, "text", "")
await self._conn.sessionUpdate(
SessionNotification(
sessionId=params.sessionId,
update=AgentMessageChunk(
sessionUpdate="agent_message_chunk",
content=TextContentBlock(type="text", text=text),
),
session_notification(
params.sessionId,
update_agent_message(text_block(text)),
)
)
return PromptResponse(stopReason="end_turn")
Expand All @@ -71,15 +123,54 @@ Full example with streaming and lifecycle hooks lives in [examples/echo_agent.py

## Examples

- `examples/mini_swe_agent`: bridges mini-swe-agent into ACP, including a duet launcher and Textual TUI client
- Additional transport helpers are documented in the [Mini SWE guide](docs/mini-swe-agent.md)
- `examples/echo_agent.py`: the canonical streaming agent with lifecycle hooks
- `examples/client.py`: interactive console client that can launch any ACP agent via stdio
- `examples/agent.py`: richer agent showcasing initialization, authentication, and chunked updates
- `examples/duet.py`: launches both example agent and client using `spawn_agent_process`
- `examples/gemini.py`: connects to the Gemini CLI in `--experimental-acp` mode, with optional auto-approval and sandbox flags

## Helper APIs

Use `acp.helpers` to build protocol payloads without manually shaping dictionaries:

```python
from acp import start_tool_call, text_block, tool_content, update_tool_call

start = start_tool_call("call-1", "Inspect config", kind="read", status="pending")
update = update_tool_call(
"call-1",
status="completed",
content=[tool_content(text_block("Inspection finished."))],
)
```

Helpers cover content blocks (`text_block`, `resource_link_block`), embedded resources, tool calls (`start_edit_tool_call`, `update_tool_call`), and session updates (`update_agent_message_text`, `session_notification`).

## Documentation

- Project docs (MkDocs): https://psiace.github.io/agent-client-protocol-python/
- Local sources: `docs/`
- [Quickstart](docs/quickstart.md)
- [Mini SWE Agent bridge](docs/mini-swe-agent.md)
- [Releasing](docs/releasing.md)

## Gemini CLI bridge

Want to exercise the `gemini` CLI over ACP? The repository includes a Python replica of the Go SDK's REPL:

```bash
python examples/gemini.py --yolo # auto-approve permissions
python examples/gemini.py --sandbox --model gemini-2.5-pro
```

Defaults assume the CLI is discoverable via `PATH`; override with `--gemini` or `ACP_GEMINI_BIN=/path/to/gemini`.

The smoke test (`tests/test_gemini_example.py`) is opt-in to avoid false negatives when the CLI is unavailable or lacks credentials. Enable it locally with:

```bash
ACP_ENABLE_GEMINI_TESTS=1 ACP_GEMINI_BIN=/path/to/gemini uv run python -m pytest tests/test_gemini_example.py
```

The test gracefully skips when authentication prompts (e.g. missing `GOOGLE_CLOUD_PROJECT`) block the interaction.

## Development workflow

Expand Down
34 changes: 28 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
<a href="https://agentclientprotocol.com/" >
<img alt="Agent Client Protocol" src="https://zed.dev/img/acp/banner-dark.webp">
</a>

# Agent Client Protocol SDK (Python)

Welcome to the Python SDK for the Agent Client Protocol (ACP). The package ships ready-to-use transports, typed protocol models, and examples that stream messages to ACP-aware clients such as Zed.

## What you get

- Fully typed dataclasses generated from the upstream ACP schema (`acp.schema`)
- Async agent base class and stdio helpers to spin up an agent in a few lines
- Examples that demonstrate streaming updates and tool execution over ACP
- Pydantic models generated from the upstream ACP schema (`acp.schema`)
- Async agent/client wrappers with JSON-RPC task supervision built in
- Process helpers (`spawn_agent_process`, `spawn_client_process`) for embedding ACP nodes inside Python applications
- Helper APIs in `acp.helpers` that mirror the Go/TS SDK builders for content blocks, tool calls, and session updates. They instantiate the generated Pydantic types for you, so call sites stay concise without sacrificing validation.
- Examples that showcase streaming updates, file operations, permission flows, and even a Gemini CLI bridge (`examples/gemini.py`)

## Getting started

Expand All @@ -20,11 +26,27 @@ Welcome to the Python SDK for the Agent Client Protocol (ACP). The package ships
```
3. Point your ACP-capable client at the running process (for Zed, configure an Agent Server entry). The SDK takes care of JSON-RPC framing and lifecycle transitions.

Prefer a guided tour? Head to the [Quickstart](quickstart.md) for step-by-step instructions, including how to run the agent from an editor or terminal.
Prefer a guided tour? Head to the [Quickstart](quickstart.md) for terminal, editor, and programmatic launch walkthroughs.

## Gemini CLI bridge

If you have access to the Gemini CLI (`gemini --experimental-acp`), run:

```bash
python examples/gemini.py --yolo
```

Flags mirror the Go SDK example:

- `--gemini /path/to/cli` or `ACP_GEMINI_BIN` to override discovery
- `--model`, `--sandbox`, `--debug` forwarded verbatim
- `--yolo` auto-approves permission prompts with sensible defaults

An opt-in smoke test lives at `tests/test_gemini_example.py`. Enable it with `ACP_ENABLE_GEMINI_TESTS=1` (and optionally `ACP_GEMINI_TEST_ARGS`) when the CLI is authenticated; otherwise the test stays skipped.

## Documentation map

- [Quickstart](quickstart.md): install, run, and extend the echo agent
- [Mini SWE Agent guide](mini-swe-agent.md): bridge mini-swe-agent over ACP, including duet launcher and Textual client
- [Quickstart](quickstart.md): install, run, and embed the echo agent, plus next steps for extending it
- [Releasing](releasing.md): schema upgrade workflow, version bumps, and publishing checklist

Source code lives under `src/acp/`, while tests and additional examples are available in `tests/` and `examples/`. If you plan to contribute, see the repository README for the development workflow.
54 changes: 0 additions & 54 deletions docs/mini-swe-agent.md

This file was deleted.

Loading