@rkat/mobkit-sdk) provides type-safe access to the MobKit JSON-RPC gateway from Node.js.
Installation
The npm package is client-only and does not contain
rpc_gateway. Download
mobkit-rpc-gateway-<version>-<target>.tar.gz for Unix or macOS, or
mobkit-rpc-gateway-<version>-<target>.zip for Windows, and extract its
rpc_gateway binary (rpc_gateway.exe on Windows). Alternatively, follow the
source-build instructions. Pass that binary’s path to
.gateway(...).Quick start
Durable detached tools
Long-running host work must declare detached execution rather than keeping a tool callback open:rosterProvider, .agentMemory() enables optional identity-scoped hot memory injection from <persistentState>/agent-memory with contextual recall by default. Options include realm, selection, maxEntries, recallTimeoutMs, recallFailurePolicy, and instructionHeader; automatic injection defaults to a 500 ms timeout and skips the memory block if recall fails. Write records with handle.rememberAgentMemory(identity, { title, body, tags, realm }), read them with handle.recallAgentMemory(identity, { realm, selection, queryText, queryTerms, maxEntries }), and delete them with handle.forgetAgentMemory(identity, memoryId, { realm }); new records are available on the next identity-first send and during later materialize/resume/respawn/reset flows. Forgetting a record removes it from future recall/injection, but does not erase text already delivered into an active model context.
Type definitions
The SDK exports camelCase result types. Its wire parsers translate snake_case gateway JSON into these shapes:ModuleConfig is not a public TypeScript SDK export. Pass module declaration
objects to .modules(...), whose public parameter type is unknown[].
An identity-first RosterProvider.roster(context) receives a typed
RosterContext, a one-to-one mirror of the Rust struct the gateway sends
under params.context:
Module support
The SDK supports both ESM and CommonJS:Cross-module identity check
Because dual CJS+ESM packaging, vitest module isolation, and hoisted-vs-nested monorepos can ship two distinctRpcError
constructors in the same process, prefer the structural type guards
over instanceof:
Structural mob events + flow runs
Both APIs return the full meerkat ledger projection:Mobpack authoring
MobHandle wraps the full Flow Editor authoring surface (mobkit/mobpacks/*) with typed methods: mobpackTemplates, mobpackCatalogs, mobpackValidate, mobpackSource, mobpackExport, mobpackImport, mobpackList, mobpackGet, mobpackCreate, mobpackSave, mobpackDelete, mobpackUndo, mobpackRedo, mobpackApplyOperation, mobpackDeployCommand, and mobpackDeploy.
mobpackDeploy(document, true) sends execute: true, which writes the archive and runs rkat mob run on the host — gated by the surface’s advertised authoring_capabilities and, on ABAC-enforced runtimes, the caller’s mobpack.deploy grant. See the Flow Editor guide.
Rust parity notes
The TypeScript SDK targets the JSON-RPC gateway. Rust also exposes lower-level native builder options for in-process embedding; those remain Rust-native and are not mirrored one-for-one in the gateway SDKs. External identity providers are all-or-nothing: configurecontinuityStore(), leaseProvider(), and scratchDir() together. The SDK sends the corresponding init flags to Rust, and provider callbacks use Rust’s wire shape (result tags and ttl). LeaseProvider.renewLeases(...) is atomic from the caller’s perspective: a rejected promise means no input grant was changed, while every returned renewed or lost result is already committed for that identity. Providers must not commit a replacement grant and then reject.
Continuity stores should treat checkpoint_version as monotonic per identity and continuity generation. A live session rebind changes session_id without resetting the version; only destructive reset advances generation and starts the version stream over.
Gateway memory config accepts { backend: "local_json" } with an optional healthCheckEndpoint (memory.localJson(...)); the legacy Elephant { backend, endpoint } shape still works but is deprecated. Store, collection, and space selectors are retained on the helper object for app code but are not sent to the Rust gateway. Gateway auth config supports JWT validation; Google/OIDC helpers are model objects, not accepted by mobkit/init today.
The builder exposes no roleMigrations(...) setter and sends no role_migrations init param, so a TypeScript host cannot authorize a role-migrating resume: a durable member whose role changed keeps refusing to resume with MobError::MemberRoleMigrationRequired. Declaring the migration currently requires the Python builder’s .role_migrations([...]) or a hand-built mobkit/init payload; see the configuration reference.
The builder forwards consoleConfig(path) as runtime_options.console_config_path, which lets the bundled console consume the same console_config contract projected by /console/experience. The console default is fail-closed: with neither auth(...) nor consoleAuthRequired(false) the gateway trusts no signing key and refuses every console request with 401 (it logs a startup warning naming this). consoleAuthRequired(false) is the explicit opt-out; use it only for a local or host-protected console. The Python twin is .console_auth_required(False).
DurableAgentSpec carries the two per-identity knobs the Rust type deserializes: runtimeModeOverride ("autonomous_host" or "turn_driven"; null defers to the profile’s runtime_mode, whose meerkat default is autonomous_host) and initialMessage (the first turn a fresh autonomous_host member runs on: a string or DispatchContentBlock[], Rust ContentInput; null leaves meerkat’s fallback spawn prompt). Both are omitted from the roster payload when unset. durableAgentSpecToDict and parseDurableAgentSpec translate them (runtime_mode_override, initial_message). The Python twins are runtime_mode_override and initial_message on DurableAgentSpec.
The gateway binds 127.0.0.1 on an ephemeral port by default. httpListen("0.0.0.0:8080"), allowRemote() and httpPublicBaseUrl(url) are the exposure knobs (runtime_options.http_listen, allow_remote, http_public_base_url): a non-loopback bind is refused at init unless auth(...) enforces console auth or allowRemote() acknowledges the exposure, and the advertised base is read back as runtime.rustHttpPublicBaseUrl while runtime.rustHttpBaseUrl stays the same-host form the SDK itself dials. See Deployment.
meerkatConfig(path) forwards a Meerkat host config.toml as runtime_options.meerkat_config_path, the only door for the [self_hosted] and [realm] tables Meerkat keeps out of mob.toml (a host-config [models] table reaches the factory too, but a profile’s model must be catalogued, provider-annotated or defined under mob.toml’s own [models.<id>] to pass the init model check); a missing, malformed or non-validating file refuses init rather than building agents from the default config, and a top-level [self_hosted] or [realm] table inside mob.toml is refused at init with a message naming this option. The Python twin is .meerkat_config(path). See Self-hosted models and the Meerkat host config.
Storage durability declarations
The gateway is fail-closed about durable storage: a store that cannot open is a startup error, never a silent in-memory fallback. TheruntimeStore
and eventLog config modules produce the explicit declarations:
StatusResult.storage /
CapabilitiesResult.storage parse the gateway’s storage object into
StorageSummary (blob durability, the H2 incremental probe, and the
per-slot StorageSlotSummary census with domain, durabilityClass,
resolution, backend, degraded, detail); apply parseStorageSummary
to the raw storage record of mobkit/storage/doctor. A fail-closed
startup refusal — file-name twins, a store that failed to open — surfaces
as the typed StorageResolutionError (code -32014,
STORAGE_RESOLUTION_CODE), not a TransportError; its message names the
remediation (mobkit/storage/doctor, or the explicit ephemeral
declaration). Blob-store durability has no wire declaration today — it is
declared by Rust embedders via ephemeral_blobs(true) /
binary_blob_store(...) and reported read-only in the census.
Gateway logging (stderr)
The persistent gateway reports tracing lines, panic hooks, and storage migration progress on its stderr. By default the SDK inherits the host process’s stderr, so those lines are visible where your application logs. Two environment variables adjust this (same shape as the Python SDK):
Discarding is the legacy pre-0.8.9 default and is not recommended: it hides
panic output and makes a slow-but-working storage migration indistinguishable
from a hang.
Error hook (onError)
category is one of the ErrorCategory constants (spawn_failure,
reconcile_incomplete, checkpoint_failure,
compaction_persistence_rejected, actor_loop_stalled,
actor_loop_recovered, host_loop_crash, rediscover_failure,
event_log_flush_failure, identity_materialization_failure,
mob_stop_proceeded_without_interrupt), kept in lockstep with the Rust enum
by tests/sdk_error_category_parity.rs; context carries the variant’s
fields (member_id, error, and so on). The hook is fire-and-forget: a
rejected promise is swallowed, and with no callback registered the
notification is dropped. The gateway’s own stderr line for the same event
(ERROR, or INFO for actor_loop_recovered) is written either way, so the
hook adds alerting, not logging. Use
isResolutionErrorEvent(event) to tell a failure ending
(actor_loop_recovered) from one starting before paging on it. The Python
twin is .on_error(callback).
HTTP transport timeout
createJsonRpcHttpTransport defaults to a 60-second timeout (via
AbortController) so a server that accepts but never replies cannot
hang the caller’s await forever. Override per-call:
Contract parity
The TypeScript SDK includes parity tests that validate type definitions against the Rust core. This ensures the SDK stays in sync with the runtime API across releases.See also
- JSON-RPC API — full method reference
- Rust SDK — primary Rust interface
- Python SDK — Python equivalent
