API Reference Raxol Agent Client Protocol v#0.1.0

Copy Markdown View Source

Modules

Elixir/OTP implementation of ACP (Agent Client Protocol) — the JSON-RPC 2.0 protocol spoken between code editors ("clients") and AI coding agents ("agents"). See https://agentclientprotocol.com.

use Raxol.AgentClientProtocol.Agent to implement the agent side of ACP: the process that answers initialize, creates/loads sessions, and serves session/prompt turns.

The negotiated-capability PREDICATE: given a Connection's snapshotted capability tree, decide whether a wire method is negotiated and therefore permitted.

use Raxol.AgentClientProtocol.Client to implement the client side of ACP: the editor/host process that answers permission asks, filesystem, and terminal requests, and receives session/update streaming notifications.

Confines fs/read_text_file / fs/write_text_file handling to a sandbox directory -- backs use Raxol.AgentClientProtocol.Client, fs_sandbox: path (see that module's moduledoc for the option). Not a general-purpose path library: it exists solely to give a minimal client a working filesystem story out of the box.

ONE GenServer per peer link, either role — the correlation + dispatch brain of ACP.

Per-dispatch handler context.

Per-session open-turn state, populated only on a client-role Connection.

Ergonomic DX layer for agent handler code running inside session/prompt turn tasks (the functions a turn_runner closure or one of its subagent tasks actually calls). This module introduces no new runtime semantics: every function here is a thin, documented wrapper over Raxol.AgentClientProtocol.Connection.request/4 (the agent->client filesystem/terminal/permission requests) or Raxol.AgentClientProtocol.Session.post_update/2 / Session.request_permission/2 (the Session-owned turn primitives).

Delivery vocabulary shared by Connection (stamping + direct turn delivery) and Client (turn consumption).

JSON-RPC 2.0 error object, plus the ACP-specific vendor error codes.

Fail-closed attach admission behaviour.

The BEAM-local :authorize bridge — make an in-process attach seam defer to the SAME fail-closed admission funnel (Ext.AttachPolicy.Runner) the untrusted ACP boundary uses.

The DEFAULT deny-by-default attach policy.

THE single fail-closed admission funnel. There is exactly ONE funnel: authorize/2. No second try/catch wrapper exists anywhere — a second funnel with weaker timeout/crash semantics would be a dual-ownership hole.

The capability-token attach policy.

The signing side. Mints RXC1 tokens.

Verifier-side keyring load + validation.

The RXC1 capability token — offline-verifiable detached Ed25519 signature.

The durable session journal — behaviour + live-bus registration facade.

ETS-backed in-memory journal — an implementation of Raxol.AgentClientProtocol.Ext.Journal bound by its OFFSET LAW.

One grow-only journal record.

ONE GenServer per session_id — the SINGLE PUBLISHER of a session's live tail.

The register-before-h attach seam — the correctness core of the reattach extension.

Wire schema structs for the reattach extension's _raxol/* notification vocabulary.

_raxol/session.caught_up: the history→live boundary UX signal (offset = h+1). OPTIONAL, non-load-bearing.

_raxol/session.closed: terminate an ALREADY-REGISTERED subscriber mid-stream. reason is a grow-only string set.

_raxol/session.detach: client→agent voluntary unsubscribe. Idempotent.

_raxol/session.lagged: terminal drop-on-lag. lastOffset is the subscriber's own last forwarded offset; heal by reattaching from lastOffset + 1.

_raxol/session.record: the generic, self-describing delivery frame for every record kind OTHER than session_update (turn_started, turn_completed, session_created, and any kind added later). New record kinds require NO new method rows — readers skip-unknown-kind as a fold.

_raxol/session.steer request: redirect a running turn with new user input WITHOUT killing it, addressed by sessionId. A steer is the sibling of interrupt (kill-now); it injects at the next turn boundary.

_raxol/session.steer response: the synchronous, honest CAS outcome — the full vocabulary a Surface banner renders.

Single source of truth for the ACP method vocabulary: every wire method string, its direction, its JSON-RPC kind, the callback atom used for both the behaviour @callback and the Router dispatch clause, its param/result schema modules, its capability gate, and its layer.

Table-driven JSON-RPC method routing for ACP: decode/4 classifies and type-decodes an inbound wire method + params into a tagged tuple, dispatch/4 calls the matching handler callback, and result_marker/1 tells the sending side how to decode a pending outbound request's response.

JSON-RPC 2.0 primitives for the Agent Client Protocol.

Wraps a Request, Notification, or Response with the required "jsonrpc": "2.0" field, and decodes a raw wire frame into whichever of the three it turns out to be.

JSON-RPC 2.0 Notification object: method + optional params, no id, no response expected.

JSON-RPC 2.0 Request object (id + method + optional params).

JSON-RPC request id: null | integer | string. Wire type is preserved exactly (no coercion between string and integer ids).

JSON-RPC 2.0 Response object: either a result or an error, represented as a tagged tuple {:result, id, result} | {:error, id, error} rather than a struct (a Response is a discriminated union at the wire level, and the two shapes are mutually exclusive per spec).

Agent-side types for the Agent Client Protocol: the initialize/ authenticate handshake, session lifecycle (session/new, session/load, session/set_mode, session/prompt, session/cancel), capability negotiation, and MCP server descriptors.

Authentication-related capabilities supported by the agent: currently just the optional logout leaf. Not in f1729; ported from the pinned oracle schema $defs/AgentAuthCapabilities.

Capabilities declared by the agent in the initialize response.

Tagged union of every response the agent may send back to the client.

A method by which a client may authenticate with an agent.

The authenticate request, sent by the client with the chosen auth method id.

The (empty, besides _meta) response to authenticate.

Tagged union of every notification the client may send to the agent, used for JSON-RPC method-name routing.

Tagged union of every request the client may send to the agent, used for JSON-RPC method-name routing.

A single name=value environment variable for a stdio-launched MCP server.

A single HTTP header for an HTTP/SSE MCP server.

Identifies an agent or client implementation (name, version, optional title).

The initialize request, sent by the client to negotiate protocol version and capabilities.

The initialize response, sent by the agent with its capabilities and supported authentication methods.

The session/load request: replays an existing session's history.

The session/load response: optional mode/model/config-option state.

Capability flag for logout: agent supports the logout method. Not in f1729; ported from the pinned oracle schema $defs/LogoutCapabilities.

MCP transports the agent supports for client-provided MCP servers.

A client-provided MCP server descriptor: tagged union of http, sse (both discriminated by a "type" wire field), and the untagged stdio fallback.

A streamable-HTTP MCP server descriptor.

A stdio-launched MCP server descriptor (the untagged wire variant: no "type" field).

The session/new request: creates a new session rooted at cwd, optionally wiring up MCP servers.

The session/new response: the new session id plus optional mode/model/ config-option state (the latter two are unstable extensions).

Content-block kinds the agent accepts in a session/prompt.

The session/prompt request: a turn's content blocks sent to the agent.

The session/prompt response: why the turn ended.

Session-lifecycle capabilities the agent supports, including the unstable list/fork/resume extensions.

Capability flag for session/close: agent supports closing sessions. Not in f1729; ported from the pinned oracle schema $defs/SessionCloseCapabilities.

Capability flag for session/delete: agent supports deleting sessions from session/list. Not in f1729; ported from the pinned oracle schema $defs/SessionDeleteCapabilities.

A single selectable session mode (e.g. "code", "ask").

The set of available session modes and the one currently active.

The (empty, besides _meta) response to session/set_mode.

Optional annotations for the client (audience, priority, last-modified). Every field is optional and decode-lenient: a malformed value defaults to absent rather than failing the whole Annotations.

Audio provided to or from an LLM.

A single command the agent can execute, as advertised via AvailableCommandsUpdate.

Input specification for an AvailableCommand: an untagged union with a single documented variant, unstructured (free text typed after the command name). Per package convention, tagged-tuple unions don't get a Jason.Encoder impl of their own.

Payload for the SessionUpdate available_commands_update variant: the set of commands the agent can execute has changed. available_commands is decode-lenient, matching the oracle schema's x-deserialize-default-on-error + x-deserialize-skip-invalid-items: a missing/wrong-typed list defaults to [], and items that individually fail to decode are skipped rather than aborting the whole update.

Enum of all possible agent->client requests, with their wire method names.

Capabilities declared by the client at initialize.

Request to create a new terminal and execute a command (terminal/create).

Response containing the ID of the newly created terminal.

File-system capabilities supported by the client.

Request to kill a terminal command without releasing the terminal (terminal/kill).

Response to terminal/kill. Carries no data of its own.

An option presented to the user when the agent requests permission for a tool call.

Hint about the nature of a PermissionOption, so clients can choose appropriate icons/UI treatment.

Request to read content from a text file (fs/read_text_file). Only sent if the client declared the fs.readTextFile capability.

Response containing the contents of a text file.

Request to release a terminal and free its resources (terminal/release).

Response to terminal/release. Carries no data of its own.

The outcome of a permission request: either the prompt turn was cancelled before the user responded, or the user selected one of the offered options. Tagged by the outcome discriminator field on the wire (not a struct in its own right -- see SelectedPermissionOutcome for the _meta-carrying payload of the :selected variant).

Request from the agent asking the client for permission to perform a tool call, sent before a sensitive operation.

Response to a session/request_permission request, carrying the user's decision.

A RequestPermissionOutcome variant: the user selected one of the offered options.

Exit status of a terminal command: an exit code (normal exit) and/or a signal name (killed by signal), independently nullable per the schema-oracle.

Request to get the current output and status of a terminal (terminal/output).

Response containing the terminal output captured so far, and its exit status if the command has completed.

Request to wait for a terminal command to exit (terminal/wait_for_exit).

Response containing the exit status of a terminal command.

Request to write content to a text file (fs/write_text_file). Only sent if the client declared the fs.writeTextFile capability.

Response to fs/write_text_file. Carries no data of its own.

Content blocks represent displayable information in ACP: a tagged union discriminated by a "type" wire key (text | image | audio | resource_link | resource). Named ContentBlock both upstream and here (all other structs ported from content.ex -- Role, Annotations, TextContent, ImageContent, AudioContent, TextResourceContents, BlobResourceContents, EmbeddedResourceResource, EmbeddedResource, ResourceLink -- are separate, bare Schema.* modules, not nested under this one).

A single streamed content block, used as the payload for the SessionUpdate user_message_chunk/agent_message_chunk/ agent_thought_chunk variants.

Cumulative session cost information -- the optional cost field of UsageUpdate.

Payload for the SessionUpdate current_mode_update variant: the session's active mode has changed.

A diff representing file modifications.

The contents of a resource, embedded into a prompt or tool call result.

Resource content that can be embedded in a message (untagged union, discriminated by the presence of a "text" or "blob" wire key).

Extension types for ACP protocol extensibility.

An arbitrary _-prefixed extension notification, not part of the core ACP spec. No reply is expected.

An arbitrary _-prefixed extension request, not part of the core ACP spec. Carries the raw JSON-RPC method name and already-decoded params.

An image provided to or from an LLM.

Minimal, oracle-derived param/result structs for v1.19.0 ACP methods that had no home in the ported f1729 Schema.* layer: session/close, session/delete, logout, session/update (the notification envelope), and the protocol-level $/cancel_request.

The protocol-level $/cancel_request notification: {requestId, _meta}, where requestId is a JSON-RPC request id (null | integer | string, see Raxol.AgentClientProtocol.Rpc.RequestId). Oracle-derived (schema.json CancelRequestNotification); not a port of any upstream f1729 module (f1729 has no $/cancel_request support).

Request parameters for session/close: closes an active session, best- effort cancelling any in-flight work first. Oracle-derived (schema.json CloseSessionRequest); not a port of any upstream f1729 module.

The (empty, besides _meta) response to session/close. Oracle-derived (schema.json CloseSessionResponse).

Request parameters for session/delete: deletes an existing session from session/list. Oracle-derived (schema.json DeleteSessionRequest); not a port of any upstream f1729 module.

The (empty, besides _meta) response to session/delete. Oracle-derived (schema.json DeleteSessionResponse).

The (empty, besides _meta) response to logout. Oracle-derived (schema.json LogoutResponse). See the module doc above for why there is no sibling LogoutRequest in this file.

The session/update notification envelope: {sessionId, update, _meta}, where update is the Raxol.AgentClientProtocol.Schema.SessionUpdate discriminated union (ported separately, session_update.ex). Oracle-derived (schema.json SessionNotification); not a port of any upstream f1729 module — upstream's ACP.SessionNotification envelope was explicitly left unported by agent_types.ex's and session_update.ex's own moduledocs pending whoever wired the routing union it belongs to.

A three-state value type: :undefined, nil (null), or {:value, term}.

An execution plan for accomplishing complex tasks: an ordered list of PlanEntry structs. Per the ACP schema, entries is decode-lenient at both levels: a missing/wrong-typed entries field defaults to [] (never fails the whole plan), and entries that individually fail to decode are skipped rather than aborting the list (x-deserialize-skip-invalid-items).

A single entry in the execution plan. content, priority, and status are all required per the ACP schema (no x-deserialize-default-on-error leniency for this struct's own fields) -- a malformed value for any of them fails the whole entry's decode; the caller (Plan.from_json/1) skips entries that fail to decode rather than failing the whole plan.

A resource that the server is capable of reading.

The sender or recipient of messages and data in a conversation.

The session/update notification's sessionUpdate-discriminated union: real-time feedback the agent streams back to the client during a prompt turn (message/thought chunks, tool call lifecycle, the execution plan, available-command changes, mode changes, and the unstable config-option/ session-info updates).

Text provided to or from an LLM.

Represents a tool call that the language model has requested. Every other type ported from tool_call.ex (ToolKind, ToolCallStatus, ToolCallLocation, Diff, ToolCallTerminal, ToolCallContentWrapper, ToolCallContent, ToolCallUpdateFields, ToolCallUpdate) is a separate, bare Schema.* module, not nested under this one.

Content produced by a tool call: a tagged union discriminated by a "type" wire key (content | diff | terminal).

Standard content block wrapper for tool call content (the "content" variant of ToolCallContent; named Content in the official schema, but kept as ToolCallContentWrapper here to avoid colliding with Schema.ContentBlock, the tagged-union content block type).

A file location being accessed or modified by a tool.

Execution status of a tool call. Every place this enum is used in the ACP schema (ToolCall.status, ToolCallUpdateFields.status) carries x-deserialize-default-on-error: true, so -- like ToolKind -- decode is total and infallible: an unrecognized wire value falls back to the documented default, :pending, rather than failing the enclosing object.

Embeds a terminal created with terminal/create, by its id.

An update to an existing tool call. ToolCallUpdateFields is flattened into the same wire object as toolCallId and _meta (a "serde flatten"), not nested under its own key.

Optional fields that can be updated in a tool call. Every field is optional and decode-lenient per the ACP schema (x-deserialize-default-on-error, plus x-deserialize-skip-invalid-items on the two list fields) -- decode of this struct never fails for a map input. Flattened directly into ToolCallUpdate's wire object (no nested "_meta" of its own; unrecognized fields fold into the parent's _meta).

Categories of tools that can be invoked. An open enum: the ACP schema documents "other" as its explicit default, so an unrecognized wire value decodes to :other rather than failing (no String.to_atom/1 is ever used -- every value is an explicit, whitelisted clause).

Unstable ACP types that are not yet part of the stable protocol surface — the Elixir counterpart of the Rust reference implementation's #[cfg(feature = "unstable_*")]-gated types: session model selection (session/set_model), generic session config options (session/set_config_option), session fork/resume/list (session/fork, session/resume, session/list), and their capability flags. These may be removed or changed at any point; callers should gate their use on the corresponding Raxol.AgentClientProtocol.Schema.AgentTypes. SessionCapabilities fields (:list, :fork, :resume) rather than assuming availability.

Payload for the session/update notification's config_option_update variant: session configuration options have been updated. The variant wiring itself lives in SessionUpdate (ported from client_types.ex, not this file). (Unstable)

Request to fork an existing session (session/fork). (Unstable)

Response from forking a session: the new session id plus optional mode/model/config-option state. (Unstable)

Request to list existing sessions (session/list). (Unstable)

Response from listing sessions. (Unstable)

Information about a selectable model. (Unstable)

Request to resume an existing session without replaying its history (session/resume). (Unstable)

Response from resuming a session: optional mode/model/config-option state. (Unstable)

Type-specific session configuration option payload: a tagged union by the wire "type" field. Currently only :select is defined by the spec. (Unstable)

A session configuration option selector and its current state. The kind-specific payload (currently only select) is flattened directly into this struct's top-level wire object alongside id/name/etc. (Unstable)

Semantic category for a session configuration option. (Unstable)

A single-value selector (dropdown) session configuration option payload. (Unstable)

A named group of SessionConfigSelectOptions. (Unstable)

A possible value for a select-kind session configuration option. (Unstable)

Possible values for a select-kind session configuration option: an untagged union of either a flat list of options ({:ungrouped, [...]}) or a list of groups ({:grouped, [...]}), distinguished on decode by whether the first list element has a "group" key. (Unstable)

Capability flag for session/fork. (Unstable)

Information about a session returned by session/list. (Unstable)

Payload for the session/update notification's session_info_update variant: a partial update to session metadata. The variant wiring itself lives in SessionUpdate (ported from client_types.ex, not this file).

Capability flag for session/list. (Unstable)

The set of selectable models and the one currently active. (Unstable)

Capability flag for session/resume. (Unstable)

Request to set a session configuration option value (session/set_config_option). (Unstable)

Response to session/set_config_option: the full, refreshed set of config options. (Unstable)

Request to set the active model for a session (session/set_model). (Unstable)

The (empty, besides _meta) response to session/set_model. (Unstable)

Unstructured command input: raw free text typed after the command name, as a hint for what's expected.

Payload for the SessionUpdate usage_update variant: a context-window and cost update for a session -- tokens currently in context (used), the total context window size (size), and an optional cumulative session cost.

Protocol version identifier for ACP (protocolVersion on the wire).

One GenServer per session_id: the ACP turn state machine.

The Session emit seam — one injection point through which every session/update and every turn boundary flows.

The DEFAULT emitter. emit/2 forwards a session/update to Connection.notify on the same FIFO lane as the eventual prompt reply; the turn-boundary hooks are no-ops (it keeps no durable journal). Selecting this emitter (or omitting :emitter) means the reattach extension is OFF.

The durable emitter — reroutes updates and turn boundaries through the single-publisher Writer (Ext.Journal.Writer) so the session's durable, offset-addressed journal is FILLED by live turns, and every attached reattacher replays it.

The Session's steer seam — the one injection point through which a live turn's compare-and-swap steer decision is driven.

The DEFAULT steer adapter — refuses. With no injected :steer_adapter, the turn hooks are the identity function (they never touch steer_state, which stays nil), and resolve/2 answers {:error, :no_steer_channel} — an honest refusal: no live steering owner is wired.

Ephemeral per-turn state, held by a Raxol.AgentClientProtocol.Session only while a session/prompt turn is in flight. outcome is written once by the root leg; the cancel leg overwrites it.

The classified registry of every :telemetry event this package emits.

Behaviour for pluggable ACP message carriers.

A pure, process-free sequencing envelope for unordered-carrier transports (no shipped transport uses it; see Raxol.AgentClientProtocol.Transport.Reassembly for the receive-side counterpart).

A pure, process-free NDJSON (newline-delimited JSON) line framer.

An in-process, zero-copy pair of Raxol.AgentClientProtocol.Transport handles. This is the test backbone for the rest of the library and the BEAM-local wiring for an agent/client pair that live in the same VM.

A pure, process-free reorder buffer for unordered-carrier transports (pairs with Raxol.AgentClientProtocol.Transport.Envelope on the send side; no shipped transport uses it).

Newline-delimited JSON (NDJSON) over a stdio pipe — either our OWN process's real stdin/stdout (:self mode, when this BEAM process IS the ACP agent/client speaking on its own stdio), or a spawned peer command's stdio (:spawn mode, when we launch and speak to a subprocess).

The package OTP application — the single shared supervision tree that the per-connection subtrees and the reattach extension depend on.

Mix Tasks

Recomputes the SHA256 of the vendored ACP (Agent Client Protocol) schema oracle files under priv/schema-oracle/v1/ and compares them against the hashes recorded at pin time (see priv/schema-oracle/PINNED.md).