> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# JSON-RPC stdio server

> Stateful JSON-RPC 2.0 interface for stdio, TCP, and optional live-channel WebSocket hosting.

Meerkat exposes a JSON-RPC 2.0 surface for IDE integration, desktop apps, and automation tools. Stdio is the default, and the binary also supports TCP plus an optional live-channel WebSocket listener (`--live-ws`). Unlike REST and MCP, the RPC server keeps agents alive between turns for fast multi-turn conversations.

The RPC surface is fully runtime-backed:

* `keep_alive` is runtime/session behavior
* `session/external_event` queues runtime-backed external work
* committed success is not rewritten to cancellation

## Getting started

<Steps>
  <Step title="Start the server">
    ```bash theme={null}
    rkat-rpc
    ```

    The server reads newline-delimited JSON (JSONL) from stdin and writes JSONL to stdout. Each line is a complete JSON-RPC 2.0 message.

    Optional listener modes:

    ```bash theme={null}
    rkat-rpc --tcp 127.0.0.1:9001
    rkat-rpc --tcp 127.0.0.1:9001 --live-ws 127.0.0.1:9002
    ```

    TCP and live WebSocket listeners are local-only by default. Binding
    a non-loopback address such as `0.0.0.0:9001` requires `--allow-remote`;
    that flag only opts in to network exposure and does not add
    authentication or encryption. Use it behind a production-safe transport
    wrapper such as SSH tunneling, mTLS, or another authenticated encrypted
    channel. Plain TCP host capabilities continue to report
    `secure_remote_rpc: false`.

    `rkat-rpc --tcp` is a JSON-RPC host transport. It is not the signed
    Meerkat peer/comms channel used by remote agents or external mob members;
    use `rkat run --comms-listen-tcp ...` for that.
  </Step>

  <Step title="Send the handshake">
    ```json theme={null}
    {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
    ```
  </Step>

  <Step title="Create a session">
    ```json theme={null}
    {"jsonrpc":"2.0","id":2,"method":"session/create","params":{"prompt":"Hello!"}}
    ```
  </Step>
</Steps>

<Note>
  `rkat-rpc` defaults to a new isolated realm each time. Use `--realm <id>` to share config/sessions with other surfaces or processes.
</Note>

## Runtime scope

`rkat-rpc` accepts global scope flags:

```bash theme={null}
rkat-rpc [--realm <id>] [--isolated] [--instance <id>] [--realm-backend <sqlite|jsonl|memory>] [--state-root <path>] [--context-root <path>] [--user-config-root <path>]
```

* `--realm`: explicit sharing/isolation key
* `--instance`: optional instance metadata
* `--realm-backend`: creation hint only; actual backend is pinned per realm manifest

## Method overview

This table mirrors the generated catalog in `artifacts/schemas/rpc-methods.json`
(`meerkat_contracts::rpc_method_catalog`). `initialize` returns the methods
enabled in the running binary, so reduced or feature-limited builds expose a
subset.

