Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ActiveGraph-Inspired Runtime

yoagent-state is inspired by Yohei Nakajima’s ActiveGraph work, adapted into an idiomatic Rust runtime for yoagent and yoyo evolve.

The full concept is:

append-only event log
  -> deterministic replay
  -> typed graph projection
  -> pattern subscriptions
  -> behaviors
  -> policy-gated patches
  -> replay, fork, and diff
flowchart LR
  log["append-only event log"]
  replay["deterministic replay"]
  graphNode["typed graph projection"]
  patterns["pattern subscriptions"]
  behaviors["behaviors"]
  policies["policy gates"]
  forks["replay / fork / diff"]

  log --> replay --> graphNode --> patterns --> behaviors
  graphNode --> policies
  graphNode --> forks
  behaviors --> log
  policies --> log

What changed in v0.2

The core lineage path now starts from goals:

goal -> task -> run -> observation -> failure -> hypothesis -> patch -> artifact -> eval -> decision -> promotion
flowchart LR
  goal["goal"]
  task["task"]
  run["run"]
  observation["observation"]
  failure["failure"]
  hypothesis["hypothesis"]
  patch["patch"]
  artifact["artifact"]
  eval["eval"]
  decision["decision"]
  promoted["promoted status"]

  task -- serves --> goal
  run -- produces --> observation
  observation -- observes --> failure
  hypothesis -- explains --> failure
  patch -- addresses --> failure
  patch -- advances --> goal
  patch -- references --> artifact
  patch -- validated_by --> eval
  patch -- approved_by --> decision
  decision -- allows --> promoted

This is the common graph spine. It is not a claim that every agent run must create every node. artifact includes diffs, logs, screenshots, files, eval output, and other external evidence. promotion is represented by the patch lifecycle status.

yoagent-state now has first-class IDs and helpers for:

  • goals
  • tasks
  • runs
  • observations
  • hypotheses
  • evals
  • decisions
  • project snapshots
  • model calls
  • tool calls
  • frames
  • forks
  • behaviors
  • policies
  • packs
  • views

Runtime layers

YoAgentState remains the simple state API: record events, apply ops, query graph, query lineage.

YoAgentRuntime adds the ActiveGraph-inspired runtime layer:

  • register typed packs
  • validate typed nodes and relations
  • register behavior subscriptions
  • enforce policy gates
  • create approval requests

This keeps simple usage simple while allowing richer agent systems to use the full concept.

Extensible storage

The event log remains the source of truth.

Storage is split into traits:

  • EventStore
  • SnapshotStore
  • ForkStore
  • IndexStore
  • ArtifactStore

JSONL is implemented first because it is inspectable. SQLite, PostgreSQL, and graph-backed projections can be added later behind the same traits.

Behaviors

Behaviors subscribe to event patterns and return state ops.

They do not mutate the graph directly.

event -> matching behavior -> new events/state ops -> replayable state
flowchart LR
  event["failure.observed"]
  behavior["matching behavior"]
  task["create investigation task"]
  ops["state.ops_applied event"]
  graphNode["replayed graph"]

  event --> behavior --> task --> ops --> graphNode

This keeps behavior execution auditable.

Policies

Policies can allow, deny, or require approval for sensitive actions.

The current policy foundation supports approval requests for runtime operations. More policy surfaces can be added without changing the event-sourced model.

flowchart TB
  action["runtime action"]
  policy["policy check"]
  allow["allow"]
  deny["deny"]
  approval["approval request node"]

  action --> policy
  policy --> allow
  policy --> deny
  policy --> approval

Replay, fork, diff

Replay rebuilds graph state from events.

Fork creates an alternate event history from a parent event cutoff.

Diff compares projected graphs so agents can inspect what changed between histories.

flowchart LR
  events["events"]
  cutoff["event cutoff"]
  fork["fork graph"]
  current["current graph"]
  diff["graph diff"]

  events --> cutoff --> fork
  events --> current
  fork --> diff
  current --> diff