Skip to content

Part I · Concepts / Ch. 16

Chapter 16: When There Is More Than One Route — Workflow & Graph ​

Xia A and Lao Z look over a miniature garden with a straight stepping-stone path, branching trails, a fenced loop, and a glowing checkpoint.

Xiao A had recently come across three things at once: the Agent loop he was writing himself, an "approval flow" a colleague owned, and an article about "graph orchestration". A little panicked, he took his coffee and went to find Lao Z.

"Do I have to pick one of these three, and is it over if I pick wrong?" he asked.

"Hold on. Retrieval decides what material comes along; it does not answer who decides the next step," Lao Z said. "The three things you are looking at — the loop, the workflow, and the graph — are not rivals waiting for you to choose one. They are three different arrangements of control and state. Work out what each one governs, and you will naturally know how to use it."

This chapter compares Loop, Workflow, and Graph. It commits to no particular framework, and it does not mistake a graphical representation for a reliability guarantee.

Aligning the Names First ​

TermFull English name or abbreviationWorking definition in this bookWhat it is not
Agent loopAgent Loopbounded iteration driven by model output and tool resultsunbounded autonomous execution
workflow / graphWorkflow / Graphfixed steps / nodes and edges with routing expressedtwo strictly mutually exclusive categories
state machinestate machinean explicit model of states, events, and transition conditionsjust drawing a flowchart
checkpoint / replay / idempotencycheckpoint / replay / idempotencythe contracts for saving a recovery point, executing again, and avoiding repeated side effectsautomatic transactional guarantees

Three Arrangements of Control ​

"So who exactly decides the next step?" Xiao A asked.

"Look at this table and the question becomes clear. The key is who decides the next step:"

FormWho mainly decides the next stepThe boundary it fits
Loopthe runtime iterates on model output and stop conditionsexploratory tasks, which must carry a budget and an abort
Workflowthe developer fixes the steps up frontapprovals, ETL, predictable business processes
Graphnodes and edges define the reachable routes, conditions pick the branchmulti-path, recoverable state flows

"And the stop conditions — who is responsible for each form's stop?" Xiao A pressed.

"That is the part people overlook most easily," Lao Z said. "A Loop's stop condition must be given explicitly by the host: turn count, tokens, cost, or timeout. The model is not responsible for hitting the brakes. A Workflow ends at a defined terminal node — walk into it and you stop. A Graph stops when a node has no outgoing edge or a termination condition is met. Whichever form you choose, you have to be able to answer 'when does it stop, and what state is left when it does'. Otherwise recovery and auditing are out of the question."

"Is a Graph necessarily more advanced than a Workflow?" Xiao A asked.

"No. A Graph need not contain a model, and a Workflow can contain branches. The difference between them is in how they express things and how they manage state, not two mutually exclusive categories: a Workflow lays its steps out in order, a Graph draws branches explicitly as nodes and edges. The same business logic fits either one. The difference only shows up in what you touch when you change one branch: in a Workflow you edit the step definition, in a Graph you edit the routing condition."

"What if I pick the wrong form at the start — can I switch later?"

"You can, at different costs," Lao Z said. "Going from a Workflow to a Graph usually just means rewriting the fixed steps as nodes and transitions. Going from a Graph to a Loop hands the routing authority from your code to the model, so the stop conditions and guardrails all have to be redesigned. The work of switching forms goes almost entirely into moving the routing authority from one side to the other. So ask before you start: how fixed is the path in this task, really?"

"Whether the path is fixed — I read that as whether all the branches can be written out in advance?" Xiao A jumped in.

"Right. It is exactly whether the branches can be enumerated ahead of time," Lao Z said. "'Retry on failure, ask for missing material, finish when done' — if every outcome is written out clearly, the path is fixed, and a Workflow expresses it well enough. When the branches are numerous and the conditions themselves are only known at runtime, the path is not fixed. That is when a Graph or a Loop earns its place. What you are judging is whether the branches are predictable, not whether the task is complex."

"Can we line up a few common tasks against that?"

"Sure. Here are a few common tasks side by side:"

TaskAre the branches predictable?Fitting form
form approval (pass / return / reject)yesWorkflow
release process (check → approve → deploy → verify)mostlyWorkflow / Graph
support tickets (route by type, then follow up on reply quality)partlyGraph + bounded Loop
exploring a new feature (generate options → verify → iterate)noLoop + human confirmation