| Method                                | Category     | Params                                   | Result                                  | Description                                                                                             |
| ------------------------------------- | ------------ | ---------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `initialize`                          | Handshake    | —                                        | `ServerCapabilities`                    | Returns server capabilities                                                                             |
| `tools/register`                      | Tools        | `ToolsRegisterParams`                    | `ToolsRegisterResult`                   | Register callback tools for server-to-client execution                                                  |
| `help/ask`                            | Help         | `HelpRequest`                            | `HelpResponse`                          | Ask Meerkat usage help with the embedded platform skill                                                 |
| `runtime/host_info`                   | Runtime      | —                                        | `RuntimeHostInfo`                       | Read host identity, endpoints, capabilities, health, and realm projection                               |
| `runtime/capabilities`                | Runtime      | —                                        | `RuntimeHostCapabilities`               | Read runtime host capability flags                                                                      |
| `runtime/health`                      | Runtime      | —                                        | `RuntimeHostHealth`                     | Read runtime host health                                                                                |
| `jobs/get`                            | Jobs         | `JobsGetParams`                          | `JobsGetResult`                         | Read a realm-scoped detached-job projection without worker write authority                              |
| `jobs/list`                           | Jobs         | `JobsListParams`                         | `JobsListResult`                        | List detached jobs for one origin session in the active realm                                           |
| `jobs/cancel`                         | Jobs         | `JobsCancelParams`                       | `JobsCancelResult`                      | Commit a cancellation request and notify the owning runner                                              |
| `jobs/progress`                       | Jobs         | `JobsProgressParams`                     | `JobsProgressResult`                    | Read committed detached-job progress                                                                    |
| `jobs/result`                         | Jobs         | `JobsResultParams`                       | `JobsResultResult`                      | Read a safe terminal-result summary                                                                     |
| `jobs/artifacts`                      | Jobs         | `JobsArtifactsParams`                    | `JobsArtifactsResult`                   | List safe artifact references produced by a job                                                         |
| `jobs/retry`                          | Jobs         | `JobsRetryParams`                        | `JobsRetryResult`                       | Schedule a generated-machine-authorized retry                                                           |
| `jobs/health`                         | Jobs         | —                                        | `JobsHealthResult`                      | Read realm-scoped detached-job health and delivery backlog                                              |
| `jobs/subscribe`                      | Jobs         | `JobsSubscribeParams`                    | `JobsSubscribeResult`                   | Add a durable record, notification, or event delivery subscription                                      |
| `jobs/unsubscribe`                    | Jobs         | `JobsUnsubscribeParams`                  | `JobsUnsubscribeResult`                 | Remove a durable delivery subscription                                                                  |
| `monitors/start`                      | Jobs         | `MonitorsStartParams`                    | `MonitorsStartResult`                   | Start a high-trust durable script monitor with explicit restart and output contracts                    |
| `mobkit/jobs/heartbeat`               | Host jobs    | `MobkitJobHeartbeatParams`               | `MobkitJobMutationResult`               | Renew the exact committed attempt lease                                                                 |
| `mobkit/jobs/progress`                | Host jobs    | `MobkitJobProgressParams`                | `MobkitJobMutationResult`               | Commit progress under exact attempt/fence authority                                                     |
| `mobkit/jobs/checkpoint`              | Host jobs    | `MobkitJobCheckpointParams`              | `MobkitJobMutationResult`               | Commit a restart checkpoint under exact attempt/fence authority                                         |
| `mobkit/jobs/complete`                | Host jobs    | `MobkitJobCompleteParams`                | `MobkitJobMutationResult`               | Commit successful terminality under exact attempt/fence authority                                       |
| `mobkit/jobs/fail`                    | Host jobs    | `MobkitJobFailParams`                    | `MobkitJobMutationResult`               | Commit failed terminality under exact attempt/fence authority                                           |
| `mobkit/jobs/cancel_ack`              | Host jobs    | `MobkitJobCancelAckParams`               | `MobkitJobMutationResult`               | Acknowledge cancellation under exact attempt/fence authority                                            |
| `session/create`                      | Session      | `CreateSessionParams`                    | `WireRunResult \| DeferredCreateResult` | Create session and run first turn                                                                       |
| `session/list`                        | Session      | `ListSessionsParams`                     | `ListSessionsResult`                    | List active sessions                                                                                    |
| `session/read`                        | Session      | `ReadSessionParams`                      | `WireSessionInfo`                       | Get session state                                                                                       |
| `session/history`                     | Session      | `ReadSessionHistoryParams`               | `WireSessionHistory`                    | Get committed session transcript messages                                                               |
| `session/export_atif`                 | Session      | `ExportAtifParams`                       | `Value`                                 | Export the complete durable session event log as an ATIF trajectory                                     |
| `session/update_system_prompt`        | Session      | `UpdateSystemPromptParams`               | `SystemPromptUpdateResult`              | Explicitly replace one durable versioned system-prompt key                                              |
| `session/rewrite_transcript`          | Session      | `RewriteSessionTranscriptParams`         | `SessionTranscriptRewriteResult`        | Commit a same-session transcript rewrite                                                                |
| `session/transcript_revision`         | Session      | `ReadSessionTranscriptRevisionParams`    | `WireSessionTranscriptRevision`         | Read a transcript revision by id                                                                        |
| `session/transcript_revisions`        | Session      | `ListSessionTranscriptRevisionsParams`   | `WireSessionTranscriptRevisionList`     | List retained transcript revision commits with the current head                                         |
| `session/restore_transcript_revision` | Session      | `RestoreSessionTranscriptRevisionParams` | `SessionTranscriptRewriteResult`        | Restore an earlier transcript revision in place                                                         |
| `session/fork_at`                     | Session      | `ForkSessionAtParams`                    | `SessionForkResult`                     | Fork an idle session at a transcript message index                                                      |
| `session/fork_replace`                | Session      | `ForkSessionReplaceParams`               | `SessionForkResult`                     | Fork an idle session and apply a typed transcript replacement                                           |
| `blob/get`                            | Session      | `BlobGetParams`                          | `BlobPayload`                           | Fetch a blob payload by id                                                                              |
| `artifact/list`                       | Artifact     | `ArtifactListParams`                     | `ArtifactListResult`                    | List stable artifact records                                                                            |
| `artifact/get`                        | Artifact     | `ArtifactIdParams`                       | `ArtifactRecord`                        | Get one stable artifact record                                                                          |
| `artifact/download`                   | Artifact     | `ArtifactDownloadParams`                 | `ArtifactDownloadResult`                | Download blob-backed artifact payload bytes                                                             |
| `approval/request`                    | Approval     | `ApprovalRequestParams`                  | `ApprovalRecord`                        | Create a durable approval request                                                                       |
| `approval/list`                       | Approval     | `ApprovalListParams`                     | `ApprovalListResult`                    | List approval records                                                                                   |
| `approval/get`                        | Approval     | `ApprovalGetParams`                      | `ApprovalRecord`                        | Get one approval record                                                                                 |
| `approval/decide`                     | Approval     | `ApprovalDecideParams`                   | `ApprovalRecord`                        | Record an approval decision                                                                             |
| `events/latest_cursor`                | Events       | `EventsLatestCursorParams`               | `EventsLatestCursorResult`              | Read the latest replay cursor for a typed event scope                                                   |
| `events/list_since`                   | Events       | `EventsListSinceParams`                  | `EventsListSinceResult`                 | List replayable events after a typed cursor                                                             |
| `events/snapshot`                     | Events       | `EventsSnapshotParams`                   | `EventsSnapshotResult`                  | Read a point-in-time snapshot with its replay cursor                                                    |
| `session/archive`                     | Session      | `ArchiveSessionParams`                   | `Value`                                 | Remove session from runtime                                                                             |
| `session/external_event`              | Session      | `SessionExternalEventEnvelope`           | `RuntimeAcceptResult`                   | Queue a runtime-backed external event                                                                   |
| `session/peer_response_terminal`      | Session      | `SessionPeerResponseTerminalParams`      | `RuntimeAcceptResult`                   | Admit a correlated terminal peer response through the typed runtime ingress                             |
| `session/inject_context`              | Session      | `InjectSystemContextParams`              | `InjectSystemContextResult`             | Append one ordinary durable ordered System message at the admitted transcript boundary                  |
| `session/input_status`                | Session      | `SessionInputStateParams`                | `SessionInputStateResult`               | Read an input's stored runtime state (terminal outcome, run association) by input id or idempotency key |
| `turn/start`                          | Turn         | `StartTurnParams`                        | `WireRunResult`                         | Start a new turn on existing session                                                                    |
| `turn/interrupt`                      | Turn         | `InterruptParams`                        | `InterruptResult`                       | Cancel in-flight turn                                                                                   |
| `live/open`                           | Live         | `LiveOpenParams`                         | `LiveOpenResult`                        | Open a live channel; optionally bound its serialized seed messages                                      |
| `live/webrtc/answer`                  | Live         | `LiveWebrtcAnswerParams`                 | `LiveWebrtcAnswerResult`                | Answer a browser WebRTC offer for an already-open live channel                                          |
| `live/status`                         | Live         | `LiveChannelParams`                      | `LiveStatusResult`                      | Get the status of a live channel                                                                        |
| `live/close`                          | Live         | `LiveChannelParams`                      | `LiveCloseResult`                       | Close a live channel                                                                                    |
| `live/send_input`                     | Live         | `LiveSendInputParams`                    | `LiveSendInputResult`                   | Send an audio, text, or model-supported image chunk to a live channel                                   |
| `live/commit_input`                   | Live         | `LiveCommitInputParams`                  | `LiveCommitInputResult`                 | Commit pending input on a live channel (turn boundary)                                                  |
| `live/interrupt`                      | Live         | `LiveChannelParams`                      | `LiveInterruptResult`                   | Interrupt the assistant turn on a live channel (barge-in)                                               |
| `live/truncate`                       | Live         | `LiveTruncateParams`                     | `LiveTruncateResult`                    | Truncate assistant output at a client-tracked playback cursor                                           |
| `live/refresh`                        | Live         | `LiveChannelParams`                      | `LiveRefreshResult`                     | Apply mutable session config (instructions/tools/audio) to an open live channel                         |
| `session/stream_open`                 | Session      | `SessionStreamOpenParams`                | `SessionStreamOpenResult`               | Open a standalone session event stream                                                                  |
| `session/stream_close`                | Session      | `SessionStreamCloseParams`               | `SessionStreamCloseResult`              | Close a standalone session event stream                                                                 |
| `mob/create`                          | Mob          | `MobCreateParams`                        | `MobCreateResult`                       | Create a mob from a definition (mob feature)                                                            |
| `mob/list`                            | Mob          | —                                        | `MobListResult`                         | List mobs (mob feature)                                                                                 |
| `mob/status`                          | Mob          | `MobIdParams`                            | `MobStatusResult`                       | Get mob status (mob feature)                                                                            |
| `mob/members`                         | Mob          | `MobIdParams`                            | `MobMembersResult`                      | List mob members (mob feature)                                                                          |
| `mob/spawn`                           | Mob          | `MobSpawnParams`                         | `MobSpawnResult`                        | Spawn a member into a mob (mob feature)                                                                 |
| `mob/spawn_many`                      | Mob          | `MobSpawnManyParams`                     | `MobSpawnManyResult`                    | Spawn multiple members into a mob (mob feature)                                                         |
| `mob/retire`                          | Mob          | `MobMemberParams`                        | `MobRetireResult`                       | Retire a mob member (mob feature)                                                                       |
| `mob/respawn`                         | Mob          | `MobRespawnParams`                       | `MobRespawnResult`                      | Respawn a mob member (mob feature)                                                                      |
| `mob/wire`                            | Mob          | `MobWireParams`                          | `MobWireResult`                         | Wire two mob members for comms (mob feature)                                                            |
| `mob/wire_members_batch`              | Mob          | `MobWireMembersBatchParams`              | `MobWireMembersBatchResult`             | Wire multiple local mob member edges in one batch (mob feature)                                         |
| `mob/unwire`                          | Mob          | `MobUnwireParams`                        | `MobUnwireResult`                       | Remove mob comms wiring (mob feature)                                                                   |
| `mob/lifecycle`                       | Mob          | `MobLifecycleParams`                     | `MobLifecycleResult`                    | Stop, resume, complete, destroy, or reset a mob (mob feature)                                           |
| `mob/events`                          | Mob          | `MobEventsParams`                        | `MobEventsResult`                       | Read mob events by cursor (mob feature)                                                                 |
| `mob/ingress_interaction`             | Mob          | `MobIngressInteractionParams`            | `MobIngressInteractionResult`           | Ensure an ingress member and deliver user input with replay anchors (mob feature)                       |
| `mob/stream_open`                     | Mob          | `MobStreamOpenParams`                    | `MobStreamOpenResult`                   | Open mob or member event stream (mob feature)                                                           |
| `mob/stream_close`                    | Mob          | `MobStreamCloseParams`                   | `MobStreamCloseResult`                  | Close mob or member event stream (mob feature)                                                          |
| `mob/member_send`                     | Mob          | `MobMemberSendParams`                    | `MobMemberSendResult`                   | Deliver ordinary content to a specific mob member via the host control plane (mob feature)              |
| `mob/append_system_context`           | Mob          | `MobAppendSystemContextParams`           | `MobAppendSystemContextResult`          | Append one ordinary durable ordered System message to a member session (mob feature)                    |
| `mob/flows`                           | Mob          | `MobIdParams`                            | `MobFlowsResult`                        | List mob flows (mob feature)                                                                            |
| `mob/run`                             | Mob          | `MobRunParams`                           | `MobFlowRunResult`                      | Invoke a mob as a typed callable run (mob feature)                                                      |
| `mob/flow_run`                        | Mob          | `MobFlowRunParams`                       | `MobFlowRunResult`                      | Start a mob flow run (mob feature)                                                                      |
| `mob/flow_status`                     | Mob          | `MobFlowStatusParams`                    | `MobFlowStatusResult`                   | Get flow run status (mob feature)                                                                       |
| `mob/run_result`                      | Mob          | `MobRunResultParams`                     | `MobRunResult`                          | Get a typed output envelope for a mob run (mob feature)                                                 |
| `mob/flow_cancel`                     | Mob          | `MobFlowCancelParams`                    | `MobFlowCancelResult`                   | Cancel a flow run (mob feature)                                                                         |
| `mob/ensure_member`                   | Mob          | `MobEnsureMemberParams`                  | `MobEnsureMemberResult`                 | Idempotent spawn — returns existing entry if member already exists (mob feature)                        |
| `mob/reconcile`                       | Mob          | `MobReconcileParams`                     | `MobReconcileResult`                    | Declarative roster reconcile against a desired spec list (mob feature)                                  |
| `mob/list_members_matching`           | Mob          | `MobListMembersMatchingParams`           | `MobListMembersMatchingResult`          | Label-filtered member listing with server-side filter (mob feature)                                     |
| `mob/spawn_helper`                    | Mob          | `MobSpawnHelperParams`                   | `MobHelperResult`                       | Spawn a helper member and wait for its result (mob feature)                                             |
| `mob/fork_helper`                     | Mob          | `MobForkHelperParams`                    | `MobHelperResult`                       | Fork a helper from an existing member and wait for its result (mob feature)                             |
| `mob/force_cancel`                    | Mob          | `MobMemberParams`                        | `MobForceCancelResult`                  | Force-cancel a member's active work (mob feature)                                                       |
| `mob/turn_start`                      | Mob          | `MobTurnStartParams`                     | `WireRunResult`                         | Start a turn on a mob member by identity (mob feature)                                                  |
| `mob/member_status`                   | Mob          | `MobMemberParams`                        | `MobMemberStatusResult`                 | Read canonical status for a specific member (mob feature)                                               |
| `mob/snapshot`                        | Mob          | `MobIdParams`                            | `MobSnapshotResult`                     | Point-in-time aggregate of mob status plus member list (mob feature)                                    |
| `mob/destroy`                         | Mob          | `MobIdParams`                            | `MobDestroyResult`                      | Destroy a mob and surface the structured MobDestroyReport (mob feature)                                 |
| `mob/rotate_supervisor`               | Mob          | `MobIdParams`                            | `MobRotateSupervisorResult`             | Rotate the supervisor bridge for all members of a mob (mob feature)                                     |
| `mob/submit_work`                     | Mob          | `MobSubmitWorkParams`                    | `MobSubmitWorkResult`                   | Submit a unit of work to a mob member through the work lane (mob feature)                               |
| `mob/conclude_objective`              | Mob          | `MobConcludeObjectiveParams`             | `MobConcludeObjectiveResult`            | Explicitly conclude a durable kickoff objective (mob feature)                                           |
| `mob/cancel_work`                     | Mob          | `MobCancelWorkParams`                    | `MobCancelWorkResult`                   | Cancel a previously submitted unit of work (mob feature)                                                |
| `mob/cancel_all_work`                 | Mob          | `MobCancelAllWorkParams`                 | `MobCancelAllWorkResult`                | Cancel all in-flight work for a mob member (mob feature)                                                |
| `mob/wait_kickoff`                    | Mob          | `MobWaitParams`                          | `MobWaitMembersResult`                  | Wait for kickoff completion for a member (mob feature)                                                  |
| `mob/wait_ready`                      | Mob          | `MobWaitParams`                          | `MobWaitMembersResult`                  | Wait for mob startup readiness (members bound but kickoff not required, mob feature)                    |
| `mob/profile/create`                  | Mob          | `MobProfileCreateParams`                 | `MobProfileLookupResult`                | Create a realm-scoped mob profile (mob feature)                                                         |
| `mob/profile/get`                     | Mob          | `MobProfileNameParams`                   | `MobProfileLookupResult`                | Read a realm-scoped mob profile (mob feature)                                                           |
| `mob/profile/list`                    | Mob          | —                                        | `MobProfileListResult`                  | List realm-scoped mob profiles (mob feature)                                                            |
| `mob/profile/update`                  | Mob          | `MobProfileUpdateParams`                 | `MobProfileLookupResult`                | Update a realm-scoped mob profile (mob feature)                                                         |
| `mob/profile/delete`                  | Mob          | `MobProfileDeleteParams`                 | `MobProfileDeleteResult`                | Delete a realm-scoped mob profile (mob feature)                                                         |
| `mob/grant_scopes`                    | Mob          | `MobGrantScopesParams`                   | `MobGrantScopesResult`                  | Record (full-replace) a principal's control-scope grant (mob feature)                                   |
| `mob/revoke_scopes`                   | Mob          | `MobRevokeScopesParams`                  | `MobRevokeScopesResult`                 | Revoke control scopes from a principal's grant; omit scopes to revoke the entire grant (mob feature)    |
| `mob/grants`                          | Mob          | `MobIdParams`                            | `MobGrantsResult`                       | List raw control-scope grant records; expired rows appear verbatim (mob feature)                        |
| `mob/member_history`                  | Mob          | `MobMemberHistoryParams`                 | `MobMemberHistoryResult`                | Read a mob member transcript page by identity; one shape local and remote (mob feature)                 |
| `mob/hosts`                           | Mob          | `MobIdParams`                            | `MobHostsResult`                        | List tracked member hosts with bind phase and declared capabilities (mob feature)                       |
| `mob/route_installs`                  | Mob          | `MobIdParams`                            | `MobRouteInstallsResult`                | Outstanding cross-host route-install obligations (mob feature)                                          |
| `mob/bind_host`                       | Mob          | `MobBindHostParams`                      | `MobBindHostResult`                     | Bind a member-host daemon to a mob from its binding descriptor (mob feature)                            |
| `mob/revoke_host`                     | Mob          | `MobRevokeHostParams`                    | `MobRevokeHostResult`                   | Revoke a bound (or bind-requested) member host (mob feature)                                            |
| `mob/hard_cancel_member`              | Mob          | `MobHardCancelParams`                    | `MobHardCancelResult`                   | Hard-cancel a mob member; immediate user-interrupt authority (mob feature)                              |
| `mob/member_live_open`                | Mob          | `MobMemberLiveOpenParams`                | `LiveOpenResult`                        | Open a live realtime channel on a mob member by identity (mob feature)                                  |
| `mob/member_live_close`               | Mob          | `MobMemberLiveChannelParams`             | `LiveCloseResult`                       | Close one named live channel on a mob member (mob feature)                                              |
| `mob/member_live_status`              | Mob          | `MobMemberLiveStatusParams`              | `LiveStatusResult`                      | Read live channel status for a mob member; omit channel\_id to discover (mob feature)                   |
| `mob/member_live_control`             | Mob          | `MobMemberLiveControlParams`             | `BridgeLiveControlOutcome`              | Drive one turn-level live control verb on a member channel (mob feature)                                |
| `schedule/create`                     | Schedule     | `CreateScheduleRequest`                  | `Schedule`                              | Create a new schedule (schedule feature)                                                                |
| `schedule/get`                        | Schedule     | `ScheduleIdParams`                       | `Schedule`                              | Get a schedule by ID (schedule feature)                                                                 |
| `schedule/list`                       | Schedule     | `ListSchedulesParams`                    | `ScheduleListResult`                    | List schedules (schedule feature)                                                                       |
| `schedule/update`                     | Schedule     | `UpdateScheduleParams`                   | `Schedule`                              | Update a schedule (schedule feature)                                                                    |
| `schedule/pause`                      | Schedule     | `ScheduleIdParams`                       | `Schedule`                              | Pause a schedule (schedule feature)                                                                     |
| `schedule/resume`                     | Schedule     | `ScheduleIdParams`                       | `Schedule`                              | Resume a paused schedule (schedule feature)                                                             |
| `schedule/delete`                     | Schedule     | `ScheduleIdParams`                       | `Schedule`                              | Delete a schedule (schedule feature)                                                                    |
| `schedule/occurrences`                | Schedule     | `ScheduleOccurrencesParams`              | `ScheduleOccurrencesResult`             | List occurrences for a schedule (schedule feature)                                                      |
| `schedule/tools`                      | Schedule     | —                                        | `ScheduleToolsResult`                   | List schedule tools (schedule feature)                                                                  |
| `schedule/call`                       | Schedule     | `ScheduleToolCallParams`                 | `Value`                                 | Call a schedule tool directly (schedule feature)                                                        |
| `workgraph/get`                       | WorkGraph    | `WorkGraphIdParams`                      | `WorkItem`                              | Read a WorkGraph item (workgraph feature)                                                               |
| `workgraph/list`                      | WorkGraph    | `WorkItemFilter`                         | `WorkItemsResult`                       | List WorkGraph items (workgraph feature)                                                                |
| `workgraph/ready`                     | WorkGraph    | `ReadyWorkFilter`                        | `WorkItemsResult`                       | List ready WorkGraph items (workgraph feature)                                                          |
| `workgraph/snapshot`                  | WorkGraph    | `WorkGraphSnapshotFilter`                | `WorkGraphSnapshot`                     | Read a WorkGraph observability snapshot (workgraph feature)                                             |
| `workgraph/events`                    | WorkGraph    | `WorkGraphEventFilter`                   | `WorkEventsResult`                      | Read WorkGraph event history (workgraph feature)                                                        |
| `workgraph/goal/status`               | WorkGraph    | `GoalStatusRequest`                      | `GoalStatusResult`                      | Read goal and attention status (workgraph feature)                                                      |
| `workgraph/attention/list`            | WorkGraph    | `AttentionListRequest`                   | `AttentionListResult`                   | List attention bindings, optionally filtered by status (workgraph feature)                              |
| `comms/send`                          | Comms        | `CommsSendParams`                        | `CommsSendResult`                       | Dispatch a comms command to a session                                                                   |
| `comms/peers`                         | Comms        | `CommsPeersParams`                       | `CommsPeersResult`                      | List discoverable peers (comms feature)                                                                 |
| `skills/list`                         | Skills       | —                                        | `SkillListResponse`                     | List skills with provenance                                                                             |
| `mcp/add`                             | MCP          | `McpAddParams`                           | `McpLiveOpResponse`                     | Stage live MCP server addition (mcp feature)                                                            |
| `mcp/remove`                          | MCP          | `McpRemoveParams`                        | `McpLiveOpResponse`                     | Stage live MCP server removal (mcp feature)                                                             |
| `mcp/reload`                          | MCP          | `McpReloadParams`                        | `McpLiveOpResponse`                     | Reload one or all MCP servers (mcp feature)                                                             |
| `models/catalog`                      | Models       | —                                        | `ModelsCatalogResponse`                 | List available models with capabilities and provider profiles                                           |
| `capabilities/get`                    | Capabilities | —                                        | `CapabilitiesResponse`                  | Runtime capability report                                                                               |
| `config/get`                          | Config       | —                                        | `ConfigEnvelope`                        | Read current config                                                                                     |
| `config/set`                          | Config       | `ConfigSetParams`                        | `ConfigWriteResult`                     | Replace config                                                                                          |
| `config/patch`                        | Config       | `ConfigPatchParams`                      | `ConfigWriteResult`                     | Merge-patch config (RFC 7396)                                                                           |
| `auth/profile/list`                   | Auth         | `RealmIdParams`                          | `WireAuthProfilesList`                  | List auth profiles in a realm                                                                           |
| `auth/profile/get`                    | Auth         | `BindingIdParams`                        | `WireAuthProfileDetail`                 | Get one auth profile                                                                                    |
| `auth/profile/create`                 | Auth         | `CreateProfileParams`                    | `WireAuthProfileCreated`                | Create an auth profile (CLI-driven for now)                                                             |
| `auth/profile/delete`                 | Auth         | `BindingIdParams`                        | `WireAuthProfileCleared`                | Delete an auth profile (CLI-driven for now)                                                             |
| `auth/login/start`                    | Auth         | `LoginStartParams`                       | `WireLoginStart`                        | Begin interactive authorization-code OAuth (returns authorize\_url + pkce\_verifier)                    |
| `auth/login/complete`                 | Auth         | `LoginCompleteParams`                    | `WireLoginReady`                        | Exchange authorization code for tokens; persists to TokenStore                                          |
| `auth/login/device_start`             | Auth         | `DeviceStartParams`                      | `WireDeviceStart`                       | Begin device-code OAuth; returns user\_code + verification URL                                          |
| `auth/login/device_complete`          | Auth         | `DeviceCompleteParams`                   | `WireDeviceCompleteResult`              | Single-poll completion for a device-code OAuth login                                                    |
| `auth/login/provision_api_key`        | Auth         | `ProvisionApiKeyParams`                  | `WireProvisionApiKeyResult`             | Console-OAuth → API key provisioning (Anthropic oauth\_to\_api\_key)                                    |
| `auth/status/get`                     | Auth         | `BindingIdParams`                        | `WireAuthStatusDetail`                  | Get auth status for a profile                                                                           |
| `auth/logout`                         | Auth         | `BindingIdParams`                        | `WireAuthProfileCleared`                | Revoke + remove persisted credentials                                                                   |
| `realm/list`                          | Realm        | —                                        | `WireRealmList`                         | List realm summaries                                                                                    |
| `realm/get`                           | Realm        | `RealmIdParams`                          | `WireRealmConnectionSet`                | Get full realm connection set                                                                           |

