ACP native bridge¶
Bernstein speaks the Agent Client Protocol natively — editors that ship ACP support can plug Bernstein in as their backend with zero per-IDE plumbing.
The bridge is a protocol adapter: ACP prompt opens a Bernstein task, streamUpdate notifications tail the existing streaming-merge utility, cancel walks the standard drain pipeline, and setMode toggles the janitor approval gate. Cost-aware routing, HMAC audit, and sandbox-backend selection apply identically to ACP-initiated and CLI-initiated sessions.
Transports¶
| Transport | When to use | Command |
|---|---|---|
| stdio (line-delimited JSON-RPC) | IDE embedding (default) | bernstein acp serve --stdio |
| HTTP / SSE | remote IDEs, CI, debugging | bernstein acp serve --http :8062 |
Stdio is the canonical IDE transport: the editor spawns bernstein acp serve --stdio as a subprocess and exchanges line-delimited JSON-RPC frames over its stdio pipes. The HTTP transport accepts a single JSON-RPC frame per POST /acp request and supports Accept: text/event-stream for streaming responses.
Zed settings.json¶
{
"agent_servers": {
"bernstein": {
"command": "bernstein",
"args": ["acp", "serve", "--stdio"],
"env": {}
}
}
}
Generic ACP client (any editor)¶
{
"name": "bernstein",
"transport": "stdio",
"command": ["bernstein", "acp", "serve", "--stdio"],
"protocolVersion": "2025-04-01"
}
For HTTP-mode integrations, point the client at http://127.0.0.1:8062/acp and set Accept: text/event-stream to receive streaming streamUpdate and requestPermission notifications.
Methods supported¶
| Method | Direction | Notes |
|---|---|---|
initialize | client → server | reports server capabilities, available adapters, and configured sandbox backends |
initialized | client → server (notification) | acknowledged silently |
prompt | client → server | opens a task in the existing task store; returns a real Bernstein session id |
streamUpdate | server → client (notification) | tails the streaming-merge utility |
cancel | client → server | walks the standard drain + shutdown pipeline |
setMode | client → server | toggles auto (always-allow) ↔ manual (interactive approval gate) |
requestPermission | server → client (prompt) and client → server (decision) | maps onto the janitor approval gate |
Observability¶
Two Prometheus metrics ship with the bridge:
bernstein_acp_messages_total{method, outcome}— JSON-RPC message count partitioned by method and outcome (ok,error,rejected,cancelled,permission_denied).bernstein_acp_active_sessions— gauge of live ACP sessions.
Both are exported via the existing observability stack — the running task server's /metrics endpoint scrapes them automatically.
Audit¶
Every ACP-driven mutation produces an HMAC-chained audit entry that is byte-identical (modulo timestamp + chain HMAC) to the entry the CLI surface emits for the same operation. See tests/integration/acp/test_audit_parity.py for the parity guard.
Out of scope (v1.9)¶
- Windows named-pipe transport — POSIX stdio + HTTP only.
- Bidirectional file-edit primitives that are not in the ratified ACP spec — those track in a follow-up.
- ACP authentication beyond loopback — remote HTTP usage rides the existing tunnel wrapper.