Skip to main content
Mobs are Meerkat’s multi-agent runtime. There is no separate sub-agent substrate: delegation, helper agents, flows, and reusable profiles all compile to mob members managed by meerkat-mob.

Core Model

MobActor serializes mob commands, persists mob state, and projects public status from MobMachine authority. Member sessions are still ordinary Meerkat sessions, so they inherit provider, tool, auth, memory, and live-channel behavior from the session runtime.

Identity

Mob member identity has two layers: Use AgentIdentity for facts that survive respawn. Use AgentRuntimeId only for per-binding runtime facts.

One-shot durable role migration

Role is durable context, but it is not member identity. MemberLaunchMode::Resume can carry resume_from_role on one exact trusted-host request. The declaration must name the role stored on the exact cold session. The mob id, AgentIdentity, and session id remain unchanged. When the stored and requested roles differ, an absent declaration fails with MemberRoleMigrationRequired; incorrect, inapplicable, and live-session attempts fail with MemberRoleMigrationRejected. Success retains the transcript and restamps the current comms name, typed member binding, role/profile labels, callback context, and explicitly configured tooling. The declaration is not persisted, so a SpawnMemberCustomizer must re-supply it at SpawnSource::Resume after process restart. This seam exists on trusted in-process SpawnMemberSpec and private MaterializeLaunchMode::Resume only. Agent tools, standing profiles, CLI, public RPC/REST/MCP/SDK spawn contracts, and Web do not expose it.

Runtime Bindings

Member construction and member placement are separate facts. Members can be local session-backed agents, explicitly bound external peers, or session-backed agents materialized on a bound member host. External members require an explicit runtime binding. A bare External backend tag is not enough because the runtime needs a concrete process identity before it can route work or trust peer messages. For a remote rkat member, generate the current binding with rkat run --comms-listen-tcp ... --comms-binding-out <path>.

Placed-member portability

The remote spawn lane accepts only a digest-covered PortableMemberSpec. Machine admission rejects, rather than drops, all controller-local executable or secret-bearing fields: Placement also cannot be combined with an explicit backend or RuntimeBinding; the member must have exactly one execution transport story. WorkGraph tools are controller-local because the WorkGraph store and execution binding remain on the controlling host. Schedule tools are portable. Memory and declarative MCP servers require matching member-host capabilities and must not carry the rejected secret fields. Host capability admission also checks autonomous members, durable sessions, tracked input cancel, bridge protocol v4, memory store, and MCP when the resolved member requires them.

Host-designated conversational input

Trusted Rust hosts can submit authenticated human input with MobHandle::submit_host_human_input_bounded(runtime_id, fence_token, spec, handling_mode, delivery_identity, deadline). It returns WorkDeliveryReceipt after runtime admission, not after an LLM response. start_host_human_input_bounded takes the same arguments and returns a WorkTurnHandle for separate runtime-owned completion observation. submit_host_human_input_for_identity_bounded resolves an identity once before the same fenced admission. A host already holding a delivery lease should pass its exact runtime and fence instead of resolving a replacement. This is a Rust-only designation, not a serializable WorkSpec role or an agent-tool flag. The host must authenticate the human before opting in. WorkOrigin still governs addressability. Existing generic work APIs retain their behavior, including autonomous SystemNotice::ExternalEvent delivery. Only the explicit human seam delivers the work content as canonical conversational Message::User. System and injected-context slots keep their own roles. Installed shared Live context receives conversational input and assistant text from the normal store-sealed commit path; platform notices are not promoted. Use MobDeliveryIdentity::new(stable_key, interaction_uuid.to_string()), retain both values across retries, and keep any WorkSpec.interaction_id identical to that UUID. The deadline is meerkat_core::time_compat::Instant (std::time::Instant on native hosts). ActorCommandTimedOut reports unknown execution fate: an already-started admission may finish after the observation deadline. Retry only with the same delivery identity. Dropping a completion handle does not cancel work. On replay, the receipt refers to the original admission, even if that work already terminalized. Completion-bearing replay reads the original runtime terminal result; an unavailable result is an explicit WorkInputCompletionUnavailable, never synthesized success. Human admission requests exact prompt replay from the runtime owner. A compact prompt witness is persisted atomically with the input row and survives terminal payload retirement. A repeated strict request must match the original prompt, typed context slots, handling mode, and correlation; a prior external event, changed body, or legacy row without a provable prompt witness returns WorkInputIdempotencyConflict. Generic callers keep their existing key-only deduplication contract. Stale runtime/fence pairs remain machine-refused.