Both helper parameter types (`MobSpawnHelperParams`, `MobForkHelperParams`)
require `result_label` and `max_text_bytes`. `MobHelperResult` is the exact
operation carrier: `output`, `tokens_used`, `agent_identity`, `member_ref`,
`bounded_result`, `session_id`, `usage`, `turns`, and `tool_calls` are
required, while `retirement_error` reports post-result cleanup debt when
present.

<Note>
  Every `Schedule` result is one flattened public object. Configuration fields
  including `planning_horizon_days`, `planning_horizon_occurrences`, `labels`,
  `created_at_utc`, and `updated_at_utc` are top-level; there is no nested
  `config` and persisted machine authority is not exposed as `machine_state`.
</Note>

WorkGraph goal and attention mutation methods require trusted host/session
authority. JSON-RPC exposes observability reads; goal creation, reassignment,
policy escalation, confirmation, and closure stay on trusted in-process host and
agent-tool surfaces.

<Note>
  Generated assistant images use the same surface-neutral history and blob APIs as other blob-backed artifacts. Read `session/history`, find assistant blocks with `block_type: "image"`, then call `blob/get` with `data.blob_ref.blob_id` to retrieve the base64 payload.
</Note>

<Note>
  Live channels provide low-latency audio/text streaming with model-gated image input. Create a session
  with a realtime-capable model (e.g. `gpt-realtime-2`), then call
  `live/open` to start the channel. The `--live-ws <addr>` flag on
  `rkat-rpc` enables the WebSocket listener required for audio transport.
  Use `live/status` to observe channel state and check
  `live/open`'s `capabilities.image_in` before sending image context.
