Experimental Contrib Modules¶
The helpers under
acp.contribcapture patterns we observed in reference integrations such as Toad and kimi-cli. Every API here is experimental and may change without notice.
SessionAccumulator¶
Module: acp.contrib.session_state
UI surfaces like Toad need a live, merged view of the latest tool calls, plan entries, and message stream. The core SDK only emits raw SessionNotification payloads, so applications usually end up writing their own state layer. SessionAccumulator offers that cache out of the box.
Capabilities:
SessionAccumulator.apply(notification)mergestool_callandtool_call_updateevents, backfilling a missing start message when necessary.- Each call to
snapshot()returns an immutableSessionSnapshot(Pydantic model) containing the active plan, current mode ID, available commands, and historical user/agent/thought chunks. subscribe(callback)wires a lightweight observer that receives every new snapshot, making it easy to refresh UI widgets.- Automatic reset when a different session ID arrives (configurable via
auto_reset_on_session_change).
Integration tip: create one accumulator per UI controller. Feed every
SessionNotificationthrough it, then render fromsnapshot.tool_callsorsnapshot.user_messagesinstead of mutating state manually.
ToolCallTracker & PermissionBroker¶
Modules: acp.contrib.tool_calls and acp.contrib.permissions
Agent-side runtimes (for example kimi-cli) are responsible for synthesising tool call IDs, streaming argument fragments, and formatting permission prompts. Managing bare Pydantic models quickly devolves into boilerplate; these helpers centralise the bookkeeping.
ToolCallTracker.start()/progress()/append_stream_text()manages tool call state and emits canonicalToolCallStart/ToolCallProgressmessages. The tracker also exposesview()(immutableTrackedToolCallView) andtool_call_model()for logging or permission prompts.PermissionBroker.request_for()wrapsrequestPermissionRPCs. It reuses the tracker’s state (or an explicitToolCall), applies optional extra content, and defaults to a standard Approve / Approve for session / Reject option set.default_permission_options()exposes that canonical option triple so applications can customise or extend it.
Integration tip: keep a single tracker alongside your agent loop. Emit tool call notifications through it, and hand the tracker to
PermissionBrokerso permission prompts stay in sync with the latest call state.
Design Guardrails¶
To stay aligned with the ACP schema, the contrib layer follows a few rules:
- Protocol types continue to live in
acp.schema. Contrib code always copies them via.model_copy(deep=True)to avoid mutating shared instances. - Helpers are opt-in; the core package never imports them implicitly and imposes no UI or agent framework assumptions.
- Implementations focus on the common pain points (tool call aggregation, permission requests) while leaving business-specific policy to the application.
Try the contrib modules in your agent or client, and open an issue/PR with feedback so we can decide which pieces should graduate into the stable surface.