"By that table, the same person can use all three forms at the same time?"

"Exactly. Different tasks inside one team often do use all three at once," Lao Z said. "Rather than sticking a 'form label' on every task, record clearly who holds the routing authority for each one."

Metaphor: the route map

A Workflow is a subway on a fixed schedule, a Graph is a map with transfers, a Loop is a taxi with no fixed route. None is better; it only depends on where you want to go.

The Engineering Profile of Each Form ​

"Beyond 'who decides the next step', is there any real engineering difference between the three?" Xiao A asked.

"There is, and the form choice usually hides it," Lao Z said. "Put observability, cost, failure recovery, testing, and debugging side by side and the differences are plain:"

DimensionLoopWorkflowGraph
Observabilityeach turn's events can be logged, but the next step is not knownsteps are known in advance, progress at a glancenodes and edges are visible, the current position is queryable
Costevery iteration incurs a model callfixed steps, cost estimablemore branches, more test combinations
Failure recoveryresume from the stop reason; intermediate state may be lostreplay from the failed step, needs idempotencyresume from a checkpoint; the path can be rebuilt
Testingneeds many boundary input sampleseach path tested separatelyeach node transition tested separately
Debuggingthe problem may be buried in a model decisionthe problem localises to a specific stepthe problem localises to a specific node

"Just from the testing row, the three have completely different things to prove?"

"Completely different," Lao Z said. "A Loop can go wrong at any model decision, so its exam is the stop condition and the boundary inputs — you need samples that cover 'did it stop when it should have'. A Workflow's exam is each fixed path: input A takes 1, 2, 3; input B takes 1, 2, 4; a path walked wrongly means a definition written wrongly. A Graph's exam is the transition conditions: from the same node, which edge to take when the condition holds, and which edge when it does not. One more thing — the number of test combinations is itself a hidden cost you pay when choosing a form."

"Is there a common pattern of building one form first and switching later?"

"Yes, and it is very common," Lao Z said. "Most systems start as a Workflow: fixed paths, testable, cost controllable. Only when task complexity climbs and the branches stop being enumerable do you turn parts of it into a Graph or a Loop. The direction of travel is usually from the deterministic toward the flexible; the reverse is rare, because the cost and the auditability the deterministic parts save you are precious assets you should not drop lightly."

State, Routing, and Recovery ​

"Whatever shape you draw it in, what should engineering actually care about?"

"Five questions: what the current state is, who may change it, where the branch conditions come from, where you recover after a failure, and whether the action is idempotent." Lao Z drew a simplified schema:

text
receive request → validate → [enough data?] ─no→ request material → validate
                                  │yes
                                  ↓
                            execute task → record result

"Why are those five questions questions about 'state' rather than about 'shape'?"

"Because the diagram is for people to read; the state is for the program to use," Lao Z said. "You can draw the same process any way you like, but the state has to land somewhere persistable — a database, a file, an in-memory object. Otherwise one process restart and the flow no longer knows where it got to. To judge whether an orchestration design is reliable, don't check whether the diagram is right; check whether each of those five questions has a place where it actually lands."

"What engineering part does each of the five questions correspond to?"

"One to one." Lao Z laid the five questions out as a table:

State questionThe engineering part behind itWhat it looks like when missing
where the state livespersistent storage (database / file / memory)the flow is lost after a process restart
who may change itwrite-permission controlseveral processes mutate the same state concurrently
where conditions come fromthe branch logic (rules / model / external input)the wrong branch is taken and cannot be traced back
where you recover fromcheckpoint + a recovery entry pointafter a failure you can only start over
is re-running idempotentidempotency key / de-duplication logicside effects repeat after a replay

"That table is the checklist for whether an orchestration implementation is complete," Lao Z said. "Only when all five questions have an answer does the implementation close the loop. A question you cannot answer names the failure point: not that it might go wrong there, but that when it does, you have no means in hand to deal with it."

"What if the 'execute task' node in the diagram dies?"