</Note>

<Note>
  RPC is the canonical typed substrate for the SDKs: use explicit `mob/*` lifecycle, host-ingress, and observation methods from apps. Inside running sessions, mob capability is exposed by composing `meerkat-mob-mcp` (`MobMcpState` + `AgentMobToolSurfaceFactory`) into `SessionBuildOptions.mob_tools`, which provides authorized `mob_*` tools to the agent. `external_tools` remains for callback and MCP-backed tool dispatchers.
</Note>

<Note>
  WorkGraph RPC methods are observability reads. Programmatic hosts inspect
  WorkGraph through `workgraph/get`, `list`, `ready`, `snapshot`, `events`,
  `goal/status`, and `attention/list`; agents mutate ordinary WorkGraph state
  through the `workgraph_*` tools. Authority-bearing attention reassignment and
  policy escalation are runtime-injected WorkGraph tool operations, not public
  JSON-RPC methods.
</Note>

## Protocol

Standard JSON-RPC 2.0 with `"jsonrpc": "2.0"` on every message. Three message types:

* **Request** (client -> server): has `id`, `method`, `params`
* **Response** (server -> client): has `id`, `result` or `error`
* **Notification** (server -> client): has `method`, `params`, no `id`

<Accordion title="Full lifecycle diagram">
  ```text theme={null}
  Client                          Server
    |                                |
    |-- initialize ----------------->|
    |<-- result { capabilities } ----|
    |-- initialized (notification) ->|
    |                                |
    |-- session/create { prompt } -->|
    |<-- session/event (notif) ------|  // AgentEvent stream
    |<-- session/event (notif) ------|
    |<-- result { session_id, ... } -|
    |                                |
    |-- turn/start { session_id } -->|
    |<-- session/event (notif) ------|
    |<-- result { text, usage } -----|
    |                                |
    |-- turn/interrupt { sid } ----->|
    |<-- result {} ------------------|
    |                                |
    |-- session/archive { sid } ---->|
    |<-- result {} ------------------|
  ```
</Accordion>

## Session methods

### initialize

