Skip to main content

WorkGraph Reference

WorkGraph is an optional realm-scoped subsystem. Agents mutate general work items through tools. Public RPC and REST expose observability/operator lookup. CLI and trusted in-process hosts add narrow goal and attention controls. Every enabled agent/service instance is constructed with one exact WorkGraphNamespaceGrant { realm_id, namespace }. The grant is immutable and authorizes one namespace only. Cross-realm, cross-namespace, and all_namespaces requests are rejected; callers cannot widen authority by supplying filter fields.

WorkItem

Statuses

Terminal items cannot be claimed.

Completion Policies

General public goal creation exposes self_attest. Stronger policies and their typed confirmation evidence require trusted host authority. An attention-bound agent may only tighten a policy monotonically through the injected workgraph_policy_escalate operation.

Edge Kinds

WorkGraph rejects invalid endpoints, self edges, duplicate edges, and cycles for blocks and parent. For blocks, the source satisfies the edge only in completed; failed or cancelled blockers remain unsatisfied. A parent edge points from direct child to parent. Active children keep the parent join unsatisfied. For failed and cancelled children, each parent policy means:

Owners And Claims

WorkOwnerKey.kind is one of:
  • principal
  • agent
  • session
  • mob
  • label
Claims are revision-based. Mutating tools require the current expected_revision. Optional leases allow abandoned work to become recoverable through machine- approved transitions. The model-facing workgraph_claim schema advertises only lease_seconds: 1-31,536,000 seconds from the store’s claim observation time. Omit it for no expiry. Advertising a single representation avoids ambiguous calls on providers whose tool schemas cannot express root-level exclusivity. The Rust ClaimWorkItemRequest and existing tool dispatch still accept an absolute lease_expires_at instead of lease_seconds; it must be strictly later than the store observation time. Supplying both remains an error, with no inferred precedence or silent argument removal. Wall-clock expiry does not mutate a claim. A trusted observer, normally a Schedule-owned sweep, asks WorkGraph to validate the row and atomically commit release plus the lease_expired fact.

Evidence Refs

WorkEvidenceRef contains: Evidence refs are pointers. WorkGraph does not own the artifact content. Reserved confirmation classifications cannot be minted by generic workgraph_add_evidence calls.

Withdrawing Evidence

Evidence is append-only: nothing edits or removes a ref. To withdraw earlier evidence, add a new ref whose withdraws lists the ids of earlier refs on the same item. A ref is withdrawn when a later ref on the item lists its id. It stays in evidence_refs, so a reader marks it rather than dropping it; Rust hosts read the relation with WorkItem::is_evidence_withdrawn.
  • A withdrawal names only refs that come before it: earlier in evidence_refs, or earlier in the same create request. It never names its own id or another withdrawal. When several earlier refs share the id, it withdraws all of them. A ref added later with that id is not withdrawn, so adding evidence again reinstates it. Withdrawing an id again is allowed.
  • Confirmation evidence (a reserved confirmation kind or classification) and execution evidence (execution_binding_id set) cannot be withdrawn, and a withdrawing ref carries neither. A withdrawal therefore changes no completion-policy accounting and no execution binding: added to an item, it counts as one more evidence addition (refs given at creation are not counted).
  • Withdrawal needs no permission of its own. Whoever may add evidence to an item (on an attention-scoped surface, a projection with can_add_evidence) may withdraw its ordinary evidence, including evidence a host or another agent added. Refs carry no author, so a withdrawal records that a later ref declares the evidence withdrawn, not that its author retracted it.
  • A refused withdrawal is an invalid-input error and writes nothing.
  • A ref without withdrawals keeps the encoding it had before the field existed. A release before 0.9.9 reads items with withdrawals but ignores the field, and drops it when it rewrites the item (any mutation of the item, including a host sweep such as a lease-expiry observation); the withdrawing refs then remain as ordinary evidence. The upgrade guide lists the effects on keyed-create replays and attention continuation keys.

Events And Durable Facts

WorkGraphEventKind is one of created, updated, readiness_observed, claimed, released, blocked, closed, linked, evidence_added, attention_created, attention_updated, execution_bound, or execution_transitioned. An event may carry typed facts committed with the same mutation: These are ledger facts, not wake instructions. WorkGraph owns no timer. Snapshots are single-namespace atomic observations containing captured store time, event high-water mark, bounded items, included edges/attention bindings, and machine-derived ready_item_ids.

Goal Attention Bindings

An attention binding targets a session or a lowered owner. Its mode is one of pursue, coordinate, review, falsify, judge, or observe. Its status is active, paused, superseded, or stopped; only the last two are terminal. Delegated authority is one of add_evidence, close_own_review_item, request_closure, or close_if_policy_allows. The active projection also carries bounded item/parent context and its exact binding and item revisions. Reassignment and policy escalation require that current projection.

Flow Execution Bindings

WorkExecutionBinding durably associates one item with one exact Mob Flow attempt. The lifecycle phases distinguish launch request, uncertain launch, running, evidence projection, closure request, terminal Flow failure or cancellation, policy-refused closure, and successful WorkGraph closure. A retry may supersede only a terminal binding. The store enforces a single append-only retry chain with CAS machine revisions. A machine-derived, indexed recovery projection contains only nonterminal obligations, so host reconciliation does not scan or deserialize historical terminal bindings. The crash-safe launch sequence is binding commit, external-delivery begin, deterministic pending-run persistence, delivery realization claim, and Mob run start. realizing therefore implies that the exact run was already persisted. begun without a run is an abandonable uncertain launch. realizing without a run is quarantined as an invariant breach or legacy-corruption case. The WorkGraph bridge has no caller-asserted break-glass transition out of that state. It fails closed until the exact run is observed or a future sealed host authority is introduced. Every terminal Flow outcome creates evidence kind mob_flow_run_completed, mob_flow_run_failed, or mob_flow_run_canceled with the deterministic id work_execution:<binding_id>. Only completed-run evidence proceeds to a WorkGraph closure request. Exact evidence replay is a no-op; different content under the same evidence id fails closed. The typed execution_binding_id provenance is reserved to the execution bridge; the display id is never read as authority. If a completed run disappears before its evidence commits, the execution machine converts the attempt to a run-lost failure rather than closing the WorkGraph item without proof.