"If 'execute task' writes to an external system, you cannot simply re-run it on recovery — record an idempotency key, or use a compensating action," Lao Z said. "The diagram draws the route; it does not automatically solve duplicate writes, racing updates, or model misclassification. Concretely: one node does 'create order' and writes to an external system, and the process crashes before the local checkpoint is written back. On replay, with no idempotency key, you get a second order; with the key, the external system recognises it as the same call."

"What is a compensating action?"

"Compensation is the action that 'gives back' a side effect that already happened: an order created, so you send a cancellation; an email sent, so you issue a retraction notice. But compensation is not rollback. The external system may already have executed, may have executed halfway, or may never have received the request at all. Compensation can only converge as best it can; it cannot guarantee you get back to the state before execution. So the design order is always: define idempotency first, then talk about compensation."

"Then does more uncertainty mean you must use a Loop?"

"Not necessarily. You can fence the uncertain part inside one node and keep the outer layer a deterministic workflow, so approvals, permissions, and delivery stay protected," Lao Z said. "The choice turns on predictability, the cost of failure, and observability — not on which one is smarter. For a fixed process whose failure is very expensive, even when a model takes part, you would rather lock the model's decisioning inside one budgeted node than let the whole process improvise."

"The system is already running. If I want to evolve it toward flexibility, where is the safest place to start?"

"Start with a local replacement," Lao Z said. "Don't overturn the whole Workflow. Pick one branch point and change its fixed decision into a budget-limited model decision. For example, where it used to say 'exceptions split into three fixed categories', make it 'the model classifies the exception first, then the original branches apply'. Replace one point at a time and leave the rest of the structure alone; the replacement point needs its own budget, stop condition, and fallback path."

Evolution moveRiskMitigation
swap one Workflow step for a model decisionthe model's judgement is unstableconstrain inputs and outputs, give a budget, set a fallback
turn fixed branches into Graph routingrouting conditions not fully testedkeep the original branches as a fallback first
allow free improvisation inside a nodethe node runs awaycap the turns, force a stop, keep human confirmation as the backstop
replace the whole process with a Loopyou lose auditabilityalmost never taken; usually only local replacements

"And the reverse? Too many model decisions and I want to take them back."

"Going backwards is simpler," Lao Z said. "Put a rule check in front of the model's output first; anything that fails the check returns to the fixed branch. Once the rules cover enough ground, remove the model decision entirely. Retreating from flexibility to determinism works by rules replacing the model step by step, and every step needs data showing the rules reach the quality of the model's judgement. You cannot cut by feel."

Key point

The reliability of orchestration comes from the answers to the five state questions, not from the flowchart itself: where the state lives, who may change it, where the conditions come from, where you recover from, and whether re-running is idempotent.

Hybrid Orchestration ​

"So can I mix the three?"

"You can, and it is common," Lao Z said. "One usual combination: deterministic routing picks the task type first, then the open-ended analysis goes to a Loop with a bounded number of turns. Or a graph node calls retrieval, tools, and models. Every layer needs its own input and output schema, timeout, budget, and audit events. Disguising one large Loop as a 'node' without exposing those boundaries only makes recovery and testing harder."

"So what gets mixed is the form; not one boundary may get mixed?"

"Right. Boundaries are exactly what you look for," Lao Z said. "Every segment of a hybrid orchestration has explicit inputs and outputs, a budget, and a stop condition. 'No orchestration' is the whole process smeared together — no segments and no boundaries. The test is simple: can you point at a segment and say 'this part runs at most 5 turns', 'this part has human confirmation', 'this part takes a fixed branch'? If yes, it is hybrid orchestration. If not, it is a mess."

TraitHybrid orchestrationMuddled orchestration
segment boundarieseach segment has an input/output contractsegment responsibilities are fuzzy
budgeteach segment has its own turn/token limitno budget anywhere
stop conditionseach segment has an explicit stop reasondepends on the model behaving itself
auditeach segment has event logsonly the final result
recoveryeach segment can resume from a checkpointa break means starting over

"Isn't the maintenance cost higher than a single form?"

"It is — but higher where the higher cost pays off," Lao Z said. "What you maintain is no longer the logic of one form but the contracts of several segments, the switch points between them, and each one's recovery strategy. The cost is real. The return is that every segment is expressed in the form that suits it, and every segment can be tested on its own. If a segment's complexity does not justify maintaining it separately, do not open a new form for it. Most systems get by with one or two forms; a third is bought with extra complexity and cost."

