Skip to main content
Meerkat ships a REST server for running and managing agent sessions over HTTP. This is the best fit if you want a simple, language-agnostic API for the Meerkat core.

Getting started

1

Start the server

2

Set API keys

Export the key for your chosen provider:
3

Send a request

Runtime scope

rkat-rest accepts:
  • --realm <id>
  • --isolated
  • --instance <id>
  • --realm-backend <sqlite|jsonl|memory>
  • --state-root <path>
  • --context-root <path>
  • --user-config-root <path>
  • --expose-paths
If --realm is omitted, the server creates a new isolated opaque realm (realm-...). --realm-backend is a creation hint only; after first open, realm_manifest.json is authoritative.

Endpoint overview

This overview follows the generated OpenAPI artifact at artifacts/schemas/rest-openapi.json.
Schedule endpoints return the same flattened public Schedule contract as JSON-RPC. Planning, labels, and created/updated timestamps are top-level; there is no nested config and persisted machine_state is not public.
WorkGraph goal and attention mutation routes require trusted in-process host/session authority and are not part of the public REST catalog. Multi-host mob administration (host bind/revoke, hard-cancel, member live channels, grant management) is deliberately NOT served by REST — REST carries observation GETs only. The complete admin family lives on JSON-RPC and the Python/TypeScript SDKs; host binding/revoke, grants, and live control also have CLI verbs, while hard cancel is RPC/SDK-only.
Generated images are not returned as inline bytes in history. GET /sessions/{id}/history returns assistant image blocks with image_id, blob_ref, dimensions, and metadata; fetch image bytes through the blob/artifact surface exposed by the runtime-backed RPC/SDK path.
REST keeps observation and helper endpoints for mobs, but typed lifecycle/control for app hosts lives on the canonical RPC/SDK mob/* surface. Inside running sessions, mob capability is still exposed by composing meerkat-mob-mcp (MobMcpState + AgentMobToolSurfaceFactory) into SessionBuildOptions.mob_tools in the host runtime. external_tools remains reserved for callback and MCP-backed dispatchers.
WorkGraph REST endpoints are observability/operator lookup, including goal-status and attention-list reads. Agents create, claim, update, link, evidence, close, reassign attention, and escalate policy through WorkGraph tools inside sessions; goal and attention mutators stay on trusted in-process host authority.

Request cancellation

REST request cancellation is opt-in and request-ID based.
  • send X-Meerkat-Request-Id: <id> on POST /sessions or POST /sessions/{id}/messages
  • call POST /requests/{request_id}/cancel to cancel uncommitted in-flight work
  • duplicate in-flight request IDs are rejected
Cancellation only affects uncommitted work:
  • pre-start / pre-commit work may return cancelled
  • committed success is not rewritten to cancellation
  • post-commit create failures still return session identity and remain resumable

Configuration

REST configuration is realm-scoped:
  • macOS: ~/Library/Application Support/meerkat/realms/<realm>/config.toml
  • Linux: ~/.local/share/meerkat/realms/<realm>/config.toml
  • Windows: %APPDATA%\\meerkat\\realms\\<realm>\\config.toml
Each realm also has realm_manifest.json (backend pinning) and config_state.json (generation CAS state).Key sections:
API keys are provided via environment variables:
  • ANTHROPIC_API_KEY
  • OPENAI_API_KEY
  • GOOGLE_API_KEY

Endpoints

POST /help

Ask Meerkat usage help with the embedded platform skill.
Request
Returns a HelpResponse with the answer text and any plan metadata requested by the input.

POST /sessions

Create and run a new session.

Request fields

string
required
The user prompt to send to the agent.
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. Older REST servers silently ignore this field (existing REST version-skew posture).
string | null
default:"null"
Non-empty, exact host-regenerated facts for the first logical turn. Whitespace is significant. Meerkat persists the text only with the pending runtime input for crash retry and projects it as a request-local user-channel context message immediately before that turn’s conversational user message. It never enters Session history, compaction, or extraction requests.
SystemPromptOverride
default:"inherit"
Typed per-request system-prompt policy: omit/null to inherit, a string to set an explicit prompt, or {"action": "disable"} to suppress every prompt source.
string | null
default:"config default"
Model name (e.g. "claude-opus-4-8", "gpt-5.5").
string | null
default:"inferred from model"
Provider: "anthropic", "openai", "gemini", "self_hosted", "other".
u32 | null
default:"config default"
Max tokens per turn.
OutputSchema | null
default:"null"
JSON schema for structured output extraction (wrapper or raw schema).
u32 | null
default:"null"
Max retries for structured output validation. null/omitted uses the server default on create and inherits the persisted session value on continue.
bool
default:"false"
Enable verbose event logging (server-side).
bool | null
default:"null"
Keep session alive after turn for comms. On create, null/omitted uses the create default (false), true enables, and false explicitly disables. Requires comms_name when enabled.
string | null
default:"null"
Agent name for inter-agent communication.
object | null
default:"null"
Friendly metadata for peer discovery (name, description, labels).
HookRunOverrides | null
default:"null"
Run-scoped hook overrides (see Hooks).
bool | null
default:"null (factory default)"
Enable built-in tools (task management, etc.). Omit to use factory defaults.
bool | null
default:"null (factory default)"
Enable shell tool (requires enable_builtins). Omit to use factory defaults.
bool | null
default:"null (factory default)"
Enable semantic memory. Omit to use factory defaults.
bool | null
default:"null (factory default)"
Override schedule tools for this session. Omit to use factory defaults.
bool | null
default:"null (factory default)"
Override WorkGraph tools for this session. Omit to use factory defaults.

Response fields

string
UUID of the created session.
string
The agent’s response text.
u32
Number of LLM calls made.
u32
Number of tool calls executed.
WireUsage
Token usage breakdown.
object | null
Parsed structured output (when output_schema was provided).
array | null
Schema compatibility warnings per provider.

GET /sessions//history

Read committed transcript history for a session without changing the lightweight metadata shape of GET /sessions/{id}. Query parameters:
  • offset — skip this many messages from the start of the transcript
  • limit — cap the number of returned messages
History is returned oldest-to-newest and reflects the last committed session snapshot only.

GET /sessions

List sessions. Supports optional label filters via query parameters.
Response

POST /sessions/{id}/messages

Continue an existing session.

Request fields

string
required
Session ID (must match the path {id}).
string
required
Follow-up prompt.
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. Older REST servers silently ignore this field (existing REST version-skew posture).
string | null
default:"null"
Non-empty, exact host-regenerated facts for this logical turn. Whitespace is significant. The value is available to every foreground provider call and retry in the turn, persists only while the runtime input is pending, and never becomes a Session message.
string | null
default:"null"
Override the system prompt.
string | null
default:"from session"
Model override for this turn. On materialized sessions this hot-swaps the LLM client for the remainder of the session.
string | null
default:"from session"
Provider override for this turn. Typically inferred from model. Used with model for mid-session provider switching.
u32 | null
default:"from session"
Max tokens override for this turn.
OutputSchema | null
default:"null"
Structured output schema for this turn.
u32 | null
default:"null"
Max retries for structured output validation. Omit / null to inherit the persisted session value on continue.
bool
default:"false"
Enable verbose event logging.
bool | null
default:"null"
Keep-alive override for this turn. null = inherit persisted session intent, true = enable, false = disable.
string | null
default:"from session"
Agent name for comms.
HookRunOverrides | null
default:"null"
Run-scoped hook overrides.

Response fields

Same shape as POST /sessions.

POST /sessions/{id}/interrupt

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

POST /requests/{request_id}/cancel

Cancel an uncommitted in-flight request that previously supplied X-Meerkat-Request-Id.
Response
Returns 200 with {"cancelled": false, "reason": "already_terminal"} when the tracked request already published or completed. Returns 404 only when the request ID is unknown.

DELETE /sessions/{id}

Archive (remove) a session.
Response
Returns 404 if the session is not found.

POST /sessions/{id}/external-events

Queue an external event through the runtime-backed admission path.
This route keeps the optional RKAT_WEBHOOK_SECRET header auth used for webhook delivery, but the admitted event now flows through runtime input acceptance instead of a surface-local injector path.
any JSON
required
Any JSON payload. Pretty-printed and injected as an event into the agent’s inbox.
string
Webhook secret for authentication. Required when RKAT_WEBHOOK_SECRET env var is set on the server. Compared using constant-time equality (subtle::ConstantTimeEq).

POST /sessions/{id}/peer-response-terminal

Admit a terminal peer response through the typed runtime ingress.
string
required
Canonical peer routing ID. Display names are not accepted as routing identity.
string
Optional presentation label.
string
required
Peer correlation ID for the request this terminal response completes.
string
required
Terminal response status: "completed", "failed", or "cancelled".
any JSON
required
Peer-returned terminal payload.

GET /sessions/{id}

Fetch session metadata and usage.
Response

GET /sessions/{id}/events

Server-Sent Events (SSE) stream for real-time updates. Event types:

GET /skills

List all skills with provenance information. Returns active and shadowed entries.
Response
Returns 404 if skills are not enabled.

GET /health

Returns "ok" (HTTP 200). Use for liveness checks.

GET /models/catalog

Return the curated model catalog with provider profiles, capability metadata, and parameter schemas.
Response (abbreviated)
The catalog is resolved from built-in model metadata plus config-backed provider/server entries. Each provider entry includes the default model and a list of models with their capabilities and parameter schemas.

GET /capabilities

Returns runtime capabilities with status resolved against config.
Response (abbreviated)
The full response includes all capabilities: sessions, streaming, structured_output, hooks, builtins, shell, comms, memory_store, schedule, work_graph, session_store, session_compaction, skills, mcp_live. See the RPC capabilities endpoint for the complete example.

GET /config

Returns a realm config envelope:
  • config
  • generation
  • realm_id
  • instance_id
  • backend
  • resolved_paths

PUT /config

Replaces config. Accepted request forms:
  • Direct config object (compat)
  • Wrapped form with CAS:
    • { "config": <Config>, "expected_generation": <u64|null> }

PATCH /config

Applies RFC 7396 merge patch. Accepted request forms:
  • Direct patch object (compat)
  • Wrapped form with CAS:
    • { "patch": <JSON>, "expected_generation": <u64|null> }
If expected_generation is stale, the server returns 400 with a generation-conflict message.

GET /auth/profiles

List the auth profiles, backend profiles, and provider bindings for a realm.
string
required
Realm to read.
string | null
Optional profile selector accepted by the shared auth query shape.
Response

POST /auth/profiles

Store credentials for an existing binding-scoped auth profile. The binding must resolve to an auth profile whose source is managed_store; inline, env, external resolver, platform-default, command, and file-descriptor sources are configured outside this endpoint.
Request
Response (201 Created)
string
required
Realm containing the binding.
string
required
Binding whose configured auth profile will receive the stored credential.
string | null
Optional explicit profile override for the binding.
string
required
Provider expected from the resolved auth profile.
string
required
Stored-secret method: "api_key", "azure_api_key", or "static_bearer".
string
required
Secret material to persist in the token store.

GET /auth/bindings/{binding_id}

Read the auth profile resolved by a binding.
string
required
Binding to resolve.
string
required
Realm containing the binding.
string | null
Optional explicit profile override for the binding.

DELETE /auth/bindings/{binding_id}

Clear stored credentials for the resolved binding-scoped auth profile.
string
required
Binding whose stored credentials should be cleared.
string
required
Realm containing the binding.
string | null
Optional explicit profile override for the binding.

POST /auth/bindings/{binding_id}/test

Resolve a binding through the provider registry and report whether credential material or a dynamic authorizer is available.
Request
string
required
Binding to test.
string
required
Realm containing the binding.
string | null
Optional explicit profile override for the binding.

POST /auth/login/start

Begin a loopback OAuth login. The server owns the OAuth state and PKCE verifier.
Request

POST /auth/login/complete

Complete a loopback OAuth login and store the resulting tokens under an explicit binding-scoped AuthBindingRef.
Request
string
required
Realm containing the binding.
string
required
Binding that owns the stored OAuth tokens.
string | null
Optional explicit profile override for the binding.

POST /auth/login/device/start

Begin a device-code OAuth login.
Request

POST /auth/login/device/complete

Poll one device-code OAuth completion attempt and, when ready, store the tokens under an explicit binding-scoped AuthBindingRef.
Request
Returns 202 with { "state": "pending" } when the provider has not finished, 429 with { "state": "slow_down" } when the caller should back off, and 200 with a ready payload after tokens are persisted.

GET /auth/bindings/{binding_id}/status

Read binding-scoped auth status. The response includes the flattened binding identity plus profile_id, provider, auth_method, public state, expiration, refresh timestamp, account ID, and refresh-token presence.
string
required
Binding whose status should be read.
string
required
Realm containing the binding.
string | null
Optional explicit profile override for the binding.

POST /auth/bindings/{binding_id}/logout

Clear stored credentials for the binding and publish the auth lifecycle release.
string
required
Binding to log out.
string
required
Realm containing the binding.
string | null
Optional explicit profile override for the binding.

GET /realms

List configured realm summaries.

GET /realms/{id}

Read one realm connection set.

POST /comms/send

Push a canonical comms command into a running session. Requires the comms feature.
string
required
Session ID to dispatch the comms command to.
string
required
Command kind: "input", "peer_message", "peer_lifecycle", "peer_request", or "peer_response".
string | null
Canonical peer ID to send to (required for peer_message, peer_lifecycle, peer_request, and peer_response).
string | null
Message body (required for input and peer_message).
string | null
Handling mode for input, peer_message, peer_request, and peer_response. Local callers must provide "queue" or "steer".
peer_message is the default collaboration primitive. peer_lifecycle is a one-way topology notification. peer_request is only a structured ask with correlated replies.
string | null
Lifecycle event kind: "mob.peer_added", "mob.peer_retired", or "mob.peer_unwired" (required for peer_lifecycle).
string | null
Request intent (required for peer_request, e.g. "review", "delegate").
object | null
Request parameters (optional for peer_request).
string | null
ID of the request being responded to (required for peer_response).
string | null
Response status: "accepted", "completed", or "failed" (for peer_response).
object | null
Response result data (optional for peer_response).
string | null
Optional source label.
string | null
Optional input stream mode: "none" or "reserve_interaction" (for input and peer_request).
bool | null
Allow the session to send a message to itself (default: false).
Unlike POST /sessions/{id}/external-events (which uses RKAT_WEBHOOK_SECRET header auth), /comms/send has no authentication. It is intended for trusted internal callers that already know the session ID.

GET /comms/peers

List discoverable peers for a session. Requires the comms feature.
string
required
Session ID to query peers for.
Response
peer_id is the canonical routing value accepted by POST /comms/send; name is display-only and need not be unique. address is a typed {transport, endpoint} object, while source, sendable_kinds, capabilities, and meta describe discovery provenance and supported use.

Error responses

All errors are returned as JSON with an HTTP status code:

Notes

Keep-alive mode requires keep_alive: true and a comms_name. If keep_alive is requested but the binary was not compiled with comms support, the server returns a BAD_REQUEST error.
POST /sessions/{id}/external-events queues a runtime-backed external event. It is a queue-only admission path, not a second direct execution loop.
hooks_override allows per-request hook overrides including adding extra hook entries and disabling specific hooks by ID. See Hooks for the HookRunOverrides schema.