Handshake. Returns server capabilities.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "server_info": {
        "name": "meerkat-rpc",
        "version": "0.8.22"
      },
      "contract_version": "0.8.22",
      "methods": [
        "initialize", "initialized",
        "session/create", "session/list", "session/read",
        "turn/start", "turn/interrupt",
        "runtime/host_info", "config/get",
        "live/open", "mob/create"
      ]
    }
  }
  ```
</CodeGroup>

The actual array contains every method compiled into the server. For the full
documented list and parameter/result type names, use
`artifacts/schemas/rpc-methods.json`.

<ResponseField name="server_info.name" type="string">
  Server name.
</ResponseField>

<ResponseField name="server_info.version" type="string">
  Server version.
</ResponseField>

<ResponseField name="contract_version" type="string">
  Protocol contract version.
</ResponseField>

<ResponseField name="methods" type="array">
  List of supported method names.
</ResponseField>

### session/create

Create a new session and run the first turn. Set `initial_turn` to `"deferred"` to return a pending `session_id` without running the first turn; that returned `session_id` is valid for the first `turn/start`, including sessions created with inline `external_tools`.

<CodeGroup>
  ```json Request (minimal) theme={null}
  {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "session/create",
    "params": {
      "prompt": "What is Rust?"
    }
  }
  ```

  ```json Request (full) theme={null}
  {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "session/create",
    "params": {
      "prompt": "What is Rust?",
      "model": "claude-sonnet-4-6",
      "provider": "anthropic",
      "max_tokens": 4096,
      "system_prompt": "You are a helpful assistant.",
      "output_schema": {
        "schema": {"type": "object", "properties": {"answer": {"type": "string"}}},
        "name": "answer"
      },
      "structured_output_retries": 2,
      "hooks_override": null,
      "enable_builtins": false,
      "enable_shell": false,
      "enable_memory": false,
      "enable_schedule": null,
      "enable_workgraph": null,
      "keep_alive": null,
      "comms_name": null,
      "provider_params": null,
      "preload_skills": [
        {"source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f", "skill_name": "extraction-email"}
      ],
      "skill_refs": [
        {
          "kind": "structured",
          "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
          "skill_name": "formatting-markdown"
        }
      ]
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 2,
    "result": {
      "session_id": "01936f8a-7b2c-7000-8000-000000000001",
      "text": "Rust is a systems programming language...",
      "turns": 1,
      "tool_calls": 0,
      "usage": {
        "input_tokens": 50,
        "output_tokens": 200,
        "total_tokens": 250
      },
      "structured_output": null,
      "schema_warnings": null
    }
  }
  ```
</CodeGroup>

Only `prompt` is required. All other fields are optional and fall back to config defaults. During execution, `session/event` notifications are emitted (see [Notifications](#notifications)).

#### Parameter reference

<ParamField body="prompt" type="string" required>
  The user prompt to send to the agent.
</ParamField>

<ParamField body="injected_context" type="ContentInput[] | null" default="null">
  Host-attached injected context for the first turn. Each entry materializes
  as a separate typed injected-context user-channel message immediately before
  the first turn's user message, in order; injected context is excluded from
  semantic-memory indexing.
</ParamField>

<ParamField body="transient_turn_context" type="string | null" default="null">
  Non-empty, exact request-only host facts for the immediate first turn;
  whitespace is significant. The pending runtime input retains the bytes for
  crash retry; the Session transcript, compaction summarizer, and extraction
  phase never receive them. Deferred create rejects this field; provide it on
  the eventual `turn/start`.
</ParamField>

<ParamField body="model" type="string | null" default="config/catalog default">
  Model name (e.g. `"claude-opus-4-8"`, `"gpt-5.5"`).
</ParamField>

<ParamField body="provider" type="string | null" default="inferred from model">
  Provider name: `"anthropic"`, `"openai"`, `"gemini"`, `"self_hosted"`, `"other"`.
</ParamField>

<ParamField body="max_tokens" type="u32 | null" default="config default">
  Max tokens per turn.
</ParamField>

<ParamField body="system_prompt" type="string | null" default="null">
  Override system prompt.
</ParamField>

<ParamField body="output_schema" type="object | null" default="null">
  JSON schema for structured output extraction (wrapper or raw schema).
</ParamField>

<ParamField body="structured_output_retries" type="u32" default="2">
  Max retries for structured output validation.
</ParamField>

<ParamField body="hooks_override" type="HookRunOverrides | null" default="null">
  Run-scoped hook overrides (entries to add, hook IDs to disable).
</ParamField>

<ParamField body="enable_builtins" type="bool" default="false">
  Enable built-in tools (task management, etc.).
</ParamField>

<ParamField body="enable_shell" type="bool" default="false">
  Enable shell tool (requires `enable_builtins`).
</ParamField>

<ParamField body="enable_memory" type="bool" default="false">
  Enable semantic memory (`memory_search` tool + compaction indexing).
</ParamField>

<ParamField body="enable_schedule" type="bool | null" default="null">
  Override schedule tools for this session. `null` uses the surface default.
</ParamField>

<ParamField body="enable_workgraph" type="bool | null" default="null">
  Override WorkGraph tools for this session. `null` uses the surface default.
</ParamField>

<ParamField body="keep_alive" type="bool | null" default="null">
  Keep session alive after turn for comms. `null` = inherit persisted session intent, `true` = enable, `false` = disable. Requires `comms_name` when enabled.
</ParamField>

<ParamField body="comms_name" type="string | null" default="null">
  Agent name for inter-agent communication.
</ParamField>

<ParamField body="provider_params" type="object | null" default="null">
  Provider-specific parameters (e.g., thinking config, reasoning effort).
</ParamField>

#### Response fields

<ResponseField name="session_id" type="string">
  UUID of the created session.
</ResponseField>

<ResponseField name="text" type="string">
  The agent's response text.
</ResponseField>

<ResponseField name="turns" type="u32">
  Number of LLM calls made.
</ResponseField>

<ResponseField name="tool_calls" type="u32">
  Number of tool calls executed.
</ResponseField>

<ResponseField name="usage" type="WireUsage">
  Token usage breakdown.
</ResponseField>

<ResponseField name="structured_output" type="object | null">
  Parsed structured output.
</ResponseField>

<ResponseField name="schema_warnings" type="array | null">
  Schema compatibility warnings.
</ResponseField>

### session/history

Read committed transcript history for an existing session.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "session/history",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "offset": 0,
    "limit": 50
  }
}
```

Returns oldest-to-newest committed messages plus pagination metadata. This method follows the same owner-resolution rules as `session/read`, including mob-owned session IDs when mob support is enabled.
When `limit` is omitted, the server returns at most 100 messages. The maximum
accepted `limit` is 1,000 and the maximum `offset` is 1,000,000; larger values
fail with `INVALID_PARAMS` before the session store is queried.

### session/export\_atif

Export the complete durable session event log as an ATIF (Agent Trajectory
Interchange Format) v1.7 trajectory document.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "session/export_atif",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "agent_name": "meerkat",
    "agent_version": "0.8.22",
    "model_name": "claude-opus-5"
  }
}
```

`agent_name`, `agent_version`, and `model_name` are optional overrides for the
trajectory's `agent` block; when `model_name` is omitted the session's model is
used. The export replays the durable event log, so it requires a persistent
session backend; exports are rejected past a 100,000-event replay bound.

### session/rewrite\_transcript

Commit a transcript rewrite without changing the session identity. The request names a
message-range selection, supplies replacement messages, and records a machine-readable
reason. The session appends a rewrite commit, advances its transcript head, and retains
the parent revision for audit and restore.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "session/rewrite_transcript",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "selection": {
      "type": "message_range",
      "start": 2,
      "end": 3
    },
    "replacement": [
      {
        "role": "block_assistant",
        "blocks": [{ "block_type": "text", "data": { "text": "Compacted assistant trace" } }],
        "stop_reason": "end_turn"
      }
    ],
    "reason": {
      "kind": "compaction",
      "note": "Replace verbose assistant output with durable compacted form"
    },
    "running_behavior": "reject"
  }
}
```

Returns the stable `session_id`, the parent revision, the new revision, and the updated
message count. `running_behavior` currently supports `"reject"`, which returns
`SESSION_BUSY` if the target session has active work.

### session/transcript\_revision

Read one retained transcript revision body by revision id.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "session/transcript_revision",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "revision": "current",
    "offset": 0,
    "limit": 50
  }
}
```

Use `"current"` to read the active transcript head, or pass a concrete revision returned
by `session/rewrite_transcript` or `session/restore_transcript_revision`.

### session/transcript\_revisions

List retained transcript revision commits (oldest first) together with the current
transcript head revision. Each entry records the revision the commit produced, the
parent it was applied against, the recorded actor, the rendered rewrite reason, and
the commit timestamp.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "session/transcript_revisions",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "offset": 0,
    "limit": 50
  }
}
```

Sessions without any rewrite commit return an empty list; `head_revision` still names
the active transcript head. Pass a returned `revision` to `session/transcript_revision`
to read the retained body, or to `session/restore_transcript_revision` to restore it.

### session/restore\_transcript\_revision

Restore a retained transcript revision as the active transcript head without changing
the session identity. Restore is represented as another rewrite commit so the graph
remains append-only even though the source transcript projection is updated in place.
`revision` accepts the same selector as `session/transcript_revision`: `"current"`
resolves to the head revision, so restoring it surfaces the typed no-op rewrite error.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 10,
  "method": "session/restore_transcript_revision",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "revision": "sha256:...",
    "reason": {
      "kind": "restore"
    },
    "running_behavior": "reject"
  }
}
```

### session/fork\_at

Create a new idle session whose transcript is the source session prefix ending before `message_index`. The source session is not mutated.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "session/fork_at",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "message_index": 2,
    "running_behavior": "reject"
  }
}
```

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 8,
  "result": {
    "source_session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "session_id": "01936f8a-7b2c-7000-8000-000000000009",
    "message_count": 2
  }
}
```

`running_behavior` currently supports `"reject"`, which returns `SESSION_BUSY` if the source session has active work.

### session/fork\_replace

Create a new idle session from the source prefix through `message_index`, replacing the addressed message or block with a typed replacement. Later source messages are intentionally omitted so callers continue from the edited branch instead of replaying stale descendants.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "session/fork_replace",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "message_index": 2,
    "replacement": {
      "type": "message",
      "message": {
        "role": "user",
        "content": "Edited follow-up"
      }
    },
    "running_behavior": "reject"
  }
}
```

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 9,
  "result": {
    "source_session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "session_id": "01936f8a-7b2c-7000-8000-000000000010",
    "message_count": 3
  }
}
```

Supported replacement variants are `message`, `user_content_block`, `assistant_block`, and `tool_result_content_block`. Edits always create a new session identity.

### session/list

List active sessions.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":3,"method":"session/list"}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 3,
    "result": {
      "sessions": [
        {"session_id": "01936f8a-...", "state": "idle"},
        {"session_id": "01936f8b-...", "state": "running"}
      ]
    }
  }
  ```
</CodeGroup>

`session/list` is owner-paginated rather than load-all/truncate: omitted
`limit` defaults to 100, the maximum is 1,000, and `offset` is capped at
1,000,000. The same 100/1,000 collection limits apply to
`events/list_since`, `workgraph/list`, `workgraph/ready`,
`workgraph/snapshot`, and `workgraph/events`.

WorkGraph ready-set and snapshot projections are atomic only within explicit
process bounds. A projection that would need to scan more than 1,000 items,
1,000 edges, or 1,000 attention bindings fails closed with
`INVALID_PARAMS`; narrow the realm/namespace/filter and retry. The store does
not materialize an oversized graph and truncate it after the fact.

### session/read

Get session state.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":4,"method":"session/read","params":{"session_id":"01936f8a-..."}}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 4,
    "result": {
      "session_id": "01936f8a-...",
      "state": "idle",
      "message_count": 4,
      "total_tokens": 500
    }
  }
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to read.
</ParamField>

### session/archive

Remove a session from the runtime.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":5,"method":"session/archive","params":{"session_id":"01936f8a-..."}}
  ```

  ```json Response theme={null}
  {"jsonrpc":"2.0","id":5,"result":{"archived":true}}
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to archive.
</ParamField>

## Turn methods

### turn/start