"Draw me a hybrid structure?"

"Sure. Here is a simplified sketch:"

text
entry router (deterministic) ─── task type A → fixed approval flow (Workflow)
                             └── task type B → bounded investigation node (Loop, at most 5 turns)
                                                      ↓
                                        graph orchestration: pick a branch from the findings
                                                      ↓
                                        human confirmation (required)

"In this structure each form owns one segment," Lao Z said. "The entry router and the approval flow are the deterministic parts; they handle authorisation and delivery. The investigation node is a bounded Loop; it handles the open-ended analysis. The graph chooses the next step once the findings are in. Every boundary is explicit: the Loop has a turn cap, the Workflow has a human gate, the graph has definite branch conditions."

"Why not just hand the whole task to a Loop?"

"Because the costs differ," Lao Z said. "Every extra turn of a Loop buys one more model call, a little more context cost, and a little less predictability in behaviour. Express the deterministic parts in a deterministic form: cheap and auditable. Give the model only the parts that genuinely need open judgement, and the budget goes where it counts. Hybrid orchestration, said plainly, is drawing a finite box around the uncertainty."

"So where should that box be drawn?"

"Wherever a failure would get amplified," Lao Z said. "Approvals, payments, permission changes — those fail expensively and irreversibly, so they belong inside the deterministic workflow, backed by human gates and auditing. Open-ended analysis, information gathering, generating options — those fail cheaply and can be retried, so they belong inside a bounded Loop. The measure is how much damage a failure here causes and whether it can be redone, not whether a model should be used here."

"Within one task, does the order of the deterministic and the open parts matter?"

"It does, and the shape is usually fixed: deterministic outside, open inside," Lao Z said. "The entry uses a deterministic router to split the traffic, the middle uses a bounded Loop to analyse, the exit returns to a deterministic process to close things out — the approval and the write-back happen in that last segment. The reverse, an open outer layer with a deterministic inner one, is rare: that lets the model decide the skeleton of the whole process, and the deterministic parts end up as the model's execution details."

Recovery Points Belong to State, Not to the Diagram ​

"Why do you say recovery points belong to state and not to the diagram?"

"Because a recovery point has to be readable back by the program. Drawing it on the diagram does not count," Lao Z said. "Take an expense-report process: 'generate draft' can be re-run safely; 'submit the report' must first check an idempotency key, or hand off to a human. Loop, Workflow, and Graph can be mixed: a deterministic workflow handles authorisation and delivery, the graph handles branching, and a turn-limited Loop handles only the open-ended analysis. You give up a little flexibility and buy a control plane that can be recovered and tested."

"Then what exactly does a node's definition have to spell out?"

"Check four things," Lao Z said,

The four definitions of a node

  1. Input: what data the node needs to start, and what happens when something is missing
  2. Output: the result the node produces on success, for downstream to consume
  3. Commit point: where the side effect lands — re-runnable before it, idempotent after it
  4. Idempotency strategy: what makes running twice different from running once — an idempotency key, querying external state, or handing off to a human

"The most common mistake is drawing the recovery point in the diagram while keeping it only in your head," Lao Z said. "The diagram says 'submitted', but the program has no field for it — one process restart and it is as good as never submitted. The recovery point has to be read out of persistable state, and that diagram cannot do it for you."

Design Recovery Before Side Effects ​

"Is there one view that covers all three forms?"

"There is. All three land on a state machine: states, events, transition conditions, plus a persistable checkpoint," Lao Z said. "A Workflow usually writes its transitions as ordered steps; a Graph records nodes and edges explicitly; a Loop delegates 'the next step' partly to the model, but a turn budget and a stop state are still mandatory. The difference is who owns the routing authority, not whether it can be drawn as a graph."

"How exactly are a state machine's states and transitions defined?"

"A state is 'where the process is right now'; a transition is 'what event happens and what condition holds for it to move from here to there'," Lao Z said. "Take the expense-report process; a minimal state machine looks like this:"

text
draft ──(submit)→ submitted ──(approve)→ approved ──(pay out)→ paid
                     │                        │
                     └──(return)→ draft    └──(reject)→ rejected
