← All writing

Technical essay · Agent systems

the state machine beneath graph engineering

A task graph shows what work may happen next. The state-transition graph beneath it determines what the system is allowed to believe after that work runs.

I became suspicious of “loop engineering” and then “graph engineering” because much of the discourse sounded like machinery we already had names for.

An agent receives some state, chooses an action, observes the result, and decides what can happen next. It may retry, branch, ask for help, or terminate. Draw those possibilities and the workflow resembles a state machine. Repeat them and it resembles a traversal over that machine.

My first reading was that the new vocabulary was mostly a smoke screen: we were inserting a language model into one or more state transitions and presenting the result as an entirely new engineering discipline.

The similarity is real, but I was conflating two graphs that often look nearly identical on a whiteboard.

Every state machine has an implicit directed graph. Its vertices are system states. Its edges are permitted transitions, triggered by events and constrained by guards.

The graph commonly meant by “graph engineering” is usually a task or action graph. Its vertices are operations: inspect the repository, form a plan, edit the code, build the app, run a scenario, collect a trace. Its edges describe dependency, control flow, data flow, branching, fan-out, or joins.

One graph is primarily about what the system is allowed to become. The other is primarily about what work may happen next.

A task node can induce several state transitions, and one state transition can require several tasks. Their structures may overlap, but their semantics differ. That distinction matters once a workflow has to survive partial execution, tool failure, retries, missing evidence, and human intervention.

Figure 01

two graphs, one execution

Task / action graph

what work may happen next
inspectimplementvalidate
reportrepairretry infrastructure

State-transition graph

what the system may believe
plannedexecuting
acceptedrejectedevidence incomplete
validation produces factsguards authorize transitions
Tasks produce observations. Guards decide which state transition those observations permit.
Read the diagram description

The left panel is a task graph: inspect leads to implement, which leads to validate. Validation may route to report, repair, or retry.

The right panel is a state-transition graph: a planned run becomes executing, then reaches accepted, rejected, or evidence incomplete. The validation tasks produce facts; the state guards decide which transition those facts authorize.

Two graphs that are easy to conflate

Consider a graph node called validate change.

In a task graph, that node may expand into building the application, executing a user journey, and capturing evidence. Its outgoing edges may route to report success, repair implementation, retry infrastructure, or escalate.

The state-transition graph sits underneath that work. A run may move from planned to executing, then to evidence_incomplete, rejected, or accepted, depending on what execution establishes.

The task graph tells us which operations can produce the information needed to choose a transition. The state machine tells us which transition that information permits.

This does not require a hand-written finite-state machine with one enumerated state for every possible combination of facts. Real systems often use extended state: a named control state with variables such as platform, scenario version, attempt count, evidence health, and remaining budget. Hierarchical states can group related recovery behaviour without flattening everything into one transition table.

When I refer to the state machine beneath graph engineering, I mean this broader state discipline: explicit control states, guarded transitions, persistent context, and invariants. I do not mean that every exploratory thought produced by an agent should become a box in a formal FSM.

Four responsibilities inside one workflow

The diagrams used to explain agent workflows tend to compress four concerns.

A task graph describes the topology of work: dependencies, available paths, branches, parallel tasks, and joins. A mobile validation task may fan out across iOS and Android and join only when the required proof exists for both.

A state machine defines valid system evolution. It names control states, constrains transitions, and preserves invariants regardless of which worker or tool is active. It should prevent a partial profile from becoming a baseline because its command exited successfully.

A loop supplies recurrence. Intent leads to planning, action produces observations, and execution returns with a revised plan. The term says little about topology or transition rules; it says the process revisits work as information arrives.

The runtime or control plane interprets the other three. It selects an eligible task edge, invokes a tool, persists checkpoints, evaluates guards, enforces budgets, and decides whether execution should continue, recover, escalate, or stop.

One graph-shaped abstraction can appear to contain all four. A workflow can still have an elaborate task graph and almost no state discipline, leaving important facts buried inside prompts, temporary files, or human memory. The reverse is also possible: explicit states with every dependency, concurrent branch, and recovery path hidden inside one transition function.

Where this became concrete for me

I ran into this while building Agent Scenario Loop.

ASL began from a narrow problem. An agent could modify a mobile application, run automation, collect traces, and claim completion. The individual tools were capable. The weak point was the space between them.

