Skip to content

Root Channel

The root channel is the top-level channel every AHP server exposes. It carries global state — the agents the server provides, the terminals it manages, and host-level configuration — plus the catalogue events for sessions.

ahp-root://

Exactly one root channel exists per server. Clients SHOULD subscribe to it during the handshake via initialSubscriptions to receive the agent list, terminal list, and host config in the same round-trip.

Subscribers receive a RootState snapshot:

RootState {
agents: AgentInfo[]
activeSessions?: number
terminals?: TerminalInfo[]
config?: RootConfigState
}
  • agents — agent backends the server can speak to, including any protectedResources they require for authentication. See Authentication.
  • activeSessions — count of non-disposed sessions. Lightweight badge counter.
  • terminals — lightweight per-terminal metadata for rendering a terminal manager UI without subscribing to every terminal. See Terminal Channel for the full state.
  • config — host-level configuration schema and current values.

The session list is not part of root state. Clients fetch it imperatively via listSessions and patch it from root/* notifications described below.

A large catalogue can be fetched incrementally. listSessions accepts an optional limit (the maximum number of entries the client wants in the page — the server SHOULD respect it, but MAY return fewer and MAY impose its own upper cap) and an optional opaque cursor. The result carries the page in items plus an optional nextCursor:

  • To fetch the first page, omit cursor. Supply limit to bound the page size.
  • If the result includes a nextCursor, more entries exist — pass it back as cursor on the next call to fetch the following page.
  • A missing nextCursor signals the end of the catalogue.

The cursor is opaque and server-defined: the server picks the ordering and keyset. Clients MUST NOT parse, modify, or persist a cursor across connections. An unrecognised cursor SHOULD be rejected with an InvalidParams error. The server SHOULD return most-recently-modified entries first, so the first page is the immediately useful one.

Pagination is fully additive. A client that omits limit/cursor and ignores nextCursor sees the pre-pagination behaviour (subject to any server-imposed cap), and a server that does not paginate ignores the inputs and returns everything in one page. Pagination governs only the initial and backfill fetches — the root/session* notifications keep an already-loaded page live exactly as before.

This section lists wire methods that are interpreted in the context of ahp-root://. If params.channel is some other URI, they are handled by the target channel instead.

Method Kind Why it belongs on root
initialize request Connection-level handshake command; scoped to the root channel.
ping request Connection liveness check; scoped to the root channel.
reconnect request Connection resume/replay negotiation; scoped to the root channel.
listSessions request Session catalogue lives on root (root/session* events keep the cache fresh).
resourceRead request Filesystem/content access is connection-level, not session-local. May also be issued server → client to fetch from a client-published URI.
resourceWrite request Filesystem/content access is connection-level, not session-local. May also be issued server → client for host-driven per-session FS providers.
resourceList request Filesystem/content access is connection-level, not session-local. May also be issued server → client.
resourceCopy request Filesystem/content access is connection-level, not session-local. May also be issued server → client.
resourceDelete request Filesystem/content access is connection-level, not session-local. May also be issued server → client.
resourceMove request Filesystem/content access is connection-level, not session-local. May also be issued server → client.
resourceResolve request stat + realpath combination; throws NotFound for missing URIs. May also be issued server → client.
resourceMkdir request mkdir -p semantics. May also be issued server → client.
resourceRequest request Permission grant/revocation flow is connection-level. Symmetrical: either peer MAY initiate.
createResourceWatch request Opens a file-change watcher; the receiver returns an ahp-resource-watch:/<id> channel. May also be issued server → client to watch a client-side URI. The watcher is released when subscribers unsubscribe — no explicit dispose call.
authenticate request Bearer-token push for protected resources is connection-level.
resolveSessionConfig request Pre-creation config resolution happens before any session channel exists.
sessionConfigCompletions request Completes dynamic fields in pre-creation session config.

Notifications (params.channel = "ahp-root://")

Section titled “Notifications (params.channel = "ahp-root://")”
Method Kind Meaning
action server → client notification Root-scoped action envelope (root/* action payloads).
root/sessionAdded server → client notification Session catalogue entry created.
root/sessionRemoved server → client notification Session catalogue entry removed.
root/sessionSummaryChanged server → client notification Session catalogue entry mutated.
root/progress server → client notification Generic progress for a long-running operation a client opted into (e.g. an SDK download).
unsubscribe client → server notification Stop receiving root-channel messages.
dispatchAction client → server notification Dispatch a root-scoped client action (currently root/configChanged).

auth/required may also be emitted on ahp-root:// when the auth requirement is root-scoped; see Authentication.

Root state is mutated by action envelopes broadcast on this channel. Refer to the Root Channel Reference for the full list; the root-scoped actions are:

Action Direction Reducer effect
root/agentsChanged Server Replaces agents
root/activeSessionsChanged Server Replaces activeSessions
root/terminalsChanged Server Replaces terminals
root/configChanged Server / Client Merges (or replaces) config.values

All root-scoped action envelopes have channel: "ahp-root://".

In addition to action envelopes, the server pushes per-session catalogue events to subscribers of ahp-root://. These notifications keep cached session lists in sync without subscribing to every session URI individually.

Emitted when a new session is created.

{
"jsonrpc": "2.0",
"method": "root/sessionAdded",
"params": {
"channel": "ahp-root://",
"summary": {
"resource": "ahp-session:/<uuid>",
"title": "New Session",
"status": 1,
"createdAt": "2024-03-09T16:00:00.000Z",
"modifiedAt": "2024-03-09T16:00:00.000Z"
}
}
}

Emitted when a session is disposed.

{
"jsonrpc": "2.0",
"method": "root/sessionRemoved",
"params": {
"channel": "ahp-root://",
"session": "ahp-session:/<uuid>"
}
}

Emitted when any mutable field on an existing SessionSummary changes (title, status, modifiedAt, working directory, read/done state, change statistics, …). Only the changed fields are carried; identity fields (resource, provider, createdAt) never change and MUST be omitted.

{
"jsonrpc": "2.0",
"method": "root/sessionSummaryChanged",
"params": {
"channel": "ahp-root://",
"session": "ahp-session:/<uuid>",
"changes": {
"title": "Refactor auth middleware",
"status": 8,
"modifiedAt": "2024-03-09T16:02:03.456Z"
}
}
}

Servers MAY coalesce or debounce this notification for noisy fields — for example, rapid modifiedAt bumps during a streaming turn, or frequent changes updates during an edit burst. Clients that have no cached entry for session MAY ignore the notification.

Like all protocol notifications, the root/* events are ephemeral and are not replayed on reconnect. After reconnecting, clients SHOULD re-fetch the catalogue via listSessions.

The server MAY emit root/progress to report incremental progress on a long-running operation a client opted into — most notably the lazy, first-use download of an agent’s native SDK. A client opts in by supplying a progressToken on the originating request (today the progressToken field of createSession); the server echoes that token on every frame so the client can correlate progress back to the call and the UI awaiting it. The notification is operation-agnostic — it names no domain object.

{
"jsonrpc": "2.0",
"method": "root/progress",
"params": {
"channel": "ahp-root://",
"progressToken": "9b2c1f7e-4a0d-4e2b-8b1a-2f7e4a0d4e2b",
"progress": 18874368,
"total": 41957498,
"message": "Downloading Claude agent…"
}
}

progress is monotonically non-decreasing for a given progressToken. total is present only when the magnitude is known up front (e.g. a Content-Length); when absent, clients SHOULD show an indeterminate indicator. The operation is complete when progress === total — the server MUST emit a final frame satisfying this, setting total to the final progress when the total was never known, after which no further frames reference the token. An optional message carries a human-readable description of the work in progress; a client that tracks the token renders its own (localized) label and MAY ignore it, while a generic client MAY display message verbatim. The server MAY emit no progress at all (for example when the work was already done), in which case the client simply never shows an indicator. Like the catalogue events, root/progress is ephemeral and is not replayed on reconnect.

The server MAY emit auth/required on the root channel when an agent’s protected resource needs (re-)authentication. See Authentication for the full flow.