meerkat-sdk) is a thin wrapper over Meerkat’s settled runtime-backed contracts. It spawns rkat-rpc as a subprocess, then exposes the same session lifecycle used by the CLI, REST, JSON-RPC, and MCP surfaces as Python-native Session and DeferredSession handles.
- Python:
>=3.10 - Dependencies: zero runtime dependencies
Getting started
Install the RPC binary
The SDK spawns Alternatively,
rkat-rpc as a subprocess. Build it from source:MeerkatClient will attempt to download a matching release binary automatically if rkat-rpc is not found on PATH.Method overview
MeerkatClient methods
| Method / Property | Description |
|---|---|
async with MeerkatClient() as client | Preferred usage — starts rkat-rpc and cleans up on exit |
await client.connect(...) | Explicit connect: spawn rkat-rpc, handshake, fetch capabilities |
await client.close() | Terminate the subprocess |
await client.create_session(prompt, ...) | Create a session and run the first turn; returns Session |
client.create_session_streaming(prompt, ...) | Create a session and stream typed events; returns EventStream |
await client.list_sessions() | List active sessions; returns list[SessionInfo] |
await client.read_session(session_id) | Read raw session state |
await client.read_session_history(session_id, offset=0, limit=None) | Read committed session transcript history |
await client.create_mob(*, prefab=..., definition=...) | Create a mob; returns Mob |
await client.create_deferred_session(prompt, ...) | Create a session without running the first turn; returns DeferredSession |
await client.list_mobs() | List mobs; returns list[MobSummary] |
client.capabilities | list[Capability] — capabilities fetched during handshake |
client.has_capability(id) | True if a capability is available |
client.require_capability(id) | Raises CapabilityUnavailableError if not available |
await client.get_config() | Read runtime configuration |
await client.set_config(config) | Replace runtime configuration |
await client.patch_config(patch) | Merge-patch runtime configuration |
Session methods
create_session() returns a Session object. All subsequent operations on a session go through that runtime-backed handle rather than through wrapper-local execution state.
| Method / Property | Description |
|---|---|
session.id | Stable session UUID |
session.ref | Optional human-readable session reference |
session.text | Assistant text from the last turn |
session.usage | Usage from the last turn |
session.turns | Number of LLM turns in the last run |
session.tool_calls | Number of tool calls in the last run |
session.structured_output | Structured output from the last run, if requested |
session.last_result | Full RunResult from the last turn |
await session.turn(prompt, ...) | Run another turn; returns RunResult |
session.stream(prompt, ...) | Run another turn with streaming; returns EventStream |
await session.history(offset=0, limit=None) | Read committed transcript history for this session |
await session.archive() | Archive (remove) the session |
await session.interrupt() | Cancel the currently running turn |
await session.invoke_skill(skill_ref, prompt) | Invoke a skill in this session |
await session.send(**kwargs) | Push a comms event into this session |
await session.peers() | List peers visible to this session’s comms runtime |
await session.subscribe_events() | Open a standalone event subscription; returns EventSubscription |
Mob methods
create_mob() returns a Mob object for explicit mob lifecycle control.
| Method | Description |
|---|---|
mob.id | The mob’s identifier |
await mob.status() | Get mob status |
await mob.lifecycle(action) | Stop, resume, complete, or destroy the mob |
await mob.spawn(...) | Spawn a member into the mob |
await mob.retire(meerkat_id) | Retire a member |
await mob.respawn(meerkat_id) | Respawn a member |
await mob.wire(a, b) | Wire two members for comms |
await mob.unwire(a, b) | Remove comms wiring |
await mob.members() | List mob members |
await mob.member(meerkat_id).send(content, handling_mode=...) | Send work to a member |
await mob.flows() | List available flows |
await mob.run_flow(flow_id, params) | Start a flow run |
await mob.flow_status(run_id) | Get flow run status |
await mob.cancel_flow(run_id) | Cancel a flow run |
await mob.subscribe_member_events(meerkat_id) | Subscribe to member events; returns EventSubscription |
await mob.subscribe_events() | Subscribe to mob-wide events; returns EventSubscription |
MeerkatClient
Constructor
connect() is called (or the async context manager is entered).
connect()
rkat-rpc subprocess, performs the initialize handshake, checks contract version compatibility, and fetches capabilities. Returns self for chaining.
If realm_id is omitted, each SDK process gets a default realm. Reuse realm_id to share config and sessions across SDK/CLI/REST/MCP surfaces. realm_id and isolated are mutually exclusive.
close()
SIGTERM and waits up to 5 seconds; falls back to SIGKILL on timeout.
create_session()
Session whose convenience properties (text, usage, turns, tool_calls, structured_output) reflect the result of that first turn.
create_session_streaming()
EventStream async context manager — the request is sent when entering the async with block. After iteration, stream.session_id and stream.result are available.
Capabilities
Session queries
Config management
Session
Session is returned by create_session() and is the primary handle for multi-turn conversations.
Properties
turn()
last_result and returns the new RunResult.
stream()
EventStream. Updates last_result when the stream completes.
archive() and interrupt()
invoke_skill()
"skills" capability — raises CapabilityUnavailableError if it is not available. Accepts a SkillKey or a legacy string of the form "<source_uuid>/<skill_name>".
send() and peers()
Streaming
EventStream
EventStream is an async context manager returned by session.stream() and client.create_session_streaming(). Iterate it to receive typed Event subclass instances.
Convenience methods
Typed event classes
All events are frozen dataclasses importable frommeerkat. Unknown event types (from newer server versions) are surfaced as UnknownEvent for forward compatibility.
| Class | Key fields | Description |
|---|---|---|
RunStarted | session_id, prompt | Agent run has started |
TurnStarted | turn_number | A new LLM turn has begun |
TextDelta | delta | Incremental text chunk from the LLM |
TextComplete | content | Full assistant text for the current turn |
ToolCallRequested | id, name, args | LLM wants to invoke a tool |
ToolResultReceived | id, name, is_error | Tool result fed back to LLM |
TurnCompleted | stop_reason, usage | LLM turn finished |
ToolExecutionStarted | id, name | Tool began executing |
ToolExecutionCompleted | id, name, result, is_error, duration_ms | Tool finished |
ToolExecutionTimedOut | id, name, timeout_ms | Tool exceeded its timeout |
RunCompleted | session_id, result, usage | Agent run completed |
RunFailed | session_id, error | Agent run failed |
CompactionStarted | input_tokens, estimated_history_tokens, message_count | Context compaction began |
CompactionCompleted | summary_tokens, messages_before, messages_after | Compaction finished |
CompactionFailed | error | Compaction failed |
BudgetWarning | budget_type, used, limit, percent | A budget threshold crossed |
Retrying | attempt, max_attempts, error, delay_ms | LLM request being retried |
HookStarted | hook_id, point | Hook invocation started |
HookCompleted | hook_id, point, duration_ms | Hook invocation completed |
HookFailed | hook_id, point, error | Hook invocation failed |
HookDenied | hook_id, point, reason_code, message | Hook denied the operation |
HookRewriteApplied | hook_id, point, patch | Hook rewrote part of request/response |
SkillsResolved | skills, injection_bytes | Skills resolved for this turn |
SkillResolutionFailed | reference, error | Skill reference could not be resolved |
InteractionComplete | interaction_id, result | Comms interaction completed |
InteractionFailed | interaction_id, error | Comms interaction failed |
StreamTruncated | reason | Event stream was truncated |
ToolConfigChanged | payload | Live tool configuration changed for this session |
UnknownEvent | type, data | Unrecognised event type (forward compat) |
Parsing and typing notes
- Capability statuses may be encoded as externally-tagged enum objects by Rust (for example
{"DisabledByPolicy": {...}}). The SDK normalises these to the string key. - Event parsing intentionally defaults missing fields to empty/zero values so partially delivered streaming payloads can still be surfaced as typed events.
RunResult.skill_diagnosticsisSkillRuntimeDiagnostics | None— present when the skills subsystem emits runtime diagnostics.
Examples
Multi-turn conversation
Multi-turn conversation
Streaming with typed events
Streaming with typed events
Structured output
Structured output
Using with tools enabled
Using with tools enabled
Multimodal prompt (image input)
Multimodal prompt (image input)
Capability checking
Capability checking
Skill invocation
Skill invocation
See also
- Python SDK reference — types, streaming events, and error handling
- Rust SDK overview — Rust library API
- RPC reference — JSON-RPC protocol specification