Public MCP

meerkat_mob_flow_status includes the corresponding redacted execution binding when the run was created by this bridge. Activation parameters, idempotency keys, correlation ids, and execution principals remain internal to the trusted realm host. The durable store journal retains full execution events for deterministic rebuild, but the general workgraph_events projection omits those event kinds. Public consumers observe execution through the redacted binding and Flow-status projections, so activation parameters and execution principals never cross the coarse WorkGraph event-read boundary. expected_item_revision is required when creating a new binding. An exact idempotent replay selects the existing binding even if later evidence changed the item revision. A changed effective Flow run configuration cannot be launched under an older binding digest.

Agent Tools

The last two tools are injected only when a turn carries a matching active attention projection. Their arguments cannot manufacture delegated authority.

RPC

General WorkGraph item mutation remains tool-owned. Attention reassignment and policy escalation are authority-bearing WorkGraph tool operations injected into turns with active attention, not public RPC methods.

REST

The GET routes use query parameters such as realm_id, namespace, all_namespaces, statuses, labels, include_terminal, limit, cursor for items, ready and snapshot, and after_seq for events. The POST /workgraph/goal/status and POST /workgraph/attention/list routes accept JSON request bodies. all_namespaces remains present in generic filter wire shapes and CLI syntax, but the standard public services hold one namespace grant and reject it. A future/bespoke host needs a separate explicit multi-namespace capability; a namespace grant never implies one.

Filter Semantics

The same filter fields drive the workgraph_list, workgraph_ready, workgraph_snapshot, and workgraph_events tools, the workgraph/* RPC methods, the REST query parameters, and the CLI flags. Their meaning is the same everywhere: Results report their cut. The list, ready, and snapshot results of the tools, RPC methods, REST routes, and rkat workgraph with --json carry total_items, the items that matched before the cursor and limit cut them (for ready, the ready items), and truncated, true when matching items exist after the last one returned. A page that ended early names a next_cursor (present exactly when truncated is true, except on a limit: 0 page) to pass back as cursor. Every page also reports anchor_event_seq, the event ledger’s high-water mark when the walk began (read before the first page’s rows; a snapshot uses its own event_high_water_mark), and changed_since_anchor, true when the ledger has moved past it. Events results carry truncated, next_after_seq (the last returned seq, present exactly when truncated is true) and the ledger’s event_high_water_mark. A result without these fields comes from an older server and may still have been cut. Walking every page. A continuation returns the rows strictly after the cursor’s order key, so rows never shift between pages:
  • An item that does not change during the walk is on exactly one page.
  • An item that changes during the walk is on at most one list or snapshot page: a write moves it ahead of the cursor. It can repeat only when a write gives it an updated_at older than the one it had (the store clock moved back). In ready, an item whose priority changes can cross the cursor either way, and one whose readiness changes during the walk can be missing. A reader that dedupes by id and keeps the higher revision is safe.
  • An item changed or created after the anchor can be missing from later pages. Those pages say changed_since_anchor: true, and events with after_seq set to anchor_event_seq name every such item. Execution-binding events also move the ledger, so the flag can be true with no public change. The flag covers writes only: readiness that arrives by time passing (not_before, snoozed_until) writes no event and is not flagged.
  • A first snapshot page holds the edges between its own items; a continuation adds the edges from its items to the items at or before the cursor, so a walk sees every edge between the items it returned once.
ready and snapshot read one observation of the whole namespace and classify readiness against all of it, however many items, edges, and attention bindings it holds: an item a snapshot returns is not ready while a blocker the cut left out is unresolved. Terminal items (completed, cancelled, failed) are never ready again; they still resolve blockers and child joins, and are returned with include_terminal. Every list, ready, and snapshot call reads the whole namespace, closed history included, so its cost grows with the namespace, and a walk of several pages reads it once per page. A trusted in-process Rust caller that needs the whole selection in one consistent read, such as live delegation scheduling, uses WorkGraphService::snapshot_uncut: one observation with every item a snapshot filter selects, with no limit cut and no cursor (it ignores both). No tool, RPC method, REST route or CLI command offers it; they keep the bounded pages. Scope long-lived work across deliberately scoped realms or namespaces issued by an embedding Rust host. A caller-supplied namespace string cannot widen the service’s grant; there is no item-delete, namespace-rename, or graph-compaction API. Items and edges are never deleted. No tool, RPC method, REST route, or CLI command unlinks an edge or removes an item; only the trusted attention prune deletes rows. Close an item that should leave live views as cancelled, and replace one with a supersedes edge from the successor (from_id) to the superseded item (to_id).

CLI

CLI commands use the same realm flags as other rkat commands. On standard surfaces, select the granted namespace (normally default) and do not pass --all-namespaces.

Companion Skill

workgraph-workflow is an embedded builtin companion skill gated by the work_graph capability. It teaches agents how to use the WorkGraph tool family. Mob members whose profile sets tools.workgraph = true receive it preloaded; on other surfaces it is discoverable through the normal skills inventory and is not automatically preloaded.