Skip to main content

Version

Primary handles

  • MeerkatClient owns the runtime process and transport.
  • Session is a live multi-turn handle.
  • DeferredSession is a created session that has not run its first turn yet.
  • LiveChannel is the session-bound wrapper for the live/* RPC surface.
  • Mob is a first-class mob control handle.

Session result and metadata types

RunResult

Returned by session.turn(), deferred.start_turn(), and available as events.result after streaming. Fields:
  • session_id: str
  • text: str
  • turns: int
  • tool_calls: int
  • usage: Usage
  • terminal_cause_kind: str | None
  • session_ref: str | None
  • structured_output: Any | None
  • extraction_error: ExtractionError | None
  • schema_warnings: list[SchemaWarning] | None
  • skill_diagnostics: SkillRuntimeDiagnostics | None

SessionSummary

Returned by client.list_sessions(...).
  • session_id: str
  • session_ref: str | None
  • created_at: int
  • updated_at: int
  • message_count: int
  • total_tokens: int
  • labels: dict[str, str]
  • is_active: bool

SessionDetails

Returned by client.read_session(session_id).
  • session_id: str
  • session_ref: str | None
  • created_at: int
  • updated_at: int
  • message_count: int
  • labels: dict[str, str]
  • is_active: bool
  • model: str
  • provider: str
  • last_assistant_text: str | None
  • resolved_capabilities: ResolvedModelCapabilities | None

SessionInfo

Base shared metadata type for session identity/timestamps/state.

Usage

  • input_tokens: int
  • output_tokens: int
  • cache_creation_tokens: int | None
  • cache_read_tokens: int | None
  • accounting: ProviderTokenAccounting | None

ProviderTokenAccounting

  • provider: str
  • model: str
  • presented_tokens: int
  • convention: str
  • aggregation: str
One Usage type serves two different accounts. When present on the TurnCompleted event it is per-call usage: input_tokens is the raw provider counter (for Anthropic, uncached input only) and accounting names the resolved provider/model plus the normalized presented_tokens for that call. On RunResult.usage and the RunCompleted event it is the session-cumulative total: input_tokens is already the sum of every recorded call’s presented_tokens, it is persisted with the session so it keeps growing across turns, and accounting is None because a session may span models. Do not sum the cumulative value with anything - take the latest one - and sum accounting.presented_tokens rather than per-call input_tokens. Every committed agent-loop call publishes a turn_completed row; extraction requests publish theirs on the extraction outcome event, and compaction summaries and turns that fail after the provider answered publish none, so the turn_completed rows need not reconcile with the cumulative total. See Usage accounting for the worked example. TurnCompleted.usage is Usage | None. None is honest unmeasured accounting, not a zero-token call. Skip the row; the paired turn_usage_accounting_unmeasured wire event carries the reason.

Config API contract

get_config returns ConfigEnvelope; set_config and patch_config return ConfigWriteResult:
ConfigEnvelope fields:
  • config: dict[str, Any]
  • generation: int
  • realm_id: str | None
  • instance_id: str | None
  • backend: str | None
  • resolved_paths: dict[str, str] | None
ConfigWriteResult carries the same fields plus live_propagation: WireLiveConfigPropagationReport | None, the typed per-channel hot-swap / refresh / close outcome (swapped, skipped, swap_failed, refreshed, closed, refresh_failed, close_failed).

Models and schedules

Models catalog

  • contract_version: {"major": int, "minor": int, "patch": int}
  • providers: list[ProviderCatalog]

Schedule wrappers

Public methods:
  • create_schedule(request)
  • get_schedule(schedule_id)
  • list_schedules(labels=None, limit=None, offset=None)
  • update_schedule(request)
  • pause_schedule(schedule_id)
  • resume_schedule(schedule_id)
  • delete_schedule(schedule_id)
  • list_schedule_occurrences(schedule_id, include_terminal=None)
  • list_schedule_tools()
  • call_schedule_tool({"name": "...", "arguments": ...})
Return payloads are JSON-shaped schedule contracts with typed top-level wrappers:
  • ScheduleListResult
  • ScheduleOccurrencesResult
  • ScheduleToolsResult
ScheduleRecord is the canonical flattened RPC object: configuration fields such as planning_horizon_days, created_at_utc, and labels are top-level; there is no nested config or public machine_state. The wrappers reject a missing/malformed schedules, occurrences, or tools array and reject schedule entries missing required identity, policy, planning, or timestamp facts.

WorkGraph wrappers

WorkGraph is a host-observation surface in the SDK. Use get_workgraph_item, list_workgraph_items, list_ready_workgraph_items, get_workgraph_snapshot, list_workgraph_events, get_workgraph_goal_status, and list_workgraph_attention. Agents own graph mutation through their WorkGraph tools.

Session runtime input helpers

Immediate creation and turn methods accept host-owned context separately from the user prompt:
  • injected_context: list[ContentInput] | None is ordered durable user-channel context immediately before the prompt
  • transient_turn_context: str | None is request-only host context
  • turn methods also accept self_hosted_server_id for an exact configured local model route
Deferred creation can store injected_context for its eventual first turn but does not accept transient_turn_context; pass transient facts to DeferredSession.start_turn(...).

inject_context

send_external_event

Returns ExternalEventOutcome (runtime admission outcome payload).

Transcript and input reconciliation

Additional client wrappers

The Python SDK also exposes:
  • realm helpers: list_realms(), get_realm(...)
  • auth helpers: list_auth_profiles(...), get_auth_profile(...), create_auth_profile(...), delete_auth_profile(...), auth_login_*, auth_provision_api_key(...), auth_status(...), auth_logout(...)
  • blob/skill/MCP helpers: get_blob(...), list_skills(), mcp_add(...), mcp_remove(...), mcp_reload(...)
  • comms helpers: session.send(...), session.peers()
  • typed ingress helper: send_peer_response_terminal(...)
  • runtime host inspection: get_runtime_host_info(), get_runtime_host_capabilities(), get_runtime_host_health()
Auth profiles and persisted credentials are realm-scoped. Login/provisioning returns an auth binding; pass that binding through session auth_binding or a mob member spec instead of embedding provider secrets. A remote member host resolves the declared binding in its authorized realm.

Detached jobs and monitors

The public job wrappers are jobs_get, jobs_list, jobs_cancel, jobs_progress, jobs_result, jobs_artifacts, jobs_retry, jobs_health, jobs_subscribe, and jobs_unsubscribe. monitors_start creates a detached monitor job. MobKit worker implementations additionally use the six mobkit_job_* authority-checked mutation methods. Every public Python RPC wrapper binds its request and result transport boundary to generated RPC-schema contracts. The job request and result dataclasses in 0.8.24 are available from meerkat.generated.types, but are not re-exported from meerkat:

Approvals, artifacts, and projected events

  • approvals: request_approval, list_approvals, get_approval, decide_approval
  • artifacts: list_artifacts, get_artifact, download_artifact
  • cursor-based event recovery: latest_event_cursor, list_events_since, event_snapshot when host event projection is enabled
Approval calls maintain audit records only; they do not automatically gate, authorize, or execute an action. Records persist when the RPC bundle exposes a store path and otherwise remain process-local. See JSON-RPC approvals. When projection is enabled, use cursor replay or a snapshot after reconnect or a typed live-stream lag marker. A live subscriber is an observation surface, not the persistence boundary. Explicitly ephemeral memory realms do not expose the replay APIs.

Mob profile and events surfaces

Multi-host operator surface

The client exposes host inventory and route installs, host bind/revoke, grant/revoke/list scopes, remote member history, hard cancel, and remote live channel control. These JSON-RPC methods are trusted operator controls. Public REST/MCP and agent-callable tools intentionally expose narrower read or member surfaces, and agent spawn cannot authorize the Rust-only resume_from_role durable role migration.

Mob event history

Returns MobEventsResult.

Realm profile CRUD

Types:
  • MobProfile, MobProfileTools
  • StoredMobProfile
  • DeletedMobProfile

Streaming

EventStream is returned by session.stream(...) and client.create_session_streaming(...).
  • synchronous constructor style (session.stream(...) returns stream object)
  • request is sent on async with entry
  • events.result is available after iteration
  • BackgroundJobCompleted.terminal_status is the typed terminal status for background jobs (job_id, display_name, terminal_status, detail)

Live channels

RealtimeChannel and the old realtime convenience helpers are no longer public SDK handles. The current helper is LiveChannel.session(client, session_id, ...), which binds a session id and stores the channel_id returned by live/open.
Direct MeerkatClient helper names mirror the RPC methods:
  • live_open(session_id, turning_mode=None, transport=None, seed_max_chars=None)
  • live_webrtc_answer(channel_id, token, offer_sdp)
  • live_status(channel_id)
  • live_close(channel_id)
  • live_send_input_text(channel_id, text)
  • live_send_input_audio(channel_id, data_base64, sample_rate_hz, channels)
  • live_send_input_image(channel_id, idempotency_key, mime, data_base64)
  • live_send_input_video_frame(channel_id, codec, data_base64, timestamp_ms)
  • live_commit_input(channel_id, response_modality=None)
  • live_interrupt(channel_id)
  • live_truncate(channel_id, item_id, content_index, audio_played_ms)
  • live_refresh(channel_id)
live_send_input_image requires a caller-stable, session-scoped key. Its return value proves queue acceptance only; durable success is the later user_content_committed observation carrying that same key. Pass a positive seed_max_chars to bound serialized seed messages and request a core-owned whole-turn suffix at open time. Omission preserves the complete seed; zero is rejected. Every ordered System message must fit; an existing compaction summary may be retained, and any truncation reports degraded continuity. Canonical image identity, tombstone, and accounting sidecars remain complete. live_open returns a discriminated transport object. The websocket variant has url and token. The webrtc variant has token, answer_method, and an optional http_url; create an SDP offer and pass it to live_webrtc_answer. Do not assume every transport has a URL. WebRTC requires connect(live_webrtc=True) and an rkat-rpc binary compiled with its non-default live-webrtc Cargo feature. The 0.8.24 auto-downloaded release binary does not include that feature. Add an audio track or the meerkat.live data channel, set the browser peer’s local description, wait for ICE gathering to complete, then send peer.localDescription.sdp. The protocol has no candidate-trickle RPC. Install the returned answer_sdp as the browser peer’s remote description before sending live input.

Event compatibility note

The generated event inventory in 0.8.24 knows reasoning_delta, reasoning_complete, assistant_image_appended, turn_usage_accounting_unmeasured, turn_usage_accounting_identity_disputed, interaction_callback_pending, peer_content_ingested, and provider_cache_breakpoints_discarded. The handwritten parser has no typed case for these eight rows, so they arrive as UnknownEvent. Current Rust server_tool_content and transcript_rewrite_audit_receipt_committed are absent from that generated inventory. Receiving either through this parser raises UNKNOWN_EVENT_TYPE. Current run_started, run_failed, retrying, and hook_failed use newer field shapes than the handwritten parser and can arrive as malformed events. Treat all of these as SDK/code-generation gaps, not stable alternate wire contracts. In the current 0.8.40 SDK, model_fallback_skipped, model_fallback_staged, model_fallback_committed, and model_fallback_target_failed are also absent from the generated inventory. If a runtime emits one during model fallback, receiving it raises UNKNOWN_EVENT_TYPE rather than yielding UnknownEvent. Streams that do not receive these events are not affected by this particular gap.

Capability and error model

Capabilities:
Errors:
All SDK errors derive from MeerkatError.