StateMeaningAllowed transitionsEvent that triggers them
draftdraft, editable→ submittedthe user submits
submittedsubmitted, awaiting approval→ draft / approvedreturned / approved
approvedapproved→ paid / rejectedpayment made / approval denied
paidpaid, terminal statenone—
rejectedrejected, terminal statenone—

"The value of defining a state machine is that illegal transitions become visible," Lao Z said. "A ticket that is already 'paid' should never go back to 'draft'. The state machine has no such transition, so the code cannot take it even if it wanted to. Without a state machine, you avoid those illegal states by developer self-discipline. Miss one, and your data keeps a record that is 'paid but still awaiting approval'."

"Then a state machine and a graph are the same thing?"

"They are not," Lao Z said. "A state machine emphasises the legality of states and transitions — which transitions are allowed. A graph emphasises the expressiveness of nodes and paths — which paths are reachable. The same business can carry both views at once: use the graph to express the routing structure, use the state machine to constrain transition legality. They are two complementary check surfaces, not substitutes for each other."

"Give me one worked example?"

"Take creating a release ticket as the running example," Lao Z said. "Checkpoint 'validation done' first, then make one external create call carrying an idempotency key. On replay, read the checkpoint and the key; never create again blindly. There are three failure paths. One, the process crashes after the write — recovery has to query external state. Two, the model routes wrongly — the Graph should send it to a human or to a safe terminal. Three, the checkpoint was never written — you must test that risk together with the order of the side effects. Hybrid orchestration can wrap the fixed approval in the outer layer and put a bounded investigation Loop inside a node, but a node that uses a model does not thereby get to give up its replay, audit, and recovery contracts."

"Those failures — how does each one recover?"

"Sort them by whether the side effect has already landed," Lao Z said,

Failure positionSide-effect stateRecoveryCounter-example
before the checkpoint writeno side effectre-run the current nodeif the node itself writes externally, it still needs idempotency
after the checkpoint writethe side effect has landedreplay from the checkpoint, de-duplicate with the idempotency keyno idempotency key → duplicate writes
the external system already executedinvisible to youquery external state, use the idempotency key, or hand off to a humanblind resend → duplicate orders
model routing errorthe wrong branch was takensend to a human or a safe terminallet the model self-correct → it may route wrong again

"The counter-example column is the important one," Lao Z said. "Every recovery method has an assumed-safe version that goes wrong: replaying because you assumed replay was safe, resending because you assumed resending was harmless. Recovery design lists 'how this goes wrong' first, then picks the recovery method — not the other way around, writing the recovery code and praying nothing happens."

The Gap Between the Diagram and the Implementation ​

"I noticed something: a lot of flowcharts look great, but the code does not match them."

"That is the trap Workflow and Graph make you step into most easily," Lao Z said. "The diagram is for people; the implementation runs the machine. Nothing guarantees the two stay consistent. When drawing, people naturally leave out error handling, timeouts, and idempotency, because a diagram shows the main path. The implementation cannot leave them out: every node has to handle failure, and every edge needs somewhere to go when it fails."

"Then what is the diagram actually for?"

"As a starting point for communication and design, not as the end point of acceptance," Lao Z said. "A diagram's value is that everyone in the discussion sees what the main path looks like, who decides the next step, and where the human gates are. But a correct diagram is not a correct implementation; whether implementation and diagram agree is checked by tests. 'The diagram says so' proves nothing."

Diagram layerImplementation layerTypical gap
nodefunction / service / subprocessthe node does more in code than on the diagram (hidden side effects)
edgefunction call / message / routeone edge on the diagram may be retries, degradation, and timeouts in code
branch conditionif / switch / routing rulethe diamond on the diagram may be several nested checks in code
terminationreturn / exit / exceptionthe exception paths the diagram omits must be drawn in the implementation

"Can the gap be narrowed?"

"Two ways," Lao Z said. "One, annotate the non-main paths on the diagram: use dashed lines or notes to mark where timeouts, failures, and human intervention lead, so the boundaries show up while you discuss. Two, check the diagram against the implementation: once the code is written, back-fill each node's actual behaviour into the diagram and see whether the diagram's promises match the code's implementation. The gap cannot be eliminated, but it can be made explicit. What is stated in the open is a known boundary; what is hidden becomes a failure nobody defends."

"Can the diagram express a node where a model is involved?"

