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

Build the server

cargo run --package meerkat-rest
2

Set API keys

Export the key for your chosen provider:
export ANTHROPIC_API_KEY="sk-..."
# or OPENAI_API_KEY, GOOGLE_API_KEY
3

Send a request

curl -X POST http://127.0.0.1:8080/sessions \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Hello, Meerkat!"}'

Endpoint overview

MethodPathDescription
POST/sessionsCreate and run a new session
POST/sessions/{id}/messagesContinue an existing session
GET/sessions/{id}Fetch session metadata and usage
GET/sessions/{id}/eventsSSE stream for real-time updates
GET/healthLiveness check
GET/capabilitiesRuntime capabilities
GET/configRead config
PUT/configReplace config
PATCH/configMerge-patch config (RFC 7396)

Configuration

The REST server reads config from its instance data directory:
  • macOS: ~/Library/Application Support/meerkat/rest/config.toml
  • Linux: ~/.local/share/meerkat/rest/config.toml
  • Windows: %APPDATA%\meerkat\rest\config.toml
Key sections:
[rest]
host = "127.0.0.1"
port = 8080

[agent]
model = "claude-opus-4-6"
max_tokens_per_turn = 8192

[tools]
builtins_enabled = false
shell_enabled = false
API keys are provided via environment variables:
  • ANTHROPIC_API_KEY
  • OPENAI_API_KEY
  • GOOGLE_API_KEY

Endpoints

POST /sessions

Create and run a new session.
{
  "prompt": "Your prompt here"
}

Request fields

prompt
string
required
The user prompt to send to the agent.
system_prompt
string | null
default:"null"
Override the system prompt for this session.
model
string | null
default:"config default"
Model name (e.g. "claude-opus-4-6", "gpt-5.2").
provider
string | null
default:"inferred from model"
Provider: "anthropic", "openai", "gemini", "other".
max_tokens
u32 | null
default:"config default"
Max tokens per turn.
output_schema
OutputSchema | null
default:"null"
JSON schema for structured output extraction (wrapper or raw schema).
structured_output_retries
u32
default:"2"
Max retries for structured output validation.
verbose
bool
default:"false"
Enable verbose event logging (server-side).
host_mode
bool
default:"false"
Run in host mode for inter-agent comms (requires comms_name).
comms_name
string | null
default:"null"
Agent name for inter-agent communication.
hooks_override
HookRunOverrides | null
default:"null"
Run-scoped hook overrides (see Hooks).

Response fields

session_id
string
UUID of the created session.
text
string
The agent’s response text.
turns
u32
Number of LLM calls made.
tool_calls
u32
Number of tool calls executed.
usage
WireUsage
Token usage breakdown.
usage.input_tokens
u64
Input tokens consumed.
usage.output_tokens
u64
Output tokens generated.
usage.total_tokens
u64
Total tokens (input + output).
usage.cache_creation_tokens
u64 | null
Cache creation tokens (provider-specific).
usage.cache_read_tokens
u64 | null
Cache read tokens (provider-specific).
structured_output
object | null
Parsed structured output (when output_schema was provided).
schema_warnings
array | null
Schema compatibility warnings per provider.
{
  "prompt": "Extract the capital of France",
  "model": "claude-opus-4-6",
  "output_schema": {
    "schema": {
      "type": "object",
      "properties": {
        "country": {"type": "string"},
        "capital": {"type": "string"}
      },
      "required": ["country", "capital"]
    },
    "name": "capital_extraction",
    "strict": false,
    "compat": "lossy",
    "format": "meerkat_v1"
  },
  "structured_output_retries": 2
}
When output_schema is provided, the text field contains the schema-only JSON string produced by the extraction turn (no extra prose). The structured_output field contains the parsed JSON value for convenience.output_schema may be provided as a wrapper object (shown above) or as a raw JSON Schema object. The wrapper enables explicit compat/format settings.

POST /sessions/{id}/messages

Continue an existing session.
{
  "session_id": "01936f8a-7b2c-7000-8000-000000000001",
  "prompt": "Follow-up message"
}

Request fields

session_id
string
required
Session ID (must match the path {id}).
prompt
string
required
Follow-up prompt.
system_prompt
string | null
default:"null"
Override the system prompt.
model
string | null
default:"from session"
Model override for this turn.
provider
string | null
default:"from session"
Provider override for this turn.
max_tokens
u32 | null
default:"from session"
Max tokens override for this turn.
output_schema
OutputSchema | null
default:"null"
Structured output schema for this turn.
structured_output_retries
u32
default:"2"
Max retries for structured output validation.
verbose
bool
default:"false"
Enable verbose event logging.
host_mode
bool
default:"false"
Enable host mode for this turn.
comms_name
string | null
default:"from session"
Agent name for comms.
hooks_override
HookRunOverrides | null
default:"null"
Run-scoped hook overrides.

Response fields

Same shape as POST /sessions.

GET /sessions/{id}

Fetch session metadata and usage.
Response
{
  "session_id": "01936f8a-7b2c-7000-8000-000000000001",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:31:00Z",
  "message_count": 4,
  "total_tokens": 500
}

GET /sessions/{id}/events

Server-Sent Events (SSE) stream for real-time updates. Event types:
EventDescription
session_loadedEmitted on connect with session metadata
run_startedTurn execution began
turn_startedNew LLM call within the turn
text_deltaStreaming text chunk from LLM
tool_call_requestedLLM wants to call a tool
tool_execution_startedTool dispatch began
tool_execution_completedTool returned a result
turn_completedLLM call finished
run_completedTurn execution finished successfully
run_failedTurn execution failed
budget_warningApproaching resource limits
retryingRetrying after transient error
doneEmitted when the broadcast channel closes

GET /health

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

GET /capabilities

Returns runtime capabilities with status resolved against config.
Response
{
  "contract_version": {"major": 0, "minor": 1, "patch": 0},
  "capabilities": [
    {
      "id": "sessions",
      "description": "Session lifecycle management",
      "status": "Available"
    },
    {
      "id": "shell",
      "description": "Shell command execution",
      "status": {"DisabledByPolicy": {"description": "Disabled by config"}}
    }
  ]
}

GET /config

Returns the current Config object.

PUT /config

Sets the entire config. Body: full Config JSON.

PATCH /config

RFC 7396 merge patch on the config. Body: partial JSON.

Error responses

All errors are returned as JSON with an HTTP status code:
{
  "error": "Human-readable error message",
  "code": "ERROR_CODE"
}
HTTP StatusCodeWhen
400BAD_REQUESTInvalid parameters, session ID mismatch, host_mode without comms
404NOT_FOUNDSession does not exist
500CONFIGURATION_ERRORConfig store read/write failure
500AGENT_ERRORLLM provider error, tool dispatch failure, agent loop error
500INTERNAL_ERRORStore initialization failure, unexpected server error
{
  "error": "Session not found: 01936f8a-7b2c-7000-8000-000000000099",
  "code": "NOT_FOUND"
}

Notes

Host mode requires host_mode: true and a comms_name. If host_mode is requested but the binary was not compiled with comms support, the server returns a BAD_REQUEST error.
hooks_override allows per-request hook overrides including adding extra hook entries and disabling specific hooks by ID. See Hooks for the HookRunOverrides schema.