Start a new turn on an existing session.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 6,
    "method": "turn/start",
    "params": {
      "session_id": "01936f8a-...",
      "prompt": "Can you explain ownership?",
      "skill_refs": [
        {
          "kind": "structured",
          "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
          "skill_name": "rust-patterns-ownership"
        }
      ]
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 6,
    "result": {
      "session_id": "01936f8a-...",
      "text": "Ownership is Rust's approach to memory management...",
      "turns": 1,
      "tool_calls": 0,
      "usage": {
        "input_tokens": 300,
        "output_tokens": 400,
        "total_tokens": 700
      },
      "structured_output": null,
      "schema_warnings": null
    }
  }
  ```
</CodeGroup>

Returns the same result shape as `session/create`. Fails with error code `-32001` (SESSION\_BUSY) if a turn is already in progress.

<ParamField body="session_id" type="string" required>
  Session ID to continue.
</ParamField>

<ParamField body="prompt" type="string" required>
  The follow-up prompt.
</ParamField>

<ParamField body="injected_context" type="ContentInput[] | null" default="null">
  Host-attached injected context for this turn. Each entry materializes as a
  separate typed injected-context user-channel message immediately before the
  turn's user message, in order; injected context is excluded from
  semantic-memory indexing.
</ParamField>

<ParamField body="transient_turn_context" type="string | null" default="null">
  Non-empty, exact request-only host facts for this newly admitted turn;
  whitespace is significant. Projected before the admitted conversational
  user message for foreground model calls only; never appended to Session.
</ParamField>

<ParamField body="model" type="string | null" default="from session">
  Model override for this turn. On pending (deferred) sessions this sets the model before materialization. On materialized sessions this hot-swaps the LLM client for the remainder of the session.
</ParamField>

<ParamField body="provider" type="string | null" default="from session">
  Provider override (e.g. `"anthropic"`, `"openai"`, `"gemini"`). Typically inferred from `model`.
</ParamField>

<ParamField body="provider_params" type="object | null" default="from session">
  Provider-specific parameters (e.g. `{"thinking_budget": 10000}`). Applied alongside model/provider override.
</ParamField>

<ParamField body="max_tokens" type="u32 | null" default="from session">
  Max tokens override.
</ParamField>

<ParamField body="skill_refs" type="object[] | null">
  Tagged structured skill references to resolve and inject for this turn. Each entry uses `{"kind":"structured","source_uuid":"...","skill_name":"..."}`.
</ParamField>

### turn/interrupt

Cancel an in-flight turn. No-op if the session is idle.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":7,"method":"turn/interrupt","params":{"session_id":"01936f8a-..."}}
  ```

  ```json Response theme={null}
  {"jsonrpc":"2.0","id":7,"result":{"interrupted":true}}
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to interrupt.
</ParamField>

## Event methods

### session/external\_event

Queue a runtime-backed external event for an existing session.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 8,
    "method": "session/external_event",
    "params": {
      "session_id": "01936f8a-...",
      "kind": "generic_json",
      "event_type": "ci-pipeline",
      "payload": {"alert": "build failed", "repo": "main"}
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 8,
    "result": {
      "outcome_type": "accepted"
    }
  }
  ```
</CodeGroup>

### session/peer\_response\_terminal

Admit a correlated terminal peer response through the typed runtime ingress.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 9,
    "method": "session/peer_response_terminal",
    "params": {
      "session_id": "01936f8a-...",
      "peer_id": "00000000-0000-4000-8000-000000000161",
      "display_name": "analyst",
      "request_id": "00000000-0000-4000-8000-000000000162",
      "status": "completed",
      "result": {"token": "silver harbor"}
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 9,
    "result": {
      "outcome_type": "accepted",
      "input_id": "01936f8a-..."
    }
  }
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to admit the peer response to.
</ParamField>

<ParamField body="peer_id" type="string" required>
  Canonical peer routing ID.
</ParamField>

<ParamField body="display_name" type="string">
  Optional presentation label. It is not used as routing identity.
</ParamField>

<ParamField body="request_id" type="string" required>
  Peer correlation ID for the request this terminal response completes.
</ParamField>

<ParamField body="status" type="string" required>
  Terminal response status: `"completed"`, `"failed"`, or `"cancelled"`.
</ParamField>

<ParamField body="result" type="any JSON" required>
  Peer-returned terminal payload.
</ParamField>

Error `-32603` if runtime admission fails, `-32602` if the session locator is invalid.

This is a queue-only runtime admission path; it does not create a second direct execution loop.

### comms/peers

List discoverable peers from configured `TrustedPeers` and active in-process registrations. Requires the `comms` feature.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 9,
    "method": "comms/peers",
    "params": {
      "session_id": "01936f8a-..."
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 9,
    "result": {
      "peers": [
        {
          "peer_id": "550e8400-e29b-41d4-a716-446655440001",
          "name": "reviewer",
          "address": {
            "transport": "tcp",
            "endpoint": "127.0.0.1:4201"
          },
          "source": "trusted",
          "sendable_kinds": ["peer_message", "peer_request", "peer_response"],
          "capabilities": {
            "version": 1,
            "extensions": {"review": true}
          },
          "meta": {
            "description": "Reviews pull requests",
            "labels": {"role": "reviewer"}
          }
        },
        {
          "peer_id": "550e8400-e29b-41d4-a716-446655440002",
          "name": "coordinator",
          "address": {
            "transport": "inproc",
            "endpoint": "coordinator"
          },
          "source": "inproc",
          "sendable_kinds": ["peer_message", "peer_request", "peer_response"],
          "capabilities": {"version": 1, "extensions": {}},
          "meta": {}
        }
      ]
    }
  }
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to query peers for.
</ParamField>

Use `peer_id` as the `to` value for `comms/send`; `name` is display-only and
may collide. Each entry uses the canonical typed `PeerDirectoryEntry` shape:
`address` is `{transport, endpoint}`, `source` records discovery provenance,
`sendable_kinds` states supported comms operations, `capabilities` carries the
versioned capability envelope, and `meta` contains supplementary description
and labels.

### skills/list

List all skills with provenance information, including active and shadowed entries.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":12,"method":"skills/list"}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 12,
    "result": {
      "skills": [
        {
          "key": {
            "source_uuid": "00000000-0000-4b11-8111-000000000001",
            "skill_name": "task-workflow"
          },
          "name": "Task Workflow",
          "description": "How to use task tools",
          "scope": "builtin",
          "source": {
            "source_uuid": "00000000-0000-4b11-8111-000000000001",
            "display_name": "embedded",
            "transport_kind": "embedded",
            "fingerprint": "embedded:inventory",
            "status": "active"
          },
          "is_active": true
        },
        {
          "key": {
            "source_uuid": "00000000-0000-4b11-8111-000000000002",
            "skill_name": "my-deployment"
          },
          "name": "Deployment Guide",
          "description": "Project-specific deployment",
          "scope": "project",
          "source": {
            "source_uuid": "00000000-0000-4b11-8111-000000000002",
            "display_name": "project",
            "transport_kind": "filesystem",
            "fingerprint": "filesystem:.rkat/skills",
            "status": "active"
          },
          "is_active": true
        },
        {
          "key": {
            "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
            "skill_name": "task-workflow"
          },
          "name": "Custom Task Workflow",
          "description": "Override tasks",
          "scope": "project",
          "source": {
            "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
            "display_name": "company",
            "transport_kind": "git",
            "fingerprint": "repo-7cc66f36fd9db1a1",
            "status": "active"
          },
          "is_active": true
        }
      ]
    }
  }
  ```
</CodeGroup>

<ResponseField name="skills" type="array">
  List of `SkillEntry` objects with `key`, `name`, `description`, `scope`, canonical `source` provenance, `is_active`, and optional canonical `shadowed_by` provenance.
</ResponseField>

Returns error `-32603` if skills are not enabled.

`skills/inspect` is not part of the advertised RPC catalog. Use `skills/list` for provenance, or the CLI/MCP skill inspection surfaces when full skill bodies are needed.

## Live channel methods

Live channels provide low-latency audio and text streaming plus model-gated still-image input on sessions that use a realtime-capable model. Create a session with a model like `gpt-realtime-2`, then call `live/open` to start the channel explicitly. The `--live-ws <addr>` flag on `rkat-rpc` enables the WebSocket listener required for audio transport. See the [Live Channels guide](/guides/realtime) for the full flow.

### Opening a live channel

Create a session on a realtime-capable model and call `live/open`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 19,
  "method": "session/create",
  "params": {
    "prompt": "Let's talk.",
    "model": "gpt-realtime-2",
    "provider": "openai"
  }
}
```

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 20,
  "method": "live/open",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001"
  }
}
```

`live/open` returns a `LiveOpenResult` with transport bootstrap (e.g. WebSocket URL), `WireLiveChannelCapabilities`, and `WireLiveContinuityMode`.

<ParamField body="session_id" type="string" required>
  Session whose canonical history seeds the live channel.
</ParamField>

<ParamField body="turning_mode" type="provider_managed | explicit_commit | null" default="null">
  Optional input-turning mode. Omitted preserves provider-managed behavior.
</ParamField>

<ParamField body="transport" type="websocket | webrtc | null" default="null">
  Optional live transport. Omitted uses the server default.
</ParamField>

<ParamField body="seed_max_chars" type="usize | null" default="null">
  Optional positive serialized-character budget for the core-owned seed
  message window. Omitted preserves the complete canonical history. When
  present, core selects a recent whole-turn suffix. Every ordered System
  message is retained and their combined serialized size must fit; an existing
  compaction-summary head may also be retained. Any truncation returns degraded
  continuity. Zero is rejected.
</ParamField>

System messages are ordinary ordered transcript data and are retained by the
message window rules above. Canonical multimodal sidecars remain outside the
message window. Image identity, tombstones, and aggregate accounting stay
complete even when older seed messages are omitted.

### live/status

Read the current state of a live channel.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 22,
    "method": "live/status",
    "params": {
      "channel_id": "ch_01936f8a-..."
    }
  }
  ```
