Skip to main content
This page documents MobKit v0.8.34 (mirrored from v0.8.34). MobKit exposes three related event surfaces:
  • EventEnvelope<UnifiedEvent> merges projected Meerkat agent events with MobKit module events.
  • MobStructuralEventEnvelope projects structural events from the Meerkat mob-event ledger.
  • The WorkGraph wake stream emits bare UnifiedEvent::Module values at GET /mobkit/workgraph/facts/stream as lossy notifications.
They have different transport shapes and durability properties.

Unified event envelope

For UnifiedEvent::Agent, source must be "agent". For UnifiedEvent::Module, it must be "module". The optional agent payload is part of the wire contract and must not be dropped when matching or forwarding the event.

Agent event names

Agent event names come from Meerkat’s exhaustive event mapper. Current examples include:
  • Run and turn: run_started, retrying, run_completed, run_failed, turn_started, turn_completed
  • Model output: reasoning_delta, reasoning_complete, text_delta, text_complete
  • Tools: tool_call_requested, tool_result_received, tool_execution_started, tool_execution_completed, tool_execution_timed_out
  • Hooks: hook_started, hook_completed, hook_failed, hook_denied
  • Compaction: compaction_started, compaction_completed, compaction_failed
  • Interaction: interaction_complete, interaction_callback_pending, interaction_failed. Only the first and last are terminals; interaction_callback_pending means the interaction is paused at an external callback boundary waiting for tool results, and it resumes and closes under the same interaction_id
These strings are projections of Meerkat AgentEvent variants. MobKit does not synthesize them as module events.

Run failure payload

run_failed carries Meerkat’s typed failure fact as error_report; since Meerkat 0.7 there is no separately carried error string on the wire. MobKit’s projection (console_agent_event_payload, the single site every SSE stream, event-log row and console frame goes through) keeps the report and derives two flat keys from it, so consumers read one shape:
The console interaction_failed frame MobKit projects from run_failed carries the same payload, so frame.data.error and frame.data.reason name the failure there too. Frames MobKit mints itself (reason: "superseded_by_later_run", or error set from a delivery failure) carry only the flat keys. Meerkat’s own interaction_failed agent event carries a typed reason object (kind discriminator) whose Display is mirrored into error. The Python SDK exposes the report as RunFailed.error_report (with error_class and reason_type accessors) and derives RunFailed.error from it; the TypeScript SDK exposes RunFailedEvent.errorReport; UnifiedAgentEvent.payload carries it for query_events consumers. A retried LLM call (a 429, a network timeout) surfaces as retrying events before either terminal; a non-retryable failure (a 401 on a bad key) reaches run_failed in one round trip. The user_input frame of a console send terminates at delivered by design (the send was admitted); the turn’s outcome is the sibling interaction_complete or interaction_failed frame, not a status change on the input frame.

Merged module event names

MobKit itself generates these module event types in the merged envelope log: Generic modules may supply additional event names through their own valid envelopes. Gating audit entries, memory operations, and supervisor health transitions are not currently generated as unified module events by MobKit.

WorkGraph wake events

The separate WorkGraph wake stream uses the UnifiedEvent::Module shape but serializes that value directly as SSE data. It does not wrap the value in EventEnvelope, write it to merged_events, or include it in mobkit/events/subscribe. Every connection begins with workgraph.resync_required and reason = "initial_sync". The stream then sends workgraph.fact wakes and can send workgraph.resync_required with reason = "lagged" after broadcast lag. It has no SSE ID, Last-Event-ID, catch-up, or replay contract. Consumers obtain authoritative graph state through the WorkGraph get, list, ready, and snapshot pull methods.

Ordering and normalization

merge_unified_events orders envelopes by:
  1. timestamp_ms
  2. event_id
  3. source
There is no special agent-before-module tie rule. The module boundary accepts direct EventEnvelope<UnifiedEvent> JSON and a supported flat event form. Normalization verifies that the source agrees with the UnifiedEvent variant and rejects malformed input. It does not mint missing IDs, enforce ID uniqueness, deduplicate events, or rewrite timestamps. insert_event_sorted uses the same ordering when runtime operations add later events.

Structural mob events

The structural surface preserves a Meerkat mob-event cursor and the serialized MobEventKind payload:
The projection uses event_id: "mob-evt-{cursor}", preserves the upstream cursor and timestamp, maps the event kind to its snake-case name, and places the full serialized kind payload in data. Current kinds include mob_created, member_spawned, flow_started, step_dispatched, members_wired, and supervisor_escalation. The enum can grow, so clients should not depend on a fixed variant count.

Cursor persistence and replay

The structural subscriber reads from MobEventsView. With a saved cursor it uses subscribe_after(cursor); without one it starts from the latest cursor. It writes the last projected cursor to PersistentMetadataStore after projection. Cursor persistence is not event persistence:
  • If a persistent-state path is configured and no explicit metadata store is supplied, MobKit creates <path>/mobkit_metadata.sqlite3 for projection metadata.
  • That metadata stores the resume cursor, not the mob-event ledger.
  • .persistent_state(path) by itself keeps Mob storage in memory.
  • Replaying events written while MobKit was down requires an upstream Meerkat mob-event store that retained those events.
If a saved cursor is stale for the available ledger, the subscriber falls back to the latest cursor.

Access surfaces

See SSE API for stream parameters and JSON-RPC API for request and response shapes.

Lifecycle events

LifecycleStage has these exact variants: Each LifecycleEvent contains a monotonic seq and one stage. Read the retained entries through MobkitRuntimeHandle::lifecycle_events(). ModulesStarted is not proof that every module is healthy; inspect SupervisorReport for module transitions.

See also

  • Modules - module startup and event origins
  • Delivery - resolved and send payloads
  • SSE API - unified, WorkGraph wake, and structural streams
  • Architecture - event transport and ownership