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:Additional client wrappers
The package exports more than the core session lifecycle. TheMeerkatClient 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 plusmonitorsStartand the authority-checkedmobkitJob*worker mutations - approvals and artifacts: request/list/get/decide plus list/get/download artifacts
- projected event recovery:
latestEventCursor,listEventsSince,eventSnapshotwhen host event projection is enabled - live-channel helpers:
liveOpen,liveStatus,liveClose,liveSendInput,liveSendInputImage,liveSendInputVideoFrame,liveCommitInput,liveWebrtcAnswer,liveInterrupt,liveTruncate,liveRefresh, andparseLiveObservation
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 bysession.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.
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.
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 nototal_tokens field.
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 byclient.listSessions().
Capability
A single runtime capability entry, as returned byclient.capabilities.
{ DisabledByPolicy: { ... } }). The SDK normalizes these to the key string automatically.
ContentBlock
Content blocks are used in multimodal prompts and tool results. BothcreateSession() 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 structuredSkillKey.
SkillRuntimeDiagnostics
Runtime diagnostics from the skill subsystem. Present onRunResult.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 alltext_delta events and returns the joined string alongside the result:
Typed events
All events are discriminated on thetype field (snake_case, matching the wire protocol). All other fields are camelCase.
AgentEvent union
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, andprovider_cache_breakpoints_discardedare inventory-known but have no typed parser case, so they arrive asUnknownEvent- current Rust
server_tool_contentandtranscript_rewrite_audit_receipt_committedare missing from the generated inventory, so receiving either throwsUNKNOWN_EVENT_TYPE - current
run_started,run_failed,retrying, andhook_faileduse newer field shapes than the handwritten parser and are preserved asMalformedEvent
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 asUnknownEvent. 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 extendMeerkatError. Catch it as a base class or use the specific subclasses for targeted handling.
Error classes
Common error codes
Skills
BothcreateSession() and session.turn() accept structured skill parameters.
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.0onwards, standard semver applies: major versions must match.
connect(). A MeerkatError with code VERSION_MISMATCH is thrown if versions are incompatible.
See also
- TypeScript SDK overview - getting started, client and session API
- Python SDK - Python SDK
- RPC reference - JSON-RPC protocol specification
