car-proto
JSON-RPC 2.0 protocol types for Common Agent Runtime client-server communication.
What it does
Shared serde-defined types used by both car-server-core (server) and any Rust client. Single source of truth for request / response / notification shapes so the server and clients can't drift.
The protocol is bidirectional over WebSocket:
- Client → Server —
session.init,tools.register,proposal.submit,verify, etc. - Server → Client (callback) —
tools.execute(awaits a response) - Server → Client (notification) —
host.event,voice.event(no response expected)
Every connection using the protocol-v3 surface negotiates the exact
PROTOCOL_VERSION through server.handshake after transport
auth. Bundled clients require infer.model-identity.v1 and
models.catalog-identity.v1, send both in required_capabilities, and verify
that both appear in the reply's negotiated_capabilities. Until negotiation
succeeds, handshake-gated methods fail with -32005; a missing, malformed, or
different version fails with -32006, and an unsupported mandatory capability
fails with -32008. Negotiation state belongs to the WebSocket session, so
reconnects negotiate again.
Clients that depend on exact host-managed agent/tool approval overrides require
permissions.agent-tool-overrides.v1 in the handshake. This lets them fail
closed before using the associated WebSocket RPCs against an older daemon.
Rendering an approval for a human
approval_summary turns a HostApprovalRequest's
details into a compact, bounded plain-text summary — labelled recipients,
subject, script source, and so on — so every surface that asks a person to
approve something can say what it is asking about.
It lives here, beside the type it renders, because it is shared by callers that
have no other crate in common: the daemon's iMessage and Slack approval
adapters (car-messaging) and the out-of-workspace Windows tray
(apps/host-windows, which path-depends on this crate for exactly this). Those
surfaces previously each rendered details their own way, or not at all.
summarize_details is the same renderer for a caller holding the approval as
raw JSON rather than as a typed row.
The macOS dashboard has its own Swift implementation (ApprovalPreview in
HostEventsClient.swift); this mirrors its dispatch so the two name the same
fields from the same payload.
Where it fits
If you're building a Rust WebSocket client to talk to car-server, depend on this crate to get type-safe request/response handling. For other languages, the wire format is documented in docs/websocket-protocol.md — reach for raw JSON.