Core Mental Model
yoagent-state starts with three moving parts:
append events -> replay graph -> query lineage
flowchart LR
events["append-only events"]
replay["deterministic replay"]
graphNode["semantic graph projection"]
lineage["lineage queries"]
events --> replay --> graphNode --> lineage
The full runtime adds typed packs, behaviors, policies, replay, forks, frames, and views on top of that event-sourced base.
The graph is not the source of truth. It is a projection derived from append-only events.
Core graph shape
The current runtime is goal-centered. The common causal spine is:
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 -- produced_by --> task
run -- produces --> observation
observation -- observes --> failure
failure -- blocks --> goal
hypothesis -- explains --> failure
patch -- addresses --> failure
patch -- advances --> goal
patch -- references --> artifact
patch -- validated_by --> eval
patch -- approved_by --> decision
decision -- allows --> promoted
Read that as a graph shape, not a required pipeline:
goalcaptures the durable intent.taskis concrete work that serves a goal.run,model_call, andtool_callrecord execution.observation,failure, andhypothesispreserve what the agent noticed and believed.patchproposes a state or project change.artifactreferences concrete evidence such as diffs, logs, files, screenshots, or eval output.evalrecords validation.decisionrecords approval, rejection, or review state.- promotion is a
PatchStatus::Promotedtransition, not a separate graph node.
Side primitives such as policies, behaviors, packs, frames, forks, and views make this graph operational without changing the source-of-truth rule.
Event log
An event is an immutable fact about something that happened.
Examples:
run.startedtool.finishedgoal.createdtask.createdfailure.observedhypothesis.createdpatch.proposedpatch.status_changedartifact.attachedstate.ops_applied
Events are append-only. Do not mutate historical events.
State ops
State ops are the small mutation language for the graph projection.
They can:
- create or update nodes
- tombstone nodes
- create or delete relations
- mark nodes stale
- attach artifacts
Only state.ops_applied events mutate the graph directly.
Graph projection
The graph is a semantic view of agent state.
Common node kinds:
goaltaskrunobservationfailurehypothesispatchevaldecisionartifactfilemodel_calltool_callframe
Common relation kinds:
servesblocksadvancesobservesaddressesexplainsvalidated_byapproved_byrejected_bymodifiesreferencesproduced_bycontained_in_frameforked_from
The graph should stay lossy. It should preserve what matters for continuity and explanation, not every line of a log.
Patches
A state patch is a proposed semantic change with evidence.
It can include:
- base state version
- project reference
- preconditions
- expected effects
- evidence nodes
- artifact refs
- state ops
- lifecycle status
Patch lifecycle:
proposed -> applied_in_fork -> evaluated -> approved/rejected -> promoted
stateDiagram-v2
[*] --> Proposed
Proposed --> AppliedInFork
AppliedInFork --> Evaluated
Evaluated --> Approved
Evaluated --> Rejected
Approved --> Promoted
Proposed --> Stale
AppliedInFork --> Conflicted
Evaluated --> Stale
This lifecycle is one lane inside the larger goal-centered graph. A patch usually advances a goal, addresses a failure, references artifacts, is validated by evals, and is approved or rejected by decisions.
Artifacts
Artifacts point to external evidence such as:
- Git diffs
- commits
- files
- test output
- build logs
- eval result JSON
- model or tool output
Store paths, URIs, summaries, and hashes where practical.
Replay
On startup, the store scans events and replays them into the graph projection.
flowchart LR
store["EventStore"]
scan["scan events"]
projector["Projector"]
graphNode["Graph"]
store --> scan --> projector --> graphNode
This makes state durable without requiring a graph database.
Behaviors, policies, and packs
Typed packs validate object and relation shapes.
Behaviors react to event patterns and return state ops.
Policies gate sensitive actions by allowing, denying, or requiring approval.
flowchart TB
event["event"]
pack["typed pack validation"]
policy["policy gate"]
behavior["behavior subscription"]
ops["state ops"]
graphNode["graph projection"]
event --> pack --> policy
policy -- allow --> ops
policy -- require approval --> graphNode
event --> behavior --> ops
ops --> graphNode
These are runtime features, but they still preserve the same rule: durable state comes from append-only events.