Multi-Host Authority

Realms are not distributed. The controlling host and each member host retain one local realm and one set of local session authorities. One host acceptor serves many placed members and demultiplexes signed envelopes by recipient public key. The peer envelope stays identity-addressed. The private supervisor.bridge protocol shares that transport but has separate machine admission and is never promoted to ordinary agent authority. Remote observation is controller-proxied. Member history is read from the owning host, and remote event pages feed the controlling mob’s merged stream. The public identity-routed operations remain placement-transparent. Host reachability, route-install convergence, generation, fence, and provenance remain visible as typed evidence. Hosts advertise runtime.capabilities.features.multi_host_mobs; clients must treat false as an unsupported capability, not infer support from method presence. The placed session id remains realm-local to its owning member host. A client cannot feed it to the controller’s generic session/* methods. Use mob identity operations and mob/member_history; remote transcript revision and edit methods are not part of the v1 bridge.

Public Surfaces

Flows

Flows are declarative work graphs. They support one-to-one, fan-out, fan-in, branching, and frame/loop nodes. Flow status is persisted, so a host can check live state first and fall back to the terminal snapshot.

WorkGraph Bridge

WorkGraph commitments and Flow runs remain separate authorities. A durable WorkExecutionBinding records the exact effective Flow run configuration and deterministic run identity before execution. The generated execution lifecycle requests the launch, observes Mob-owned terminal state, requests evidence projection, and feeds the WorkGraph closure result back into the binding lifecycle. The external-delivery ledger is not a second run machine. Its realizing phase is a custody fence, crossed by the Mob actor only after the deterministic pending MobRun is durable. Mob remains the sole owner of run lifecycle. The ledger prevents blind target reinvocation across an unobserved reply boundary. Flow success is evidence, not completion authority. WorkGraph’s completion policy remains the only path that can terminalize the commitment. Failed and canceled runs remain terminal execution attempts and may be superseded by a new binding while the WorkGraph item stays open. For multi-host mobs, the binding and WorkGraph store remain on the controlling host. Remotely placed members execute Flow steps through normal Mob routing; they do not independently claim or mutate the controlling WorkGraph. Terminal run observation and evidence projection return to the controlling host, so distributed execution does not create replicated WorkGraph authority.

Persistence

Persistent mob state is SQLite/WAL-backed through SqliteMobStores. In-memory storage is used for tests and WASM. The previous exclusive-handle mob store is gone.

Durable definition updates

The structural event log owns the durable definition. MobCreated establishes definition epoch 1; each MobDefinitionUpdated is a strict MobMachine-authorized successor. The mob spec store is only a projection and its revision must equal the authoritative epoch. Trusted Rust hosts update a cold process-local mob before resume:
The event authority commits first under an atomic CAS. If the process fails before the projection write, exact retry or resume repairs the stale projection. MobStorage::definition_projection_health() exposes missing, stale, healthy, and diverged states. A same-revision content mismatch or projection-ahead state fails resume with MobDefinitionProjectionMismatch; consumers must not append raw events, write only the spec projection, or weaken this refusal. Hosts that inspect a definition before resume use the storage-minted MobDefinitionSnapshot. Verified resume compares its full definition, epoch, and authoritative MobCreated/MobDefinitionUpdated event cursor against the actual replay before repair or actuation; a concurrent update returns MobDefinitionAuthorityChanged. The verified resume claim holds the database’s shared cross-process fence through runtime construction; update_definition takes the matching exclusive fence, so an external SQLite writer cannot cross the replay-to-actuation interval. Multi-host persistence is deliberately split. The controlling realm stores the mob, host bindings, placement, grants, route obligations, flow/work state, and merged event position. The owning member-host realm stores each placed session and its history. Restart recovery replays these authorities and re-establishes routes; it does not copy member realms into the controller. Mobpacks are portable mob artifacts. They package definitions, optional runtime assets, capability declarations, and optional signature metadata. Verifier trust policy and trusted-signer enrollment remain host-owned. Deploy through:
mob web build copies the required prebuilt wasm-pack output into the browser bundle; it does not compile wasm32.

Live Channels

Live channels execute in the owning session. For a mob member, use the identity-routed mob/member_live_open, close, status, and control family. It is placement-transparent and returns the owning host’s WebSocket endpoint. Explicit WebRTC is rejected with LiveTransportUnsupported for local and placed members; session-scoped live/open remains the WebRTC path for a controller-local session. The old realtime attachment/status plane has been removed. Live channel lifecycle is caller-initiated through the live/* method family.

Source Pointers

See Also