Skip to main content
Public SDK interfaces use camelCase by default. Protocol-bound multimodal content keys (media_type, blob_id, duration_ms) intentionally remain wire-shaped.

Imports

The stable domain types and helpers are re-exported from the package root:
Every public TypeScript RPC wrapper binds its request and response transport boundary to generated RPC-schema contracts. Generated job, approval, artifact, and durable-event parameter/result names appear in the public client declarations but are not re-exported from the package root in 0.8.24. Pass structural object literals to those methods. This is an export/code-generation gap, not a second wire contract.

Additional client wrappers

The package exports more than the core session lifecycle. The MeerkatClient also exposes:
  • auth-profile helpers: authProfileList, authProfileGet, authProfileCreate, authProfileDelete
  • auth-login helpers: authLoginStart, authLoginComplete, authLoginDeviceStart, authLoginDeviceComplete, authLoginProvisionApiKey, authStatusGet, authLogout
  • realm helpers: realmList, realmGet
  • typed ingress helper: sendPeerResponseTerminal
  • MCP live-op helpers: mcpAdd, mcpRemove, mcpReload
  • blob/skill helpers: getBlob, listSkills
  • runtime host helpers: getRuntimeHostInfo, getRuntimeHostCapabilities, getRuntimeHostHealth
  • transcript and recovery helpers: inputState, exportSessionAtif, revision read/list, fork-at/fork-replace, rewrite, system-prompt update, and restore
  • WorkGraph observability: item/ready/event listing, snapshot, goal status, and attention listing
  • detached jobs and monitors: the jobs* family plus monitorsStart and the authority-checked mobkitJob* worker mutations
  • approvals and artifacts: request/list/get/decide plus list/get/download artifacts
  • projected event recovery: latestEventCursor, listEventsSince, eventSnapshot when host event projection is enabled
  • live-channel helpers: liveOpen, liveStatus, liveClose, liveSendInput, liveSendInputImage, liveSendInputVideoFrame, liveCommitInput, liveWebrtcAnswer, liveInterrupt, liveTruncate, liveRefresh, and parseLiveObservation
Approval calls maintain audit records only; they do not automatically gate, authorize, or execute an action. Records persist when the RPC persistence bundle exposes a store path. See JSON-RPC approvals. Auth profiles and persisted credentials are realm-scoped. Auth login or API key provisioning yields an auth binding; pass it as SessionOptions.authBinding or in a mob member spec instead of embedding provider secrets. A remote member host resolves that binding only inside its authorized realm.

Core types

RunResult

The result returned by session.turn(), session.invokeSkill(), and deferred.startTurn(). Session creation returns runtime-backed Session or DeferredSession wrappers, and the latest RunResult remains available through session.lastResult or stream.result after an EventStream is fully consumed.

Session

client.createSession() returns a runtime-backed Session wrapper.
The Session methods are thin conveniences over canonical runtime calls:
  • await session.turn(...)
  • session.stream(...)
  • await session.history(...)
  • await session.archive()
  • await session.interrupt()
  • await session.invokeSkill(...)
  • await session.subscribeEvents()

DeferredSession

client.createDeferredSession() reserves session identity now and runs the first turn later through await deferred.startTurn(...), or streams it through deferred.stream(...) -> EventStream. Although deferred creation reuses SessionOptions, the server rejects transientTurnContext because no immediate turn exists. Current DeferredTurnOptions omits injectedContext, transientTurnContext, and selfHostedServerId. Set injected context during deferred creation; transient first-turn context and a self-hosted server route are not expressible through the current deferred TypeScript wrapper. Both deferred turn methods accept skillRefs, turnToolOverlay, additionalInstructions, keepAlive, model, provider, maxTokens, systemPrompt, outputSchema, structuredOutputRetries, and providerParams.

LiveChannel