</CodeGroup>

### live/send\_input

Send one typed input chunk. Image input is available only when
`LiveOpenResult.capabilities.image_in` is `true`; an image is staged as context
for the next text, audio, or explicitly committed response. Every image must
carry a caller-stable, session-scoped `idempotency_key`.

The JSON-RPC JSONL transport accepts frames up to 64 MiB, excluding the
trailing newline. Direct live WebSocket frames are a different input path:
they support JSON text chunks and negotiated raw PCM audio only, with a 2 MiB
aggregate/per-frame ceiling. Images always use this JSON-RPC method, even when
the channel's observation/audio transport is WebSocket or WebRTC.

Server-originated JSON-RPC responses are capped at 32 MiB and queued
notifications at 8 MiB. Their byte/count reservations are process-wide and
remain owned through the bounded transport write; oversized collection reads
must use pagination instead of relying on socket buffering.

<CodeGroup>
  ```json Image input theme={null}
  {
    "jsonrpc": "2.0",
    "id": 23,
    "method": "live/send_input",
    "params": {
      "channel_id": "ch_01936f8a-...",
      "chunk": {
        "kind": "image",
        "idempotency_key": "turn-42-diagram",
        "mime": "image/png",
        "data": "iVBORw0KGgo..."
      }
    }
  }
  ```
</CodeGroup>

The key must be non-empty, no more than 128 UTF-8 bytes, contain no control
characters, and have no leading or trailing whitespace. Replay the same key
with the same canonical MIME and bytes after a lost receipt: Meerkat does not
resend it to the provider and emits the existing durable identity again.
Reusing a key for different content is rejected as
`image_input_idempotency_conflict`. If text or audio is already staged, commit
it before submitting an image; otherwise the image is rejected as
`image_input_requires_commit`.

`{ "status": "sent" }` proves only that the adapter queue accepted the
command. Wire validation and queue admission can instead fail immediately with
typed `LiveSendInputErrorData`. A check that fails after acceptance is emitted
as a typed `command_rejected` observation. Only a
`user_content_committed` observation carrying the same `idempotency_key`
proves the provider-acknowledged image reached durable canonical session
history. The receipt is redacted: it contains identity, ordering, media type,
and the key, never image bytes.

Each image is limited to 20 MiB decoded, and canonical live image history is
limited to 40 MiB decoded in aggregate, counting repeated references as
separate occurrences. `live/send_input` rejects a new image that would cross
the aggregate ceiling as `image_input_history_budget_exceeded` before provider
send or persistence. That keeps every successfully committed live image
reopenable. Legacy or out-of-band history already above the ceiling, missing
blobs, and content-address mismatches fail `live/open` rather than trimming,
substituting, or changing image context. See the
[Live Channels guide](/guides/realtime#sending-image-input) for retry and
transport details.

### Live channel lifecycle methods (`live/*`)

| Method               | Purpose                                                                                                                                                                                                             |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `live/open`          | Open a live channel; optional positive `seed_max_chars` bounds serialized whole-turn seed messages                                                                                                                  |
| `live/webrtc/answer` | Answer a browser WebRTC offer for an already-open live channel                                                                                                                                                      |
| `live/status`        | Get the status of a live channel                                                                                                                                                                                    |
| `live/close`         | Close a live channel                                                                                                                                                                                                |
| `live/send_input`    | Send an audio, text, or model-supported image chunk to a live channel                                                                                                                                               |
| `live/commit_input`  | Commit pending input on a live channel (turn boundary)                                                                                                                                                              |
| `live/interrupt`     | Interrupt the assistant turn on a live channel (barge-in)                                                                                                                                                           |
| `live/truncate`      | Truncate assistant output at a client-tracked playback cursor                                                                                                                                                       |
| `live/refresh`       | Apply mutable session config (instructions/tools/audio) to an open channel; config-only, does not replay history; identity swaps and canonical transcript/user-content rewrites return typed reopen-required errors |

These require `rkat-rpc` to be started with `--live-ws <addr>` for WebSocket transport.

## MCP methods

### mcp/add

Stage a live MCP server addition for a running session. The server is connected at the next turn boundary.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 14,
    "method": "mcp/add",
    "params": {
      "session_id": "01936f8a-...",
      "server_config": {
        "name": "my-tools",
        "command": "npx",
        "args": ["-y", "@my/mcp-server"]
      },
      "persisted": false
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 14,
    "result": {
      "session_id": "01936f8a-...",
      "operation": "add",
      "server_name": "my-tools",
      "status": "staged",
      "persisted": false,
      "applied_at_turn": null
    }
  }
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to add the server to.
</ParamField>

<ParamField body="server_config" type="object" required>
  Typed MCP server configuration. Include `name` with either stdio fields (`command`, optional `args`/`env`) or HTTP fields (`url`, optional `headers`/`transport`).
</ParamField>

<ParamField body="persisted" type="bool" default="false">
  Whether to also write the server to disk config.
</ParamField>

### mcp/remove

Stage removal of an MCP server from a running session. Active tool calls drain before the server disconnects at the next turn boundary.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 15,
    "method": "mcp/remove",
    "params": {
      "session_id": "01936f8a-...",
      "server_name": "my-tools",
      "persisted": false
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 15,
    "result": {
      "session_id": "01936f8a-...",
      "operation": "remove",
      "server_name": "my-tools",
      "status": "staged",
      "persisted": false,
      "applied_at_turn": null
    }
  }
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to remove the server from.
</ParamField>

<ParamField body="server_name" type="string" required>
  Name of the MCP server to remove.
</ParamField>

<ParamField body="persisted" type="bool" default="false">
  Whether to also remove from disk config.
</ParamField>

### mcp/reload

Reload one or all MCP servers for a running session. Useful after config changes.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 16,
    "method": "mcp/reload",
    "params": {
      "session_id": "01936f8a-...",
      "server_name": "my-tools"
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 16,
    "result": {
      "session_id": "01936f8a-...",
      "operation": "reload",
      "server_name": "my-tools",
      "status": "staged",
      "persisted": false,
      "applied_at_turn": null
    }
  }
  ```
</CodeGroup>

<ParamField body="session_id" type="string" required>
  Session ID to reload servers for.
</ParamField>

<ParamField body="server_name" type="string | null" default="null">
  Specific server to reload. If null, reloads all servers.
</ParamField>

## Models

### models/catalog

Return the curated model catalog with provider profiles, capability metadata, and parameter schemas.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":17,"method":"models/catalog"}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 17,
    "result": {
      "contract_version": "0.8.22",
      "providers": [
        {
          "provider": "anthropic",
          "default_model_id": "claude-opus-5",
          "models": [
            {
              "id": "claude-opus-5",
              "display_name": "Claude Opus 5",
              "tier": "recommended",
              "context_window": 1000000,
              "max_output_tokens": 128000,
              "profile": {
                "model_family": "claude-opus-5",
                "supports_temperature": false,
                "supports_thinking": true,
                "supports_reasoning": false,
                "params_schema": {}
              }
            }
          ]
        }
      ]
    }
  }
  ```
</CodeGroup>

No parameters are required. The catalog is resolved from built-in model metadata plus config-backed provider/server entries; invalid provider config can yield `INVALID_PARAMS`.

<ResponseField name="contract_version" type="string">
  Contract version for the catalog response.
</ResponseField>

<ResponseField name="providers" type="array">
  List of provider entries, each containing `provider`, `default_model_id`, and `models`.
</ResponseField>

<ResponseField name="providers[].models[].profile" type="object">
  Model profile with capability flags (`supports_temperature`, `supports_thinking`, `supports_reasoning`) and `params_schema`.
</ResponseField>

## Capabilities

### capabilities/get

Return runtime capabilities with status resolved against config. This lists every capability known to Meerkat with its current status (available, disabled by policy, not compiled, etc.).

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":8,"method":"capabilities/get"}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 8,
    "result": {
      "contract_version": {"major": 0, "minor": 8, "patch": 22},
      "capabilities": [
        {
          "id": "sessions",
          "description": "Session lifecycle management",
          "status": "Available"
        },
        {
          "id": "structured_output",
          "description": "Structured output extraction with JSON schema",
          "status": "Available"
        },
        {
          "id": "hooks",
          "description": "Lifecycle hooks for tool and turn events",
          "status": "Available"
        },
        {
          "id": "builtins",
          "description": "Built-in tools (task management)",
          "status": {"DisabledByPolicy": {"description": "Disabled by config"}}
        },
        {
          "id": "shell",
          "description": "Shell command execution",
          "status": {"DisabledByPolicy": {"description": "Disabled by config"}}
        },
        {
          "id": "comms",
          "description": "Inter-agent communication",
          "status": {"NotCompiled": {"feature": "comms"}}
        },
        {
          "id": "memory_store",
          "description": "Semantic memory indexing",
          "status": "Available"
        },
        {
          "id": "skills",
          "description": "Skill loading and injection",
          "status": "Available"
        }
      ]
    }
  }
  ```
</CodeGroup>

Possible `status` values:

| Status                   | Shape                                           | Meaning                                           |
| ------------------------ | ----------------------------------------------- | ------------------------------------------------- |
| `Available`              | `"Available"`                                   | Compiled in, config-enabled, protocol supports it |
| `DisabledByPolicy`       | `{"DisabledByPolicy": {"description": "..."}}`  | Compiled in but disabled by policy                |
| `NotCompiled`            | `{"NotCompiled": {"feature": "..."}}`           | Feature flag absent at compile time               |
| `NotSupportedByProtocol` | `{"NotSupportedByProtocol": {"reason": "..."}}` | This protocol surface does not support it         |

## Config methods

### config/get

Read current realm config envelope.

<CodeGroup>
  ```json Request theme={null}
  {"jsonrpc":"2.0","id":9,"method":"config/get"}
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 9,
    "result": {
      "config": {
        "agent": {
          "model": "claude-sonnet-4-6",
          "max_tokens_per_turn": 8192
        }
      },
      "generation": 3,
      "realm_id": "team-alpha",
      "instance_id": "rpc-worker-1",
      "backend": "sqlite",
      "resolved_paths": {
        "root": "/.../meerkat/realms/team-alpha",
        "manifest_path": "/.../realm_manifest.json",
        "config_path": "/.../config.toml",
        "sessions_sqlite_path": "/.../sessions.sqlite3",
        "sessions_jsonl_dir": "/.../sessions_jsonl"
      }
    }
  }
  ```
</CodeGroup>

### config/set

Replace config, optionally using generation CAS.

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc":"2.0",
    "id":10,
    "method":"config/set",
    "params":{
      "config": {"agent":{"model":"gpt-5.5"}},
      "expected_generation": 3
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc":"2.0",
    "id":10,
    "result": {
      "config": {"agent":{"model":"gpt-5.5"}},
      "generation": 4,
      "realm_id": "team-alpha",
      "instance_id": null,
      "backend": "sqlite",
      "resolved_paths": { "...": "..." }
    }
  }
  ```
