# car-proto
JSON-RPC 2.0 protocol types for [Common Agent Runtime](https://github.com/Parslee-ai/car) 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`](src/lib.rs) 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`](src/approval_summary.rs) 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`](../../../docs/websocket-protocol.md) — reach for raw JSON.