LiveChannel is the session-bound helper for the live/* RPC surface. RealtimeChannel was removed with the live-adapter surface; use LiveChannel.session(client, sessionId, options?) instead.
The helper stores the channel_id returned by live/open. It does not own the transport. Branch on opened.transport.transport: websocket carries url and token; webrtc carries token, answer_method, and optional http_url. Use client.liveWebrtcAnswer(...) to exchange a completed browser-created SDP offer. Do not assume every bootstrap has a URL. The Node SDK does not provide RTCPeerConnection; inject an implementation or forward browser-created SDP to the Node process. Add an audio track or the meerkat.live data channel, set the local description, wait for ICE gathering to complete, and send peer.localDescription.sdp. The 0.8.24 answerLiveWebrtcOffer(...) helper does not perform that wait and sends the original offer SDP, so use direct client.liveWebrtcAnswer(...) for the canonical browser exchange. WebRTC also requires an rkat-rpc binary compiled with the non-default live-webrtc Cargo feature. The 0.8.24 release binary does not include that feature, so liveWebrtc: true requires a custom binary. The direct helper has the same required identity: client.liveSendInputImage(channelId, idempotencyKey, mime, dataBase64). LiveChannelOptions.seedMaxChars forwards as LiveOpenParams.seed_max_chars. It must be positive, bounds serialized seed messages, and requests a core-owned whole-turn suffix; omission preserves the complete canonical seed. Every ordered System message must fit. Runtime context and complete image identity, tombstone, and accounting sidecars remain outside the window. Any truncation reports degraded continuity, and the server rejects zero.

Usage

Token usage. All fields are camelCase - there is no total_tokens field.
One type serves two different accounts. When present on turn_completed this is per-call usage: inputTokens is the raw provider counter (for Anthropic, uncached input only) and accounting names the resolved provider/model plus the normalized presentedTokens for that call. On RunResult.usage and run_completed it is the session-cumulative total: inputTokens is already the sum of every recorded call’s presentedTokens, it is persisted with the session so it keeps growing across turns, and accounting is absent because a session may span models. Do not sum the cumulative value with anything - take the latest one - and sum accounting.presentedTokens rather than per-call inputTokens. The per-call rows cover only the calls that closed a run, so they do not reconcile with the cumulative total. See Usage accounting for the worked example.

SessionInfo

Summary returned by client.listSessions().

Capability

A single runtime capability entry, as returned by client.capabilities.
Status values may be emitted as externally-tagged Rust enum objects (e.g. { DisabledByPolicy: { ... } }). The SDK normalizes these to the key string automatically.

ContentBlock

Content blocks are used in multimodal prompts and tool results. Both createSession() and session.turn() accept string | ContentBlock[] as the prompt parameter.

SchemaWarning

Emitted when a structured output response did not fully conform to the requested schema.

Skill types

SkillKey

Structured skill identifier.

SkillRef

A skill reference is a structured SkillKey.

SkillRuntimeDiagnostics

Runtime diagnostics from the skill subsystem. Present on RunResult.skillDiagnostics when the server emits skill health data.

EventStream

EventStream is an AsyncIterable<StreamEvent> returned by createSessionStreaming() and session.stream(). It yields events as the agent runs, then makes the final RunResult available on stream.result. StreamEvent includes AgentEvent and scoped wrappers. Use the exported type guards for direct payloads because UnknownEvent keeps the event union open-ended; the guards do not unwrap scoped events.

Iterating

collect()

Discards all events and returns the final result:

collectText()

Accumulates all text_delta events and returns the joined string alongside the result:

Typed events

All events are discriminated on the type field (snake_case, matching the wire protocol). All other fields are camelCase.

AgentEvent union

Event parsing fails closed: a type outside the generated KNOWN_AGENT_EVENT_TYPES inventory throws a MeerkatError with code UNKNOWN_EVENT_TYPE. A known type without a parser case in this SDK version is surfaced as UnknownEvent for forward-compatibility, and a known type with a malformed payload is preserved as a MalformedEvent (type: "malformed_event"). The 0.8.24 handwritten parser has known integration gaps:
  • 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 are inventory-known but have no typed parser case, so they arrive as UnknownEvent
  • current Rust server_tool_content and transcript_rewrite_audit_receipt_committed are missing from the generated inventory, so receiving either throws UNKNOWN_EVENT_TYPE
  • current run_started, run_failed, retrying, and hook_failed use newer field shapes than the handwritten parser and are preserved as MalformedEvent
These are SDK/code-generation gaps. The legacy parser shapes below describe the exported 0.8.24 TypeScript interfaces, not an alternate server contract. 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.

Session lifecycle events

Turn and LLM events

Tool execution events

Compaction events

Budget events

Retry events

Hook events

Skill events

SkillResolutionFailureReason is a typed union discriminated on reasonType (not_found, capability_unavailable, load, parse, source_uuid_collision, source_uuid_mutation_without_lineage, missing_skill_remaps, remap_without_lineage, unknown_skill_alias, remap_cycle, unknown).

Comms events

Tool config events

Background job events

terminalStatus is the typed semantic status; detail is the human-readable description.

Stream management

Transcript rewrite events

New inventory-known events

The usage-accounting, peer-ingestion, provider-cache-discard, reasoning, assistant-image, and interaction-callback event rows listed above currently arrive as UnknownEvent. Inspect event.type and raw fields only as a temporary compatibility measure; there is no exported typed PeerContentIngestedEvent in 0.8.24.

Type guard utilities

The SDK exports type guards for the most commonly used events:

Error handling

All errors extend MeerkatError. Catch it as a base class or use the specific subclasses for targeted handling.

Error classes

Common error codes


Skills

Both createSession() and session.turn() accept structured skill parameters.
Discovery returns generated key.source_uuid / key.skill_name fields, which must be mapped to SkillRef’s camelCase keys. The turn examples require an installed active skill and reject ambiguous names; select the intended source UUID explicitly when multiple sources provide that name.

Version compatibility

  • While the major version is 0, minor versions must match exactly between SDK and server.
  • From 1.0.0 onwards, standard semver applies: major versions must match.
Version checking happens automatically during connect(). A MeerkatError with code VERSION_MISMATCH is thrown if versions are incompatible.

See also