A successful automation command did not tell me whether the intended journey occurred. A performance trace did not tell me whether it came from the correct platform, runtime, build, or complete scenario cycle. A screenshot could prove that a screen appeared without proving that the interaction recovered correctly or emitted the application-owned events required for trust.

Adding another runner would not resolve that. The system needed a durable behavioural contract and a control layer capable of interpreting evidence against it.

A scenario in ASL describes the behaviour that must survive: the journey, milestones, platform, application-owned truth events, evidence requirements, cycles, budgets, and required runner capabilities. The tooling can change. The behavioural claim should remain legible.

intent → plan → act → observe → establish evidence trust → judge → compare → adapt

Several of those stages are commonly collapsed.

Observation is treated as judgment: a tool emits output, so the model interprets it and moves on. Execution is treated as closure: a worker finishes, so its parent marks the task complete. Comparison begins before compatibility is established even though the runtime, scenario version, platform, or interval has changed.

Once those distinctions are explicit, the need for guarded state transitions becomes difficult to ignore.

Suppose an agent is asked to improve the transition from inline media to fullscreen playback. The task graph may include inspection, implementation, build, launch, scenario execution, trace collection, event verification, comparison, and report generation. It may branch by platform or send different evidence work to different providers.

The loop repeats when the result is insufficient. The agent may revise the implementation, replace an invalid assumption, gather a missing signal, or revert an attempted optimization.

The state machine carries the run’s control status. Did the correct scenario and cycle complete? Were required milestones present? Is the trace healthy? Is the baseline compatible? Has the retry budget been exhausted?

The control plane evaluates those facts as guards on the next transition.

If the automation process exits with zero but a required truth event is absent, the run executed, but it cannot transition to accepted. It may move to evidence_incomplete, followed by a diagnostic or retry task.

If the trace is healthy and the behaviour violates its budget, the run can support a negative verdict. That is different from an unhealthy run, where the system should withhold judgment.

If the available runner cannot provide a capability required by the scenario, the plan should be rejected before execution. Traversing more of the task graph cannot produce evidence that the environment was never capable of collecting.

The task graph may have no remaining nodes while the run remains unproved. Closure needs a valid terminal state such as accepted, rejected, blocked with an inspectable reason, exhausted under policy, or escalated.

Figure 02

execution can finish before the claim is trustworthy

  1. 01intent
  2. 02plan
  3. 03act
  4. 04observe
  5. 05establish evidence trust
  6. 06judge
  7. 07compare
  8. 08adapt
missing capabilityreplan
unhealthy evidencewithhold judgment
incompatible baselinedo not compare
authority or budget exhaustedescalate
Evidence health is a control decision, not an attachment added after the run.
Read the diagram description

The main sequence moves through intent, plan, act, observe, establish evidence trust, judge, compare, and adapt.

The evidence-trust gate can route away from judgment: a missing capability returns to planning, unhealthy evidence withholds judgment, an incompatible baseline blocks comparison, and an exhausted budget escalates. Only healthy, compatible evidence permits the system to continue toward an accepted claim.

Evidence as a transition guard

Most agent workflow diagrams attach evidence near the end as an output. In software work, the quality and provenance of that evidence have to constrain control flow.

Possessing an artifact does not automatically entitle the system to reason from it. A log may cover the wrong interval. A screenshot may come from the wrong build. A benchmark may be valid but incompatible with its baseline. A test may pass while bypassing the application-owned event that represents the behaviour.

ASL separates evidence health from behavioural verdict for this reason. Health asks whether the run produced material capable of supporting judgment. Verdict asks whether the observed behaviour satisfies the scenario. A healthy failure is useful. An unhealthy pass cannot authorize acceptance.

This separation also changes retry policy. A behavioural regression should not be retried until it happens to disappear. An infrastructure failure may justify a retry. A missing capability requires replanning. An ambiguous result may require additional instrumentation. The evidence condition guards each path so that retries do not gradually turn uncertainty into a convenient answer.

The useful baseline is not merely the most recent successful run. Its scenario, platform, runtime, build conditions, event anchors, and evidence contract must allow comparison. Compatibility should guard entry into that task.

The relevant evidence metadata may be stored in the machine’s extended state, but the artifact itself is not “the state.” Its health, provenance, and compatibility determine which transitions the runtime is allowed to take.

