name: sync-acp-spec description: Sync the ACP (Agent Client Protocol) schema implementation with the official reference repo by comparing Rust source types against our Python Pydantic models.
Sync ACP Spec
Keep src/acp/schema/ aligned with the official Agent Client Protocol reference implementation.
Steps
Clone the reference repo into a temporary directory:
tmp=$(mktemp -d) git clone --depth 1 https://github.com/agentclientprotocol/agent-client-protocol "$tmp/acp"Identify new commits since last sync:
git -C "$tmp/acp" log --oneline <SPEC_SYNCED_COMMIT>..HEADThe synced commit hash is stored as
SPEC_SYNCED_COMMITinsrc/acp/__init__.py.Read the upstream Rust source (the authoritative types):
$tmp/acp/src/agent.rs— agent-side types: capabilities, auth methods, session state, config options, slash commands, content blocks, session updates, MCP servers$tmp/acp/src/client.rs— client-side types: client capabilities, requests, responses$tmp/acp/src/error.rs— error codes andErrorstruct$tmp/acp/src/content.rs— content block types$tmp/acp/src/tool_call.rs— tool call types$tmp/acp/src/plan.rs— plan entry types$tmp/acp/src/rpc.rs— JSON-RPC message types, method strings$tmp/acp/src/ext.rs— extension notifications$tmp/acp/src/version.rs— protocol version constant$tmp/acp/schema/schema.jsonandschema.unstable.json— JSON Schema (useful for cross-checking)
Compare with our Python implementation (mapping table):
Upstream Rust file Our Python module agent.rs(capabilities)schema/capabilities.pyagent.rs(auth, common types)schema/common.pyagent.rs(session updates)schema/session_updates.pyagent.rs(session state)schema/session_state.pyagent.rs(slash commands)schema/slash_commands.pyagent.rs(MCP servers)schema/mcp.pyagent.rs(responses)schema/agent_responses.pyagent.rs(requests to client)schema/agent_requests.pyclient.rs(requests)schema/client_requests.pyclient.rs(responses)schema/client_responses.pyclient.rs(capabilities)schema/capabilities.pycontent.rsschema/content_blocks.pytool_call.rsschema/tool_call.pyplan.rsschema/agent_plan.pyrpc.rsschema/messages.pyext.rsschema/notifications.pyerror.rsschema/common.py(Error),exceptions.py(RequestError)version.rsschema/__init__.py(PROTOCOL_VERSION)Apply updates to our code:
- Add new Pydantic model fields matching new Rust struct fields
- Map
#[cfg(feature = "unstable_*")]fields tofield: Type | None = None - Add new types / enums / discriminated unions
- Update
Literaltypes for new method strings inschema/messages.py - Update
__init__.pyexports in bothschema/__init__.pyandacp/__init__.py - Preserve our
camelCasealias convention (alias_generator=to_camelin base) - Do NOT modify protocol logic outside
schema/(connection handlers, bridge, transports) — only update those if they need to handle new schema types
Wire up new schema types in the protocol layer (if needed):
agent/connection.py— add dispatch cases for new agent methodsclient/connection.py— add client-side methods for new requestsbridge/bridge.py— add bridge handler casesagent/protocol.py— add methods to theAgentprotocolagent/implementations/testing.py— add stubs toTestAgentagent/implementations/debug_server/mock_agent.py— add stubs toMockAgent
Wire up in the ACP server (if needed):
src/agentpool_server/acp_server/acp_agent.py— implement new methods, advertise new capabilitiessrc/agentpool_server/acp_server/event_converter.py— emit new session update typessrc/agentpool_server/acp_server/session.py— store new state
Update the synced commit hash in
src/acp/__init__.py:git -C "$tmp/acp" rev-parse HEADUpdate the
SPEC_SYNCED_COMMITconstant to the new hash.Clean up:
rm -rf "$tmp"
Key conventions
- Rust
#[serde(rename_all = "camelCase")]→ handled by ouralias_generator=to_camelinSchemabase - Rust
#[serde(rename = "_meta")]→ handled by ourconvert()function (field_meta→_meta) - Rust
Option<T>→T | None = None - Rust
#[serde(default)]booleans →bool = Falseorbool | None = False - Rust
#[serde(tag = "type")]enums → Pydantic discriminated unions withDiscriminator() - Rust
#[serde(untagged)]variants →Field(exclude=True)on thetypediscriminator field - Rust
Vec<T>→Sequence[T](for inputs) orlist[T] - Rust
HashMap<K, V>→dict[K, V] - Unstable features (
#[cfg(feature = "unstable_*")]) → always included, marked with**UNSTABLE**docstrings
What NOT to change
connection.py(base JSON-RPC connection) — only if the wire protocol itself changestransports.py— transport layer is our ownstdio.py— our process management layerclient/implementations (DefaultACPClient,HeadlessACPClient,NoOpClient) — agentpool-specificregistry/— our agent registry, not part of ACP spectask/— our task abstractiontool_call_reporter.py,tool_call_state.py— our extensionsfilesystem.py— our filesystem handler implementation