"It can express 'this node calls a model'. It cannot express 'how the model will decide'," Lao Z said. "For a model node, what you can draw is its inputs, outputs, and stop condition — not its decisions. So annotate model nodes with particular care: draw the boundary, not the behaviour. The boundary is the budget, the stop condition, the input/output contract. The behaviour is what the model decides inside that boundary; you cannot draw it, and you should not pretend you can."

Common Orchestration Anti-patterns ​

"Are there orchestration designs that look reasonable and then actually crash?"

"Three typical kinds," Lao Z said,

Three orchestration anti-patterns

  1. Squeezing the whole task into one big Loop and pretending it is a node: nothing outside can see its internal state, and the budget, the turns, and the stop reason are all hidden, so recovery and auditing have nowhere to start
  2. Letting a graph node improvise freely with a model and no budget at all: the graph only guarantees routing determinism, not that the node's interior stays under control
  3. Treating every model call as replayable: model calls are probabilistic, so a replay yields a different result; they cannot be re-run as safely as deterministic computation

"What do these three anti-patterns have in common?"

"All three mistake one layer's constraint for the whole system's guarantee," Lao Z said. "A Loop having a stop condition does not make the whole process safe. A Graph having routing does not stop a node from running away. A replay having an idempotency key does not make every node idempotent. Each layer guarantees only its own boundary. Assumptions that cross layers must be declared explicitly and verified explicitly."

"When you design orchestration, where should you start thinking?"

"Start from the worst case," Lao Z said. "Ask first: 'what is the most expensive failure of this process' — a double charge, a wrong notification, a wrong document generated. Then reason backwards from the most expensive failure: which layer does it happen in, what stops it there, and what happens if nothing stops it. Write the worst case down, then choose the form. The form is just where that thinking lands."

"To close this out: how do I know I have thought the orchestration through?" Xiao A asked.

"When you can answer three questions at once," Lao Z said. "Who holds the routing authority at each step — code or model? What are each node's budget and stop condition, so it cannot spin forever? After each failure, where do you recover from, and do side effects repeat? With all three answered, whichever form you choose stands up. Miss one, and however right the form looks, it collapses in some corner."

Summary ​

Loop, Workflow, and Graph are three tools for expressing control and state. They are not mutually exclusive, and you choose among them by how fixed the path is. An Agent Loop hands control to the model, letting it decide the next step for itself at every point, which suits open-ended problems whose path cannot be fixed in advance. A Workflow pins the path down: what each step does, in what order, and what condition must hold before it proceeds — all written in the definition — which suits processes where mistakes are costly and you need auditability and replay. A Graph sits in between, expressing the possible branches with nodes and edges: it allows conditional routing while keeping the overall structure observable. Their engineering profiles differ sharply — observability, cost, failure recovery, and test combinations are all different — and when choosing a form these hidden costs usually matter more than the name of the form.

Checkpoints and replay are the companion capabilities of Workflow and Graph: saving a recovery point lets the process stop and continue afterwards, and replay requires every step to be idempotent, otherwise an interrupted re-run charges twice. Recovery splits four ways by whether the side effect has already landed: re-run before the checkpoint, de-duplicate with the idempotency key after it, query external state or hand off to a human when the outside world already acted, and send to a human or a safe terminal when the model took the wrong branch. All three forms land on a state machine — states, events, transition conditions, and a persistable checkpoint. The state machine's value is that illegal transitions become visible, and the graph and the state machine are two complementary check surfaces, not replacements for each other.

Hybrid orchestration is the norm: a deterministic router splits the traffic at the entry, a bounded Loop analyses in the middle, and a deterministic process closes things out at the exit, with every open node carrying its own budget and stop condition. The three common anti-patterns are squeezing the whole task into one big Loop and pretending it is a node, letting a graph node improvise with a model and no budget, and treating every model call as safely replayable. What they share is mistaking one layer's constraint for the whole system's guarantee: each layer guarantees only its own boundary, and cross-layer assumptions must be declared and verified explicitly.

Hands-on Verification ​

  1. Draw an expense-report process as nodes, states, and conditions, and mark an idempotency strategy for every external write.
  2. Change one of its open-ended "explain the anomaly" nodes into a Loop of at most three turns, and define the stop reasons.
  3. Inject one timeout and one duplicate delivery, and verify that the process recovers and does not submit twice.