Authority as a transition constraint

Agent workflows often place human intervention outside the system as an escape hatch. That misses what escalation is doing.

Every actor operates within an authority boundary. One agent may edit application code but lack permission to weaken the scenario that will judge it. A device runner can execute actions but cannot declare product behaviour correct. An instrumentation provider can produce a trace but cannot decide whether the measured interval represents the intended journey. A control plane can enforce existing policy while still requiring a human to approve a new class of external side effect.

Identity, ownership, and granted capabilities constrain transitions. Escalation hands work to an actor authorized to take a transition the current actor cannot.

This prevents self-certification. If the same agent can change the implementation, redefine its contract, select a favourable baseline, and judge the result, the task graph may complete while the proof remains weak.

In ASL, the application remains the source of truth for scenarios, identifiers, commands, and behavioural events. The orchestration layer owns planning, runner integration, evidence transport, health checks, and comparison mechanics. Tooling can evolve without silently redefining success.

Authority context may be persisted alongside execution state, just as evidence metadata is. The important point is that authority is not another synonym for state. It is a constraint the control plane evaluates before allowing an actor to cause a consequential transition.

Why the task graph still matters

None of this makes the task graph decorative.

Real work has topology that is awkward to express as flat transition rules. Cross-platform proof can fan out. Investigations can run concurrently. Several providers may contribute to an evidence bundle. A join may require every mandatory artifact while tolerating absent optional evidence.

An extended or hierarchical state machine could encode these conditions. That does not mean the resulting representation would make dependencies, parallelism, and joins easy for a person to inspect. The task graph gives the work a visible shape without forcing every operation to become a top-level control state.

The constraint is that edge selection cannot be reduced to whatever the model decides sounds reasonable next. A model can propose a route through the task graph. The control plane still has to validate it against current state, available capabilities, policy, evidence requirements, and authority.

This matters even more when graphs are dynamic. A planning agent may generate a subgraph at runtime because the exact repair path was not known in advance. The task topology can remain flexible while consequential state transitions stay guarded. The system can discover new work without acquiring permission to violate its invariants.

What should survive tool churn

A particular execution graph may be short-lived. Tools change. Models improve. A runner disappears. A provider gains better instrumentation. Some branches become unnecessary while new platform-specific paths emerge.

The more durable assets are the behaviour contract and the evidence history showing how that behaviour changed under declared conditions.

Prompts, chat transcripts, and tool-specific workflows mainly preserve activity. Versioned scenarios, explicit invariants, healthy evidence, compatible baselines, and reasons for accepted transitions create operational memory.

New runners can be evaluated against existing requirements. A better model can inherit the same contract. Historical results remain intelligible because acceptance was tied to explicit conditions.

This is the direction I now see for ASL: a protocol and control plane for making bounded, inspectable claims about software behaviour while agents, tools, runtimes, and implementations change.

“Proving” needs care. A scenario does not prove universal correctness. It supports a bounded claim: under declared conditions, this behaviour occurred, required signals were present, evidence was healthy, and the verdict followed an inspectable policy. The claim still depends on the scenario, oracle, instrumentation, and environment.

There is no value in forcing an agent’s entire exploratory process into formal states. Exploration contains incomplete ideas and abandoned hypotheses. Formalizing all of it creates state explosion without adding trust. The useful boundary is where ambiguity becomes expensive: side effects, handoffs, evidence acceptance, retries, comparison, authority changes, and termination.

What I now mean by graph engineering

I still distrust graph engineering when the graph substitutes for an account of state, evidence, and policy. A diagram of calls between boxes does not explain what makes a transition valid, which facts survive a restart, how an unhealthy run differs from a behavioural failure, which history is comparable, who can change the definition of success, or why the system stopped.

I no longer think that makes the graph itself a smoke screen.

The directed graph implicit in the state machine represents permissible system evolution. The task graph represents the operations available to move the work forward. The loop revisits those operations as observations change the plan. The control plane connects them by evaluating guards, preserving context, enforcing authority, and deciding whether the evidence supports another transition.

That framing has made completion claims harder for my systems to make. A run should not be accepted because all visible nodes finished or an agent produced a convincing summary. It should leave the system in a valid terminal state under conditions we can inspect later.

That is the practical value I was missing when I first dismissed graph engineering as another name for state machines.