POST /console/rpc for the console-specific subset and runtime passthrough.
Protocol
- SDK transport: JSON lines over stdio (one JSON object per line)
- Console transport: HTTP
POST /console/rpc - Version: JSON-RPC 2.0
- Contract version:
0.5.0
Initialization handshake
The persistent SDK gateway (rpc_gateway --persistent) does not emit an
unsolicited capabilities line. It waits for the client, whose first JSON line
must be a mobkit/init request:
contract_version in result,
together with http_base_url and the gateway’s runtime metadata. Clients that
enforce contract compatibility compare result.contract_version before
sending later requests. After init, mobkit/capabilities returns the methods
available on that runtime.
role_migrations
A durable member whose role changed refuses to resume
(MobError::MemberRoleMigrationRequired) until the host declares the
migration, so an unintended role edit cannot silently restamp a member’s
durable role, comms name and binding.
The key sits at the TOP LEVEL of params, a sibling of runtime_options and
persistent_state, not inside runtime_options. rpc_gateway reads it at init
scope, and its runtime_options handling is a closed allowlist that would
reject it as an unsupported field.
{identity, from_role}: the exact identity being migrated (no
wildcards, no prefix matching) and the role it is migrating FROM. The gateway
installs the list on its session bridge for the life of this boot and never
persists it, so omitting it next boot removes the authority. Lookup is by exact
identity; an identity the host did not name carries no migration authority.
Meerkat re-verifies from_role against the durable predecessor role and refuses
with MobError::MemberRoleMigrationRejected on mismatch, and ignores the
declaration once the roles already agree, so a leftover declaration is inert
rather than a repeat restamp.
A malformed payload fails mobkit/init with -32602 rather than arming
nothing, on both gateway binaries and whether or not an identity plane is
configured. One identity declared twice with conflicting from_role values is
refused too, rather than letting hash order pick which predecessor role becomes
authority, but the refusal differs by binary: rpc_gateway checks at init scope
and answers -32602 on the request, while mobkit_gateway checks inside its
identity-first block and fails the boot out as a -32603 internal error with a
null id. Under identity_first: false mobkit_gateway runs neither that
check nor the install, so a self-contradicting payload is not refused and
nothing is armed. An identical repeat is accepted on purpose.
The Python SDK exposes this as MobKitBuilder.role_migrations([...]), taking
RoleMigrationDeclaration dataclasses or plain dicts, both validated; a
conflicting pair raises ValueError, and an omitted or empty list emits no
role_migrations key at all. The TypeScript SDK has no equivalent surface.
Request format
Response format
Error format
data field carries structured context for typed
errors. SDKs surface it on RpcError.data.
Mobkit-specific error codes
The
-32010 constant is exported from both SDKs as
MOB_EVENTS_STALE_CURSOR_CODE. The Python and TypeScript SDKs auto-
reify -32010 errors into MobEventsStaleError (a typed subclass of
RpcError) carrying after_cursor and latest_cursor.
Console timeline replay failures use CONSOLE_TIMELINE_REPLAY_UNAVAILABLE_CODE
so they are not mistaken for mob-events ledger cursor errors.
The -32014 constant is exported as STORAGE_RESOLUTION_CODE and reified
as StorageResolutionError, so a deliberate durability refusal at startup
is a typed init failure, not a transport error. Storage refusals raised by
the Rust builder surfaces (UnifiedRuntime::bootstrap) still surface as
-32603 with the typed message text. The mobkit/init runtime_options
storage declarations (runtime_store, event_log) are documented in
Configuration → SDK and Gateway runtime options.
Topology control
Topology mutation is an optional MobKit control plane. It is disabled by default; a host must explicitly configureTopologyControlPolicy as
read_only or editable. The stock console only shows its Connections
view when the runtime advertises topology management, and it never invents a
connect all operation.
Every mutation is evaluated against both endpoint identities. With access
control enabled, callers need agent.view plus topology.view to inspect an
endpoint, and the action-specific topology.connect,
topology.disconnect, or topology.reconnect grant on both endpoints.
Planning requires the same action-specific endpoint grants as applying; it is
side-effect free, not an authorization oracle. Durable mutation history and
actor/principal attribution require the separate topology.audit grant on
every endpoint in the returned record.
Requests containing multiple explicit operations additionally require
topology.bulk and remain bounded by the policy’s finite max_batch_size.
mobkit/topology/query
Return the logical roster, observed/declared/operator topology, durable
suppression tombstones, current revision, and caller-specific per-endpoint
affordances. A disconnected declared edge remains in the response with
suppressed: true; this is how operator intent survives reconciliation and
restart.
mobkit/topology/plan
Validate a side-effect-free, revision-pinned set of explicit operations.
mobkit/topology/apply
Apply a previously valid shape of request. expected_revision provides
compare-and-swap protection and idempotency_key is mandatory. Exact replay
is durable only across the configured retention horizon: receipt_limit
keeps full operation receipts, then idempotency_history_limit keeps bounded
key fingerprints that reject ambiguous reuse after a receipt ages out.
Replaying a retained key whose receipt is unavailable returns -32009 with
data.kind = "topology_idempotency_receipt_expired"; replaying a key whose
fingerprint is still in the compacted ring returns -32009 with
data.kind = "topology_idempotency_history_compacted". Once both bounded
horizons have expired, that key is contractually new and normal revision and
policy validation applies—clients must not assume keys are reserved forever.
connect, disconnect, and reconnect are distinct policy actions:
reconnect removes a suppression and repairs an absent or one-sided desired
edge, while disconnect records a tombstone before removing physical wiring.
mobkit/topology/operation/get
Look up a durable operation receipt by operation_id. The endpoint is useful
after a client reconnect or an ambiguous transport failure; clients should
not infer success from a dropped HTTP response. The actor field is omitted
unless the caller has topology.audit on every endpoint in the receipt. This
lookup is also bounded by receipt_limit; persist the original request and
idempotency key so an ambiguous response can be replayed while its exact
receipt remains retained.
mobkit/topology/audit/query
Read the durable, versioned mutation-attempt ledger. This includes denied,
invalid, interrupted, recovered, applied, and rolled-back attempts, so it is
more sensitive than graph inspection and is advertised only to callers with a
topology.audit grant. Returned records additionally require agent.view,
topology.view, and topology.audit on every endpoint in that record.
Persist
next_after_seq after every response, including an empty one. If a
non-zero cursor is older than oldest_available_seq - 1, MobKit returns
-32009 with data.kind = "topology_audit_cursor_expired", after_seq, and
oldest_available_seq; restart from after_seq: 0 only when replaying from
the retained frontier is acceptable. A cursor equal to
oldest_available_seq - 1 remains valid.
ABAC filtering advances the cursor across records the caller cannot see. This
can leave gaps in visible seq values and reveals only that retained topology
activity existed at those sequence positions—not its endpoints, actor,
principal, operations, or result. That aggregate activity-volume metadata is
an intentional trade-off for a stable, non-duplicating forward cursor.
Cross-authority JSON-RPC mutation currently fails closed. Same-process hosts
that control both runtimes can use MobKit’s bilateral host API, which checks
both runtime policies and endpoint grants before changing either side.
Mob events
mobkit/mob_events/query
Scan the meerkat structural-event ledger and return matches.
Parameters
Parameters
next_after_seq — even when
the filter matches nothing — so polling SDKs keep a valid resume
anchor (caller’s after_seq or the current latest_cursor).
mobkit/mob_events/subscribe
JSON-RPC handshake that returns a snapshot plus a subscribe_url
pointing to the /mobkit/mob_events/stream SSE route.
The URL carries after_seq (next_after_seq ∨ caller’s after_seq ∨
latest_cursor) and the original filters so the SSE handler picks
up gaplessly with the same predicate.
Roster and reconcile methods
The roster family is served by the SDK stdio surface and, as runtime passthrough, byPOST /console/rpc. Roster reads cross the mob actor’s
sequential command loop and are bounded by the -32017 read budget. See
Roster and member lifecycle for the lifecycle model and
Profiles are templates
for why none of these methods spawn members from [profiles.*] on their own.
On rpc_gateway the roster itself comes from the SDK host. The gateway sends
callback/roster_provider/roster with the serialized RosterContext
(mob_definition, previous_identities) as the request params and expects a
DurableAgentSpec[] reply. The Python and TypeScript dispatchers hand the
provider params.context, which the gateway does not send, so the provider’s
context argument is empty on both SDKs; derive a profile-shaped roster from
the host’s own parsed definition, as the section linked above shows.
mobkit/ensure_member
Ensure a member exists, spawning it when missing. On the SDK-facing
rpc_gateway this is the ephemeral worker plane (MobHandle::ensure_member);
on an identity-first console gateway it upserts a durable identity unless the
request carries plane: "worker" (see ensure_member gateway
profiles).
Parameters
Parameters
reconcile_edges, so declared
definition wiring (auto_wire_orchestrator, role_wiring) converges
regardless of the order members are brought up; calling reconcile_edges
right after ensure_member is redundant.
Spawn refusals come back as -32602 with the meerkat error in the message,
for example ensure_member failed: wiring error: profile 'x' has tools.comms=false; mob meerkats require comms=true. Every mob profile must set
tools.comms = true (the field defaults to false, so omitting it is refused
too): a member’s identity, roster occupancy, wiring, and peer messaging are all
keyed on its comms name. To keep a member from messaging peers, use
read_only = true or a per-member tool policy, not comms = false. On the
identity plane the same refusal does not error the RPC: the receipt’s outcome
is broken and the reason lives in the identity’s bootstrap status error.
mobkit/reload_member
Non-destructive cold reload of an identity’s live member. The live runtime
registration is discarded and the SAME durable session is re-materialized
from durable truth: same identity alias, same session_id, same continuity
generation. This is the repair for a member whose sends fail with the
reload-required class (meerkat’s RecoveryRepairBlocked: “registration-
authorized cold reload is required”). The delivery path runs exactly one such
reload automatically before failing typed; this verb is the operator’s manual
form.
Contrast mobkit/respawn_member, which on an identity-first gateway is a
destructive continuity reset (fence owner, advance generation, fresh
session). reload_member never calls it.
Result:
Broken or suspended identities are refused (
-32603, invalid
state); they need the reconcile/repair paths. Retired identities return
not_current without being revived. The primitive’s not_current is also a
no-op, not a fallback to retire/rematerialize. Worker-plane members are
refused: the worker plane has no non-destructive reload. Two typed failures
come from meerkat’s reload primitive: a refusal (“store not healthy, reload
refused, retry later”: the durable resume authority is still unreadable, the
registration is retained, and sends stay reload-required) and a timeout
naming the stage it reached (MEMBER_RELOAD_TOTAL_TIMEOUT, 45 s; inspect the
member before retrying). Both are visible afterwards in
mobkit/member_health.last_reload.
mobkit/member_health
The identity’s lifecycle and delivery health from in-process reads only. It
never crosses the mob actor’s command loop, so unlike mobkit/member_status
it answers while the loop is stalled, which is when an operator needs it.
Result (
MemberHealthReport):
Actor timeouts preserve
{kind: "mob_actor_command_timed_out", command_kind, stage, deadline_reached: true} in RPC error.data, console error data, and
last_delivery_error.data. The upstream stages include
actor_command_admission and actor_command_reply; the latter may follow
runtime admission. A local observation timeout has kind
actor_admission_timeout and no invented upstream command/stage.
Neither form asserts execution fate or retryability: absent executed or
retryable fields are not a nonexecution verdict. Consult runtime idempotency
and durable fate; MobKit does not automatically retry or reload on a timeout.
The same observations survive an explicit or automatic reload. In-flight
probe interruptions carry observation: "in_flight", distinct from a true
"before_call" refusal, and do not settle the reload worker’s execution fate.
Custom SessionBridge::member_durability implementations may await their own
I/O, but do not hold the runtime’s fleet entries lock.
Admission backpressure and reload failures retain sanitized owner data across
send/dispatch errors, console REST/RPC, and health: mob_member_admission_backlog_full
carries depth, mob_member_reload_refused carries its kind only, and
mob_member_reload_timed_out carries the original stage. These payloads add
no execution or retry verdict and omit backend refusal details. Native reload
validates the identity’s existing lease before invoking Meerkat’s registration
primitive; absent or lost ownership refuses without discarding the registration.
mobkit/reconcile_edges
Converge the definition-derived edge policy over the live roster and return
{desired_edges, wired_edges, unwired_edges, retained_edges, preexisting_edges, skipped_missing_members, pruned_stale_managed_edges, failures}. The reconciler only unwires edges it wired itself. It is needed
after mobkit/reconcile_identity or an identity-first gateway boot when the
definition declares wiring, because neither of those converges definition
edges after materialization; without declared wiring the report is empty.
mobkit/reconcile_identity
Re-run the roster provider and restore_flow (Python runtime.reconcile()).
Picks up added, removed, and modified identities and host TopologyProvider
edges. It does not run reconcile_edges. Unavailable without an identity-first
runtime.
mobkit/rediscover
Reset the whole mob, re-run the Rust builder Discovery, respawn discovered
members, and reconcile edges. Neither gateway binary wires a Discovery, so on
every SDK host this returns {status: "no_discovery_configured"}; with
identity-first authority attached it is refused outright (-32000,
rediscover resets the whole mob and is unavailable with identity-first authority; use refresh_desired_topology).
Console timeline
Console-specific RPC methods are handled by the HTTP console dispatcher and are also listed in the console contractv0.5.0.
Surface split: mobkit/console/* methods are served ONLY by the HTTP
console dispatcher (POST /console/rpc). The stdio JSON-RPC surface
(rpc_gateway stdin) neither dispatches nor advertises them — embedders
needing console data over stdio should use the http_base_url from the
init handshake and call the HTTP surface. The advertised-methods list on
each surface reflects exactly what that surface dispatches.
mobkit/console/list_identities
List identities known to the console aggregator.
mobkit/console/inspect_identity
Inspect one console identity and return status, affordances, output preview, and reachability metadata. Older servers may only support the legacy mobkit/inspect_identity; the headless console controller keeps that as a compatibility fallback.
mobkit/console/query_timeline
Query the console log store for timeline frames. The method backs the bundled console chat and activity panes.
Parameters
Parameters
next_cursor never advances past visible frames omitted due to limit, so clients can page with mode: "since" without gaps. latest_cursor is the live-continuation cursor for mode: "recent" seed queries.
Backfill frames are not fresh completions. Session-history backfill
re-emits past turns as frames whose source.kind is "session_history". They
carry session_id, and they carry the SAME interaction_id and run_id the
live frames carried: meerkat persists the message identity onto committed
transcript messages and the backfill stamps it back (null only for messages
that predate that persistence). Identity queries and every session-bearing
live frame can trigger backfill, and a history twin of a tool-only assistant
step arrives as an interaction_complete with empty text, so matching by
interaction_id alone does NOT separate live completions from history. Any
consumer correlating completions MUST exclude source.kind == "session_history" frames from live turn handling, ignore frame_updated
marker frames (emitted when a frame’s status changes, for example accepted to
delivered), and then match interaction_complete on the interaction_id
returned by mobkit/console/send.
mobkit/console/send
Submit an identity-addressed console interaction through the console aggregator.
interaction_id and identity. The multipart JSON-RPC endpoint also accepts this method when content contains image_upload placeholders.
idempotency_key must be unique per send (the bundled console mints one per
send). Replaying a key with identical content returns the earlier interaction’s
acceptance, whether or not that turn has finished; replaying it with different
content is refused with -32009 (idempotency_conflict, HTTP 409 on the REST
form). The key is not cleared by a member respawn.
mobkit/blob/upload
Upload a single blob/image through POST /console/rpc/multipart. The response includes a blob_id that can be rendered through GET /blobs/{blob_id}.
mobkit/list_runs
List flow runs for this mob.
Parameters
Parameters
{runs: MobRun[]} carrying the full meerkat ledger projection:
step_ledger, failure_ledger, frames (map keyed by frame id),
loops (map keyed by loop id), loop_iteration_ledger,
flow_state, activation_params, schema_version,
root_step_outputs, loop_iteration_outputs.
mobkit/reset_all
Console surface only (POST /console/rpc; mutating; ABAC action
agent.reset). The stdio surface neither dispatches nor advertises it, and the
aggregator-only console (no runtime attached) refuses it with data.kind = "unsupported_reset_all_surface" rather than retiring anything. It resets every
console-visible identity in one pass and never exits the gateway process: a
slow reset_all is a long request, not a restart. The designed exits are
elsewhere, and differ per binary: rpc_gateway ends when the SDK closes its
stdin (EOF), on SIGINT or SIGTERM, or through the SDK’s shutdown handshake;
mobkit_gateway keeps serving HTTP after its stdin closes and ends only on
SIGINT or SIGTERM or when its HTTP server task ends. Both stdin behaviours are
test-pinned (tests/gateway_concurrent_dispatch.rs).
The pass is sequential, one identity at a time:
- Preflight, fail-closed. Every target is checked before anything is
mutated: a live console alias that resolves to another identity’s runtime
member, a registered identity whose live session disagrees with its
binding (
stale_live_identity_alias), or a registered identity when the identity runtime has no session bridge (identity_reset_requires_session_bridge). Any failure returns the body below withfailednon-empty and nothing changed. - Raw delegates, helper members with no registered identity, are retired.
- Each registered identity is reset through the identity runtime (a new generation and a new session); a live member that carries no registered identity is respawned in place. Only raw delegates without a registered identity are retired.
- The call waits up to 10 seconds for the reset identities’ startup history to reach the console timeline, then returns.
Result
Result
Gating methods
mobkit/gating/evaluate
Evaluate the risk tier for a proposed action.
Parameters
Parameters
Response
Response
mobkit/gating/decide
Approve or deny a pending gated action.
Parameters
Parameters
mobkit/gating/pending
List all pending gated actions awaiting approval.
mobkit/gating/audit
Return the gating audit log (most recent entries, bounded by retention limit).
Memory methods
mobkit/memory/index
Record an operational memory assertion or conflict signal. This surface is the
MobKit assertion ledger used by routing/gating flows; it is not semantic/vector
document search. The runtime owns the ledger: it loads the local JSON file once
at bootstrap, holds the assertions in memory, and rewrites the whole file
(optionally health-gated by an external endpoint) on every index. The file is
not a shared append log; edits made to it directly are overwritten, and the
ledger keeps at most 4,096 assertions. See
the ownership model.
The stock RPC contract stores and filters canonical assertions.
Parameters
Parameters
mobkit/memory/query
Query stored assertions and conflict signals by exact filters.
Parameters
Parameters
mobkit/memory/stores
Return information about configured memory backends.
Agent-memory methods are available over the SDK JSON-RPC gateway and over
console POST /console/rpc when the identity runtime has an agent-memory
provider configured. Console callers can recall only identities they may view;
remember and forget also require mutating console access plus
agent.memory.write and agent.memory.delete respectively.
mobkit/agent_memory/remember
Write an identity-scoped agent memory record for later per-turn and build-context injection. This is separate from mobkit/memory/*, which is the operational assertion ledger. A successful write means the configured hot identity-memory provider accepted the record; optional Elephant enrichment or extraction, when supplied by a custom provider, is out of band.
Parameters
Parameters
mobkit/agent_memory/recall
Read identity-scoped agent memory records from the configured agent memory provider. This exposes the same durable record set used for per-turn and build-context injection. Unlike automatic injection, explicit recall reports provider errors to the caller.
Parameters
Parameters
mobkit/agent_memory/forget
Delete one identity-scoped agent memory record from the configured provider. Providers that do not support deletes do not advertise this method in mobkit/capabilities. forget prevents future provider recall and future automatic injection; it cannot remove text that has already been delivered into an active model context.
Parameters
Parameters
Result
Result
Routing methods
mobkit/routing/resolve
Resolve a logical destination to a physical route.
Parameters
Parameters
Response
Response
mobkit/routing/routes/list
List all registered routes.
mobkit/routing/routes/add
Register a new route.
Parameters
Parameters
mobkit/routing/routes/delete
Remove a registered route.
mobkit/identity/routing_status
Meerkat’s typed model-routing status for the live session behind a MobKit
identity. The result is meerkat’s SessionModelRoutingStatus verbatim
(WireSessionModelRoutingStatus is a type alias to it), flattened under
identity and session_id. MobKit declares no mirror type, so this payload
cannot drift from meerkat’s contract.
Parameters
Parameters
identity, session_id, baseline_model, effective_model,
and the optional session_provider, active_turn_override,
active_operation_override, pending_switch_turn.
session_provider is the typed provider of the session’s current LLM identity.
An absent session_provider means the runtime machine has no hydrated session
LLM identity yet (pre-hydration). It is not a signal to re-derive a provider
from effective_model: meerkat documents that re-derivation as silently wrong
for models owned by a custom ModelRegistry, which is why the field is carried
typed rather than inferred.
This method requires a resolved session. Identity-first materializes an
identity without activating it, so an identity that has been materialized but
never addressed has no session and therefore no routing status. That is the
expected state after a restart, not a defect. A fleet sweep should address an
identity before reading, and label its coverage post-address rather than
post-restart.
Failures carry a machine-readable discriminator so a sweep can classify an
identity rather than only fail it:
Each reason is derived only from a fact MobKit observed.
session_not_held is
matched on RuntimeDriverError::NotFound structurally, never on message text;
because that error is #[non_exhaustive], every other upstream failure lands in
upstream_read_failed rather than being asserted as a missing session.
handle.identity_routing_status(identity) (Python),
handle.identityRoutingStatus(identity) (TypeScript).
Delivery methods
mobkit/delivery/send
Send a message through a resolved route.
Parameters
Parameters
mobkit/delivery/history
Return delivery records for audit and inspection.
WorkGraph methods
Themobkit/workgraph/* group exposes meerkat’s WorkGraph (the shared-work
ledger) for this runtime’s realm. Results serialize meerkat’s typed results
verbatim (WorkItem, WorkGraphSnapshot, WorkAttentionBinding,
WorkEdge, …); expected_revision is the compare-and-swap token on every
mutation. All fields are snake_case.
Availability and the auto-issued grant. The group is advertised in
mobkit/capabilities (and "workgraph": true is set) only when the service is
configured, which it is by default: runtime_options.workgraph defaults to
enabled (Python .workgraph(True), TypeScript .workgraph(true); false
disables, a string is an explicit durable-store directory). With
persistent_state the store is <persistent_state>/workgraph.sqlite3;
without it the service is memory-backed and the gateway warns at boot on
identity-first launches. The WorkGraphNamespaceGrant meerkat requires per
agent is issued by MobKit from the wired service (realm = the mob id,
namespace default) for every member whose profile sets
tools.workgraph = true; hosts do not issue it. realm_id is rejected
(-32602) on every method for the same reason: the service is realm-scoped at
construction and agent tool calls are scope-pinned to it.
Filter semantics that are easy to get wrong.
labelsmatches ALL: every listed label must be present on the item (list,ready,snapshot). This is the opposite of the builtintask_listtool, which matches any label.include_terminaldefaults tofalseand drops completed, cancelled, and failed items even whenstatusesnames one of them;statuses: ["completed"]withoutinclude_terminal: truereturns nothing. The bundled console panel passesinclude_terminal: true, so it can show items the SDK default hides.limitdefaults to 100 and may not exceed 1000 (-32602beyond it).- Nothing deletes items or edges. Close an item as
cancelledorfailed, or link a replacement with kindsupersedes;attention/pruneis the one deleting verb and removes only terminal attention-binding rows. The event stream keeps the history. - A
parentedge points from the child (from_id) to the parent (to_id); useblocksonly when the target must not be ready until the source is terminally resolved. closewithoutstatusrecordscompleted. Passstatusexplicitly when the outcome is anything else.
Read methods (ABAC workgraph.view)
Mutating methods (ABAC workgraph.manage; console also requires can_mutate)
goal/create, attention/*, and policy/escalate reject a non-default
namespace (-32602) because upstream turn-overlay resolution reads only the
service’s default namespace. One active (or paused) binding per target is
enforced across goal/create, attention/reassign, and attention/resume; a
second returns -32042 naming the occupant.
Errors
SDK method names are the RPC names with the
mobkit/workgraph/ prefix
dropped, in snake_case for Python (workgraph_snapshot through
workgraph_attention_prune, plus workgraph_add_evidence and
workgraph_escalate_policy) and camelCase for TypeScript.
attention/break_glass_reassign is deliberately in neither SDK, and
mobkit/workgraph/facts (the cursor-tail projection behind the SSE wake
stream) has no SDK wrapper either.
Notifications
The persistentrpc_gateway sends JSON-RPC notifications (no id) to the SDK
alongside responses. Callback requests (callback/*) expect a reply; these do
not.
mobkit/on_error
Every runtime ErrorEvent, serialized with its internal category tag in
snake_case and the variant’s fields beside it:
rpc_gateway installs the forwarding hook unconditionally, so the runtime’s
absent-hook notice never fires for SDK hosts; the SDKs deliver the payload to
the callback registered with Python .on_error(callback) / TypeScript
.onError(callback) and drop it silently when none is registered. The same
event is always logged on the gateway’s stderr at ERROR (INFO for
actor_loop_recovered). mobkit_gateway emits no notifications. The variant
table is in Error hook and logging.
Operator transcript verbs
Two identity-scoped operator affordances for oversized or wedged member transcripts. Both resolve their target through the same identity-control gate asmobkit/respawn / mobkit/reset, so identities the gateway does not own
are refused at resolution.
mobkit/compact_member
Force one transcript compaction on a member, then restore its original
compaction threshold. Arms a temporary auto_compact_threshold floor for the
identity, respawns the member in place so the fresh build picks the floor up,
drives one queued maintenance turn (the forced compaction fires at that turn’s
pre-LLM boundary), then disarms the floor and respawns again.
Params: identity (required), floor_tokens (default 1024), timeout_ms
(default 60000, budget for the maintenance turn).
timeout_ms bounds observation, not execution. The operation submits exactly
once with a caller-owned idempotency key and reads that input’s rich finalized
completion through the persistent session owner’s runtime adapter. A completion
cursor, Consumed input phase, or accepted interrupt is not completion proof.
After the deadline, the RPC remains an error even if compaction completes later.
The existing five-second secondary observation budget allows exact late
completion and profile restoration to be reported. If it expires, error.data
reports kind: "compact_member_timeout", stage: "terminal_pending" and an
operation_id; the runtime still owns completion and profile cleanup. Dropping
the RPC caller does not drop that ownership. Read failures likewise report
pending/unknown fate and retain the same input’s observer, without resending.
Concurrent compaction of the same identity refuses while that operation owns it.
An uncertain admission reply follows the same original key through these reads;
it never causes a second submission. The pending-operation record is separate
from the build override, which applies only to the intended maintenance build.
Only an exact successful terminal for the captured session and incarnation
authorizes clearing the floor and rebuilding the same session. A failed terminal
preserves its completion_type and typed error metadata; supersession refuses
restoration rather than reviving a retired identity or touching its replacement.
Supersession invalidates only that operation’s obsolete override; it does not
rebuild the member or let the old floor leak into a later incarnation.
No timeout triggers retirement, transcript discard, or a synthetic healthy state.
Stock persistent compositions supply the exact observer. Custom compositions
must forward CommittedBoundaryRecoverer::runtime_completion_observer or use
MobBootstrapSpec::with_runtime_completion_observer with the concrete
persistent session service’s canonical runtime adapter. This is separate from
the bootstrap adapter override. Missing capability returns -32016 before
installing a floor; an observer-only injection does not claim recovery support.
Result: identity, session_id, floor_tokens, messages_before,
messages_after, compaction_applied, head_revision,
last_rewrite_reason (message counts and revision facts are null when the
gateway has no concrete transcript-edit service).
mobkit/bound_member_transcript
Surgical escape hatch: commit one audited keep-last-N transcript rewrite on a
QUIESCED member session (running sessions refuse with -32015; retire or park
the member first). The cut point is pair-safe: it never separates an assistant
tool-use message from its adjacent tool_results. The removed prefix is
replaced by one operator marker notice, and the rewrite is committed with a
compare-and-swap against the head revision observed at read time.
Params: identity (required), keep_last (default 50), note (optional
audit note recorded on the rewrite reason).
Result: bounded, removed, kept, message_count, parent_revision,
revision (or bounded: false with removed: 0 when the transcript is
already within keep_last).
Scheduling migration
Contract 0.5.0 removedmobkit/scheduling/evaluate and
mobkit/scheduling/dispatch. Both names now return the standard -32601
method-not-found error. Use the durable schedule tools and ScheduleService,
which own schedule definitions, occurrence claims, firing records, and target
delivery.
See Scheduling for migration guidance.
Session store methods
mobkit/session_store/bigquery
Execute BigQuery-specific session store operations.
Storage methods
mobkit/storage/doctor
Read-only storage diagnosis over a MobKit state directory (the diagnose half
of Meerkat’s StorageMigrator seam). Safe against a live gateway: read-only
SQLite opens, no file creation, no leases, no schema-ledger runs. Reports the
per-directory database inventory (with schema-ledger versions), file-name
twins (sessions.db beside sessions.sqlite, continuity.db beside
identity_continuity.sqlite, agent-memory/ beside agent-memory-sqlite/,
…), the continuity checkpoint-evidence census per identity, dangling
console-frame blob references, legacy-FS blob objects, and filesystem
artifacts. On a live persistent gateway the H1/H2 durability resolution
(blob-durability, session-store-incremental) is attached as findings; a
cold directory reports durability-census-unavailable.
Available on the module-only, unified, and console (POST /console/rpc,
read method, runtime.admin grant) surfaces. Additive method — no
contract_version bump.
Parameters
Parameters
Result
Result
Subscribe methods
mobkit/events/subscribe
Return a bounded replay snapshot of merged runtime events. The result includes
both typed event envelopes and the same events rendered as SSE frames; this
method does not itself open a live HTTP stream.
Parameters
Parameters
The server applies the scope first, then retains at most the three newest
matching events. With no
last_event_id, all retained events are returned.
With a checkpoint, replay starts at that event, inclusively. A checkpoint that
is unknown, belongs to another scope, or has fallen outside the three-event
window returns JSON-RPC -32602. A reconnecting consumer should deduplicate
the first replayed event by event_id.
Result
Result
Console ingress
The olderconsole.route style is not the stock console contract. Use GET /console/experience, GET /console/timeline, and POST /console/rpc instead.