</CodeGroup>

### config/patch

Merge-patch the config (RFC 7396).

<CodeGroup>
  ```json Request theme={null}
  {
    "jsonrpc":"2.0",
    "id":11,
    "method":"config/patch",
    "params":{
      "patch":{"agent":{"max_tokens_per_turn":8192}},
      "expected_generation": 4
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc":"2.0",
    "id":11,
    "result": {
      "config": {"agent":{"max_tokens_per_turn":8192}},
      "generation": 5,
      "realm_id": "team-alpha",
      "instance_id": null,
      "backend": "sqlite",
      "resolved_paths": { "...": "..." }
    }
  }
  ```
</CodeGroup>

<Note>
  `config/set` also accepts a direct config object as params for compatibility. In that mode, no CAS check is applied.
</Note>

## Notifications

During turn execution, the server emits `session/event` notifications containing serialized `AgentEvent` payloads:

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/event",
  "params": {
    "session_id": "01936f8a-...",
    "event": {
      "type": "text_delta",
      "delta": "Rust is"
    }
  }
}
```

Event types match the `AgentEvent` enum in `meerkat-core/src/event.rs`
(`agent_event_type` assigns each variant its stable wire name) and are emitted
to `artifacts/schemas/events.json`. New variants must appear in both that enum
and this table.

| Event                          | Description                                                                                                                         |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `run_started`                  | Agent execution began                                                                                                               |
| `run_completed`                | Agent run finished                                                                                                                  |
| `extraction_succeeded`         | Structured-output extraction succeeded after a completed run                                                                        |
| `extraction_failed`            | Structured-output extraction failed after a completed run                                                                           |
| `run_failed`                   | Agent run failed                                                                                                                    |
| `turn_started`                 | New LLM call within the turn                                                                                                        |
| `reasoning_delta`              | Streaming reasoning/thinking chunk from the model                                                                                   |
| `reasoning_complete`           | Reasoning/thinking complete for this block                                                                                          |
| `text_delta`                   | Streaming text chunk from LLM                                                                                                       |
| `text_complete`                | Full text for this turn                                                                                                             |
| `server_tool_content`          | Provider-executed tool content surfaced during a model turn                                                                         |
| `assistant_image_appended`     | Canonical assistant image block appended to transcript history                                                                      |
| `tool_call_requested`          | LLM wants to call a tool                                                                                                            |
| `tool_result_received`         | Tool result processed                                                                                                               |
| `turn_completed`               | LLM call finished                                                                                                                   |
| `tool_execution_started`       | Tool dispatch began                                                                                                                 |
| `tool_execution_completed`     | Tool returned a result                                                                                                              |
| `tool_execution_timed_out`     | Tool exceeded timeout                                                                                                               |
| `compaction_started`           | Context compaction began                                                                                                            |
| `compaction_completed`         | Compaction finished                                                                                                                 |
| `compaction_failed`            | Compaction failed                                                                                                                   |
| `budget_warning`               | Approaching resource limits                                                                                                         |
| `retrying`                     | Retrying after transient error                                                                                                      |
| `hook_started`                 | Hook execution began                                                                                                                |
| `hook_completed`               | Hook finished                                                                                                                       |
| `hook_failed`                  | Hook execution failed                                                                                                               |
| `hook_denied`                  | Hook blocked operation                                                                                                              |
| `skills_resolved`              | Skills loaded for turn                                                                                                              |
| `skill_resolution_failed`      | Skill resolution failed                                                                                                             |
| `tool_config_changed`          | Tool visibility or MCP config changed                                                                                               |
| `background_job_completed`     | Background shell job reached a typed terminal status; `terminal_status` is semantic and `status` is only an optional display mirror |
| `interaction_complete`         | Interaction-scoped stream completed                                                                                                 |
| `interaction_callback_pending` | Interaction reached a callback boundary and is waiting for tool results                                                             |
| `interaction_failed`           | Interaction-scoped stream failed                                                                                                    |
| `stream_truncated`             | Backpressure dropped intermediate events                                                                                            |

### session/stream\_event notifications

When a session event stream is open (via `session/stream_open`), the server emits `session/stream_event` notifications. The notification payload mirrors `session/event`, but is scoped to the explicit stream handle.

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "session/stream_event",
  "params": {
    "stream_id": "550e8400-e29b-41d4-a716-446655440000",
    "sequence": 1,
    "session_id": "sess_123",
    "event": { "...": "..." }
  }
}
```

### mob/stream\_event notifications

When a mob event stream is open (via `mob/stream_open`), the server emits `mob/stream_event` notifications. Requires the `mob` feature.

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "mob/stream_event",
  "params": {
    "stream_id": "550e8400-e29b-41d4-a716-446655440000",
    "sequence": 1,
    "event": { "...": "..." }
  }
}
```

For mob-wide streams the event is an `AttributedEvent` (`source` member identity + profile + envelope). For per-member streams the event is the raw `EventEnvelope<AgentEvent>`. Runtime incarnation ids and fence tokens are bridge-internal and are not part of public stream payloads.

## Error codes

Standard JSON-RPC codes plus Meerkat-specific application codes:

| Code   | Name                    | Description                            |
| ------ | ----------------------- | -------------------------------------- |
| -32700 | Parse error             | Invalid JSON                           |
| -32600 | Invalid request         | Not a valid JSON-RPC request           |
| -32601 | Method not found        | Unknown method                         |
| -32602 | Invalid params          | Missing or invalid parameters          |
| -32603 | Internal error          | Server error                           |
| -32001 | Session not found       | Session ID does not exist              |
| -32002 | Session busy            | Turn already in progress               |
| -32003 | Session not running     | Session not in running state           |
| -32010 | Provider error          | LLM provider issue (missing key, auth) |
| -32011 | Budget exhausted        | Resource limits reached                |
| -32012 | Hook denied             | Hook blocked the operation             |
| -32013 | Agent error             | Internal agent error                   |
| -32020 | Capability unavailable  | Required capability not available      |
| -32021 | Skill not found         | Requested skill does not exist         |
| -32022 | Skill resolution failed | Skill resolution error                 |

## Architecture

The RPC server is **stateful**: agents stay alive between turns. This is the key difference from REST (stateless per-request) and MCP (callback pattern).

```text theme={null}
Client (IDE, app) <--stdio JSONL--> RpcServer
                                       |
                                  MethodRouter
                                       |
                                  SessionRuntime
                                   /    |    \
                            Session  Session  Session
                             Task    Task     Task
                              |       |        |
                            Agent   Agent    Agent
                         (exclusive ownership)
```

Each session gets a dedicated tokio task that exclusively owns the `Agent`. This solves the `cancel(&mut self)` requirement without mutex. Commands (`StartTurn`, `Interrupt`, `Shutdown`) are sent via channels.

<Note>
  **Backpressure:** The notification channel is bounded. When the client reads slowly, the agent naturally slows down.
</Note>

## Comparison with other surfaces

|               | CLI    | REST             | MCP      | RPC                 |
| ------------- | ------ | ---------------- | -------- | ------------------- |
| Stateful      | No     | No               | No       | **Yes**             |
| Streaming     | stderr | SSE              | Optional | JSONL notifications |
| Multi-session | No     | No               | No       | **Yes**             |
| Cancellation  | Ctrl+C | N/A              | N/A      | `turn/interrupt`    |
| Bidirectional | No     | No (SSE one-way) | Partial  | **Yes**             |

## See also

* [CLI reference](/cli/commands)
* [REST API](/api/rest)
* [MCP](/api/mcp)
* [Architecture](/reference/architecture)
