Skip to content
andydataguy
Wiki Corpus

State Machine Everything. State machine transitions need a route for work that fails a check.

OPERATIONAL SYSTEMS · Definitive~54 min read · 12,692 words
Still from the hero animation. A directed workflow graph: intake to triage, a fan-out into draft and build that rejoins at review, a branch out to rework, and a dashed edge running backward from rework to triage before the flow continues through approve, stage, ship and done.
The drawing runs from intake through triage and a fan-out that rejoins at review, then approve, stage and ship. The edge that carries the weight runs backward from rework to triage, because it makes the return path explicit.

A change compiles, passes code review and gets merged. The page it was meant to fix is still wrong. Each person completed the job they were given, but nobody checked the result the customer would receive. A useful workflow has to name the evidence that permits work to move, who evaluates it and where the work goes when that evidence is missing.

That's the reason I use the vocabulary of graphs for operations. A graph gives a handoff a place in the model. The condition can be discussed before the work starts, evaluated against an actual result and changed when it proves inadequate. The same approach applies to an article, a software release or a proposal that needs another round of discovery.

LangGraph supplies a concrete engineering vocabulary for this. Its nodes perform work, its edges determine what runs next and its state carries the information those decisions use. The transferable part is the discipline of making those relationships explicit. You can use it on paper before deciding whether any software needs to execute it.

A handoff needs a shared definition of done

Each local check can pass while the result remains unverified

Consider the page change as an illustrative process. The implementer checks compilation and tests. The reviewer checks the diff against the brief. The person merging checks the branch status. Those checks may all be useful. None establishes that the deployed page contains the intended change or that someone has looked at it.

A long pipe made of three polished sections. A worker stands beside each section holding a lantern up to it, and each section gleams. Water drips from the two joints between the sections into a spreading puddle that none of the lanterns light.
The implementer, the reviewer and the merger each checked their own section and found it sound. The defect sat in the joints between them, where nobody's definition of done reached.

The team needs another condition at the appropriate transition. A release can move to live-verified only after someone opens the production page, confirms the relevant behavior and records which release they inspected. A missing deployment, a wrong route and an unchanged page produce different findings, but all leave that transition unsatisfied.

This distinction is explicit in my site's operating rules. They separate authored, wired, deployed and live-verified. Approved copy can exist in a document without being connected to the page. A connected change can exist in source without being deployed. A deployed page can still need inspection. Collapsing those states into one word, done, removes information the next person needs.

The graph makes the missing transition visible. It also exposes what each existing check establishes. The build remains a build check. The reviewer still reviews the diff. Neither has to pretend its evidence establishes something outside its scope.

A useful condition identifies an artifact and a question. Which URL, for which release, showing which behavior? A screenshot of an unrelated page answers none of those questions. A successful fetch proves reachability, while a rendered inspection can establish what appeared. The evidence has to match the failure you're trying to prevent.

Responsibility, sequence and permission answer different questions

An org chart identifies responsibility and authority. It helps answer who can resolve a conflict, approve a risk or supply a missing resource. Keep it for those jobs.

A checklist identifies a sequence and helps prevent omissions. It can also include decision rules, return instructions and evidence requirements. A well-written checklist may be all a process needs. The limitation appears when relationships multiply and readers have to reconstruct the routing from scattered sentences.

A staircase built from stacked sheets of paper. Between two of the steps there is only open air, and a small brass hook hangs in that gap gripping nothing while a hand reaches toward it.
A checklist can include transition conditions as well as steps.

A workflow graph puts those relationships in the foreground. It can show which work waits for which input, which branches may proceed separately, where their results meet and where rejected work returns. A reporting hierarchy doesn't normally try to express those relationships, because it describes people and authority rather than the path of an artifact.

Those are different models of the same operation. Calling the org chart wrong because it doesn't show a revision loop is like criticizing a staff directory for lacking acceptance criteria. The useful question is which relationship is currently implicit and causing a recurring problem.

A node named review still leaves that question unanswered. The label tells someone to review something. The transition out of review needs a rule about what the reviewer found and what their finding authorizes. Work returned for a missing source should arrive with that source gap named. Work accepted for staging should carry an acceptance record for the version actually reviewed.

A gate has to change what happens

Adding a requirement to a brief helps only if the people or software executing the process use it. Drawing a diamond on a diagram has the same limitation. Both can become unused documentation.

The practical test is what happens on failure. Suppose a draft contains an unsupported claim. Does the process return the affected passage to its author, route a missing fact to an authorized source owner or stop the release? If everyone can acknowledge the defect and continue along the same path, the condition hasn't constrained the transition.

A gate also needs an evaluator with the necessary access and authority. A reviewer who can't open the deployed page can't establish its rendered behavior. A sales team can't approve a buyer's description of their own problem on the buyer's behalf. The graph should show those dependencies instead of assigning impossible checks.

Every gate costs something. Someone has to collect evidence, evaluate it and handle the false branch. Put that cost where the consequence justifies it. A repeated public-facing defect may deserve an independent inspection. A reversible internal note may need only its author's read. Treating both identically creates stops that consume attention without protecting equivalent value.

The initial improvement can be small. Choose the handoff that repeatedly needs personal follow-up. Write the condition that would have exposed its last failure, then name a destination for work that doesn't meet it. Separate the transition condition from the work contract and the information they share.

Nodes define work, edges route it and state records what's known

A process becomes easier to inspect when each element has a separate job. The work unit describes what must happen. The transition describes when another unit may begin. Shared state records the inputs, outputs and decisions the process needs to carry forward.

These distinctions also prevent a diagram from becoming a renamed org chart. A box labeled marketing tells you a department is involved. A box that produces a campaign brief from approved research tells you what another participant can expect to receive.

A node has inputs, outputs and a failure condition

A node is a unit of work with a contract. The contract names what it receives, what it produces and what prevents it from producing an acceptable result. A person, a script or an agent can carry out that work.

Take a campaign brief. The node receives an intake record and buyer research. It produces a brief at a named location. Missing research sends the work to a blocked or research-needed state. The node shouldn't fill the gap by presenting a plausible buyer story as observed fact.

The contract remains useful if the occupant changes. A contractor can leave, another person can take over and the downstream writer can still expect the same kind of brief. Staffing is a separate question from whether the brief contains the information needed to write.

One long workbench with three stations, a drafting board, a press, and a packing bench, each occupied by a differently dressed worker in the same posture, all lit by the same warm lamps.
Three stations and three occupants share one drawing.

A competent stranger is a useful test reader for that contract. They should be able to identify the authoritative inputs, the required output and the limits of their permission. They may still have domain questions. The point is to expose the assumptions that only the current occupant knows, rather than demand a document that anticipates every possible question.

I describe the same input-and-output logic in my operational-systems work. Sales-call recordings become inputs to a review process, and reports become outputs for a salesperson and manager. Deciding whether to change coaching or staffing is a further decision. Calling the whole thing sales enablement hides those different contracts.

A node can also be too large. If its output is a completed project, its internal failures may be invisible to the rest of the process. Split it where another person needs a result, a different authority must decide or recovery needs a separate checkpoint. Splitting every keystroke only creates a more expensive description.

An edge names a permitted next step

An unconditional edge means work proceeds to the named destination without a routing choice at that point. That can be correct. A record may always need normalization before anyone evaluates it.

A conditional edge chooses among destinations using current state. In LangGraph's Graph API, add_conditional_edges attaches a routing function after a node. The function reads state and returns a destination, or a value mapped to a destination. The Graph API documentation permits routing to multiple nodes, so a routing decision needn't be limited to one next box.

The business form is plain. A proposal can proceed when qualification information is sufficient, return for clarification when an answer is missing or end in decline when the opportunity is outside scope. Those outcomes should be named before an ambiguous opportunity arrives.

Separate the decision rule from its authority. The person collecting answers may have permission to record them without permission to waive a qualification requirement. A router can apply the agreed rule; an exception can go to someone authorized to change it. An exception hidden inside an ordinary success path makes the history misleading.

A transition record should explain its own decision. Store the evidence used, the rule version and the evaluator. Otherwise a later reader sees approved and has to reconstruct what approval meant at the time. The graph gives that record a location, but someone still has to create it.

Each shared field needs an update rule

State holds what the graph knows at a particular point. An article process might carry a brief, research findings, an outline, a draft, review findings and a publication record. Nodes read the parts they need and return updates.

The ownership question becomes concrete at the field level. A reviewer can write findings without overwriting the draft. The author can apply those findings to the draft without rewriting what the reviewer observed. A publication step can record a release without silently converting an earlier editorial decision into a deployment claim.

An illustrative state contract makes those boundaries explicit:

Field Authorized writer Update rule
Draft body Article author Replace with a new identified revision
Review findings Assigned reviewer Add findings tied to a draft revision
Release record Publisher Record the deployed revision and its destination
Live inspection Release evaluator Add evidence for the release inspected

LangGraph makes the update question part of the schema through reducers. A reducer combines a field's current value with an update. The documented default replaces the current value. An explicitly chosen reducer can append results instead. Concurrent updates to a field that doesn't support them can raise an error rather than resolve by whichever write happens last. LangGraph documents this as INVALID_CONCURRENT_GRAPH_UPDATE. Its example has parallel nodes write the same field in one step, then uses an Annotated reducer to declare how those updates combine.

That behavior exposes an organizational decision software often leaves implicit. Sales and marketing can both have useful information about an account without both owning its lifecycle stage. Sales might own stage while marketing owns score. An automation can propose a transition without receiving permission to overwrite either field indiscriminately.

Single writer is a design rule for authority, not a claim that the library enforces a human role model. A reducer is a technical merge function, while an ownership policy governs who may propose an update at all. You need both when several participants share state.

A single track crosses a narrow bridge over a gorge. A locomotive enters from the left while its driver holds up a glowing brass hoop. At the far end a second, grey locomotive waits at a lowered signal arm with an empty-handed driver.
On a single-track line only the train carrying the token may enter, so two trains never meet. For a LangGraph state field without a reducer supporting concurrent updates, updates from multiple nodes in one step raise an error.

Appending everything is also a choice with costs. The resulting list needs attribution, identifiers and a way to distinguish a new finding from a duplicate. Replacing everything needs protection against stale updates. Choose the rule according to what the next node needs, then make its failure visible. The drawing can now describe work and information separately from the reporting structure around them.

A reporting hierarchy and a workflow graph describe different relationships

An assembly line, a checklist and a role hierarchy each solve a coordination problem. Repeated identical work benefits from stable stations. A sequence with costly omissions benefits from a list. Decisions that require authority benefit from a named escalation path. Those gains remain available after you draw a workflow graph.

Three flat structures side by side. The line, a conveyor carrying identical parts one way. The list, a checklist with four boxes ticked and one empty. The chain, three stacked boxes with a single escalation arrow pointing up. One thread runs behind all three and stops dead against a wall at the far end.
Each flat structure is correct for the failure it was built against. The workflow also needs to show where work returns.

The difficulty is using one structure to stand in for the others. A reporting line doesn't establish that legal review must finish before a release. A checklist's ordering doesn't establish that every adjacent item actually depends on its predecessor. The workflow model should describe those relationships directly.

Flash teams already represented work as linked tasks

Stanford's flash-team research is useful prior art because it makes the handoff explicit. The 2014 flash-teams paper describes linked modular tasks and handoffs that a computational system can manage. Its Foundry platform lets an author specify a task block's requirements, including input and output types and the expertise needed to perform it.

The arrows between blocks make dependencies visible. People upload intermediate work so another block can use it. The paper also describes pipelining intermediate output, rather than waiting for an entire upstream effort to finish before any downstream work can start.

That's already a graph-shaped representation of expert work. Treating it as a primitive checklist would erase the part most relevant to this method: declared handoffs let a system help coordinate people who haven't worked together before.

The later flash-organizations paper addresses work that can't be fully specified in advance. It describes roles, teams and hierarchies that can change as a project develops. Participants branch the organizational structure, propose changes and submit those changes for review up the hierarchy. Accepted changes can alter tasks, roles or the hierarchy itself.

The distinction is between a pre-specified workflow and an organization that can adapt its structure. It's broader than a choice between a tree and a backward arrow. The later system also supports task inputs and outputs, feedback and revision. Its use of hierarchy doesn't mean it lacks a workflow.

The authors' reported limitations matter here. They describe cases where fine-grained changes became less useful to track in Foundry and people coordinated directly instead. They also report workers wanting more planning and fewer adaptations. A system can make change explicit and still impose a cost people avoid when the representation is too detailed.

My design preference is to keep the workflow relationships explicit while assigning authority separately. The papers establish that both pre-specified handoffs and adaptable organizational structures are serious design choices. They don't establish that my preferred combination wins in every setting.

A tree can't carry every kind of work relationship

A simple reporting tree gives each non-root role one parent. The underlying tree has a unique path between any pair of nodes and contains no cycles. Those properties help explain why the same drawing is a poor place to describe every dependency an operation contains.

A revision from reviewer to author is a backward transition in a workflow. An integration step that needs outputs from several specialists is a join. Engineering's need for a legal decision is a dependency between two kinds of work. None is necessarily a change in who reports to whom.

People can coordinate all those relationships while working inside a hierarchy. Those relationships still need to be represented. If the actual dependency exists only in a message, the person planning the next run may never see it. If a join exists only in a recurring meeting, someone can remove the meeting without realizing what it was synchronizing.

Keep the reporting tree for authority. Draw the revision, the join and the legal dependency on the workflow. The two models can refer to the same people without forcing their edges to mean the same thing.

That separation also helps when a process changes. Adding a review dependency shouldn't require inventing a new manager. Changing the person authorized to accept risk shouldn't silently change the order in which artifacts are produced. One drawing can display both relations, but its legend has to distinguish them.

A rope rigging shaped like a branching tree hanging in a dark hall. One direct rope that would have run sideways between two low branches has been cut, and its severed ends dangle beside the gap it left.
A hierarchy is a graph with the sideways connections removed.

Statecharts address complexity inside the model

David Harel's statecharts address depth, concurrent regions and communication by events. A state can contain substates. Independent behaviors can be represented separately while remaining active together. Events can coordinate those behaviors.

The reason for that structure is state explosion. A flat description of every combination of independent modes can become difficult to read even when each mode is simple. Nesting and concurrency let the model preserve the distinction between independent behavior and the combined state of the system.

A person stands dwarfed at the foot of a towering grey wall packed with dozens of identical toggle switches. Beside it, under a warm lamp, a low console holds only three separate dials, and one hand turns a single dial.
Model three independent modes as one flat diagram and you need a state for every combination. Harel gave each mode its own concurrent region, so three small dials replace the wall, and the explicit transitions stay.

For operations, the transferable question is whether a large box contains a smaller process worth modeling separately. Publication may contain preparation, deployment and inspection. A feature rollout may contain several independent build efforts. Flattening every detail into one giant diagram can obscure the handoffs as effectively as leaving them out.

The Workflow Patterns Initiative offers a related vocabulary for control flow: sequences, choices, parallel splits, synchronization, cycles and multiple instances. These names let you ask what a process requires before choosing software. A tool's ability to draw boxes doesn't establish its ability to synchronize variable numbers of branches or resume a bounded revision loop.

A business workflow graph isn't automatically a formal statechart or a Petri net. Borrow the distinctions where they help, and retain the limits of the analogy. The next design choice is practical: what must the process do at a decision, at a split, at a join and when work comes back?

Gates need failure routes, and parallel branches need a merge rule

A graph can express a decision without making it a good decision. The condition may be vague, its evidence may be stale or its false branch may lead nowhere. Making the transition explicit gives you something to inspect. The design still needs to match the risk.

Two operations deserve particular care. A gate decides whether an artifact may proceed. A fan-in decides what to do with the outputs of several branches. Both can destroy useful work if their rule is improvised after the results arrive.

A gate evaluates an observable result

A quality gate combines a condition, evidence and a destination for each meaningful outcome. The condition should say enough for another evaluator to understand what a passing result means.

The condition "the reviewer is satisfied" leaves much of the decision implicit. "Every factual claim has a source" is more specific, but it still requires judgment. A source can exist while contradicting the claim, supporting only part of it or applying to a different population. The gate needs to say what relationship the reviewer is checking.

Separate deterministic checks from judgment. A command can establish that a file parses. A reviewer can assess whether a sentence preserves the source's qualification. An operator can decide whether an exception is acceptable. Combining those results into one approved label without keeping their scope makes it hard to tell what was actually established.

The evaluator also needs enough independence for the consequence. An author's self-check is useful preparation. An independent reader can discover assumptions the author carried through the draft. For consequential work, the acceptance decision should use evidence beyond the producer's statement that they completed the task.

Independence alone isn't proof. Another agent can repeat the same unsupported claim. A second person can inspect the wrong version. Name the artifact, the criterion and the evidence they must read. Independence is one protection against a shared mistake, not a substitute for a check that reaches the result.

A failed gate sends work somewhere specific

A false branch should produce an action the next participant can execute. Missing research can return to research. A sentence that misstates an available source can return to the writer with the mismatch identified. A legal issue can go to the person authorized to resolve it.

Those are different failures. Routing all of them to improve the draft forces the writer to diagnose the gate after it has already failed. It also encourages edits that make the text sound better while leaving the missing evidence unresolved.

A corridor turnstile whose rotating arms have been unbolted and lie on the floor beside it. A steady stream of glowing parcels passes straight through the empty frame untouched.
The frame is still standing and the sign is still up. With no false branch there is nothing for work to fail into, so everything passes and the record shows a gate that was cleared every single time.

A blocked condition is worth representing separately from a rejected result. A reviewer unable to access a document hasn't established that the document fails. They've established that review couldn't be completed. That state shouldn't inherit approval, and the person who can restore access should be named.

Ask what happened the last time the gate failed. That account tests the operational rule against history. A gate that has never failed may be appropriate for consistently sound work, or it may be ineffective. Check it against a known failure rather than assuming either conclusion from its pass rate.

The gate's cost belongs in that discussion. Evidence collection and rework consume capacity. Apply a strong gate where a false pass has a material consequence, and remove checks that no longer answer a useful question. Accumulating approvals is an easy way to increase delay without improving the result.

Fan-out preserves separate investigations

Fan-out dispatches several branches from one point. The branches may be different tasks or several attempts at the same task. LangGraph's Send mechanism supports the dynamic form: a routing function returns a target and input state for each invocation, with the number of invocations determined from current data.

The business version might give separate researchers library behavior, prior art and operational evidence. Those are distinct questions, and each can return a finding that another branch would otherwise smooth away. Isolation is useful when the purpose is to preserve independent starting points.

Isolation has limits. Researchers still need a common question, authoritative input and shared constraints. Keeping them apart isn't useful if one studies a different product or assumes a different audience. Their contracts need to be comparable even when their findings differ.

The branch count also has to serve the task. More workers add collection and reconciliation costs. A single person can often answer a bounded question directly. Fan out when the separate work justifies the coordination, then declare what completion means for each branch.

The join determines what survives

The merge rule should exist before the branches begin. It determines both what they produce and how the next node will use it. Several rules are legitimate, but they answer different needs:

  • Select one complete result when the next step needs a coherent direction and the alternatives are competing candidates.
  • Concatenate findings when the next step needs coverage, separate attributions and unresolved disagreements.
  • Score and rank when a later decision-maker needs an ordering against an agreed rubric.
  • Synthesize when producing a new artifact from the inputs is itself a defined task with a quality requirement.

Averaging incompatible directions can discard the assumptions that made each one coherent. That's a risk to examine, not a universal claim that synthesis produces worse work. Skilled synthesis can work when the synthesizer knows which constraints must survive and checks the new artifact against them.

One flame at the top splits into three streams of light, each feeding a lantern that stands on its own low pedestal. A hand lifts the leftmost lantern away whole and still burning, while the other two keep burning where they stand.
Select means one branch leaves whole and still lit. The branches that lost stay intact on their pedestals instead of being taken apart for the pieces somebody liked.

Research often benefits from concatenation first. Keep the library finding separate from the historical finding and let a later writer decide how they relate. A disagreement is information. Combining the branches into a smooth summary too early can remove the disagreement before anyone evaluates it.

A join also needs a completion rule. Does it require every planned branch, any successful branch or an explicitly accepted subset? What happens when a branch fails or produces no result? The answer determines whether the process waits, proceeds with a documented limitation or changes its scope. A fan-in box without that rule has moved the decision into a meeting. Name it before scheduling the branches.

Dependencies determine parallel work, and revision loops need a bound

A list gives every item a position. It doesn't explain whether that position represents a dependency, a preference or the order in which someone remembered the work. Drawing the inputs and outputs can reveal work that doesn't need to wait.

That's an opportunity for parallel execution, subject to the resources and state the work shares. The graph should expose both the opportunity and the constraint. Launching two tasks together isn't useful if they overwrite the same result or both need the only person authorized to proceed.

Separate data dependencies from resource constraints

Two nodes have no dependency path between them when neither needs an output produced through the other. That removes one reason to serialize them. It doesn't establish that they can run safely together in the actual environment.

They may share a working directory, a deployment, a budget, a rate limit or an operator's attention. Those constraints need representation somewhere the scheduler or coordinator can use. Otherwise the graph describes independence while execution still creates contention.

The useful scheduling question is what each node reads, what it writes and what scarce resource it occupies. A documentation draft and a schema migration might both start from an approved specification. Publishing the documentation could still depend on the implementation's final behavior. Separate drafting from publication and the legitimate parallelism becomes easier to see.

The critical path is the longest dependency chain that determines completion under the model's assumptions. Resource limits can change the schedule. The drawing helps you reason about the dependency structure; it doesn't make staffing or execution duration disappear.

An aerial view of a river delta at night. Several channels branch from one source and end in sand, while one long channel carries water all the way to the sea, lit warm along its length.
Drawing dependencies can reveal work that can proceed independently. Completion also depends on task durations and available resources.

Check a suspected false dependency against the actual process. Which input does this task actually need from the task before it? If the answer is none, inspect the resource constraints and consider removing the ordering. A real process can then supply evidence about whether the change helped.

A block should stop only the work that depends on it

A missing input at one node needn't suspend every branch. Trace which nodes require that input, then distinguish work that can continue from work that would merely produce output against an assumption.

An unavailable buyer interview may block the final problem statement while allowing a researcher to organize already collected evidence. It may also invalidate a proposed solution, so writing that solution early could create rework. The graph helps locate the dependency; the contract decides whether a partial artifact is useful.

A waiting branch needs a durable status. Name what it's waiting for, who can provide it and what happens when it arrives. Blocked with no dependency recorded is a queue nobody can resume without another conversation.

The same logic applies to a join. A failed branch should affect the join according to its declared rule. An all-required join waits or routes to a failure handler. A coverage-oriented join may proceed with a missing input explicitly recorded. Neither should silently pretend that all planned work arrived.

Keeping unaffected work moving is a coordination job even when software schedules the nodes. Someone has to ensure that the diagram's dependencies still describe the operation. An obsolete edge can create waiting as surely as a missing edge can create premature work.

Repeating an action and revising an artifact are different loops

A directed acyclic graph has no backward edge in its topology. It can still support retries, repeated scheduled runs or repeated work inside a task. Those mechanisms are useful. The modeling question is whether the revision decision is visible at the level where people need to reason about it.

A network request retried after a transient error may belong inside one node's contract. A draft returned because its argument is incomplete may need an explicit edge from review to writing, with findings attached. Hiding that whole editorial process in a box named write makes its revisions invisible to the rest of the model.

Unrolling a loop is another option. Draft one, review one, draft two and review two can be clear when the process genuinely permits a fixed number of distinct rounds. It becomes cumbersome when each copied node repeats the same contract and the return condition is the thing that matters.

An explicit cycle gives the return a name. It also requires a stop condition. Without a bound, improve and review can repeat while nobody has authority to accept the result, reduce the requirement or abandon the task.

A workshop conveyor running past three benches, with a narrower return chute curving back overhead from the last bench to the first. One lit crate rides the return chute backward while other crates move forward below.
The return chute is a piece of equipment somebody built on purpose. A tool that forbids the backward edge removes the send-back from the drawing, not from the work.

Choose a bound that matches the work. A finite set of rollout stages can provide one. A revision counter can provide another. A substantive condition can stop a loop when the required outcome is reached, but the process still needs a destination if that condition never arrives.

Runtime safeguards don't replace the business stop rule

LangGraph's current documentation describes recursion_limit as a limit on graph super-steps in one execution. Reaching it raises GraphRecursionError. That's a runtime safeguard, and a super-step isn't necessarily one business attempt or one model call.

Define the business attempt separately. It might mean one execution against a fixed task and check, followed by evaluation. Record the attempt, the failed criterion and the resulting decision. Increasing a runtime limit shouldn't silently authorize more business retries.

The spot-fix design uses ABANDONED for exhausted work, with a human destination. The name makes the non-success explicit. The essential property is that exhausted work leaves the retry path carrying its evidence and an authorized next decision.

LangGraph offers checkpointing, while Temporal uses history-based recovery. A stored state snapshot and a replayable execution history aren't interchangeable guarantees. Each needs an implementation appropriate to its runtime and external effects.

For a business process, preserve enough evidence that someone can resume or decide without reconstructing the task from memory. An article workflow needs these same decisions about progression, joins and bounded revision.

An article workflow separates research, authorship, review and publication

An article is a useful worked example because the output can look complete before its claims or argument are sound. A writer can produce fluent text from incomplete research. A reviewer can find a problem after the author has already started another revision. A publisher can deploy a different version from the one reviewed.

This illustrative design separates the contracts for research, writing, review and release.

The brief decides what the research must establish

The brief identifies the reader, the teaching point and the useful outcome. It names the source material, the required coverage and any planned cuts. That prevents a writer from treating a long source as permission to write a short overview without deciding what was lost.

Research can then separate questions that need different kinds of evidence. For a technical article, one branch might inspect library behavior, another read prior work and another locate the author's actual practice. Each returns sources and findings with the limits preserved.

Those branches are optional design choices. A small article may need one author to read one source directly. The reason to split research is a real difference in the work, not the availability of extra agents.

The join should preserve the findings before a writer reconciles them. Suppose a historical source says an earlier system already represented task dependencies. A smooth summary saying earlier systems were flat would lose that distinction. Keep the source and the finding attached, so the outline has to accommodate it or explicitly dispute it.

Three tall glass jars stand on a shelf, each holding sand of one distinct colour under its own warm light. Below, on the floor, a person pours three smaller jars into a single jar, where the colours have turned to one even grey.
In this illustrative workflow, the three research branches remain separate findings rather than one combined summary. Flash teams specified task dependencies, while flash organizations also supported changes to roles, tasks and hierarchy.

The outline gate checks the brief against the planned argument. Every required value point needs a place. A cut needs a reason. A section needs a teaching purpose beyond mentioning the next keyword. Failure returns the work to the outline, where a structural change costs less than rewriting finished sections.

My Content Compiler work uses smaller content units and targeted edits. Here, the relevant principle is preserving the unit being changed. It doesn't justify treating isolated paragraph checks as a substitute for reading the assembled article. The argument exists across the units.

Each node produces something another participant can inspect

A compact node inventory makes the example executable as a process design. The research rows represent distinct questions, not a requirement to assign three people:

Node Receives and produces Failure destination
Brief Commission and source become purpose and coverage Return for scope resolution
Library research Technical question becomes cited behavior and limits Record unsupported claim
Prior-art research Historical question becomes attributed findings Record source gap
Practice research Author records become usable cases and qualifications Omit invented experience
Research join Separate findings become a source packet Return missing required branch
Outline Brief and packet become a section strategy Revise uncovered value point
Prose Outline and sources become a complete draft Return named incomplete section
Editorial review Exact draft becomes findings and disposition Return bounded findings to author
Release Accepted version becomes a deployed and inspected page Return failed release condition

Some nodes contain people. Others can be deterministic operations. An assembly step can concatenate completed sections. A source checker can test whether links resolve. A person still has to evaluate whether the sources support the claims and whether the sections produce a coherent lesson.

The inventory also reveals distinct ownership. Research produces findings. The author produces the draft. Review produces findings about that draft. Release records what was actually published. A participant shouldn't overwrite another participant's evidence merely because they can access the same folder.

Review findings need a revision identity

The author owns the body field. The reviewer reads an identified version and writes findings against it. The author applies accepted findings to a new revision and keeps an edit record. That allows the reviewer to distinguish a repaired defect from a changed claim elsewhere.

A checksum can bind a review to exact file bytes. A revision identifier can do the same job when the storage system guarantees its immutability. The essential condition is that reviewed and current refer to the same artifact, or that later changes are visible.

The review gate should return specific work. A missing qualification in a numerical claim needs the qualification restored or the claim removed. A broken argument may need a structural decision. Sending both back as make it better leaves the next node without a contract.

Bound the correction loop. Name the permitted rounds and the decision-maker for unresolved findings. Exhausting the bound shouldn't turn a returned draft into accepted prose. It should create a visible handoff with the remaining issue and an authority who can decide what happens next.

Publication and live inspection establish different states

Editorial acceptance permits the next authorized stage. It doesn't establish that a page exists on the public site. The release node needs the accepted artifact, the destination and the permission to publish.

The publication record should identify the version sent to that destination. The live inspection then checks the page a reader can actually open. A build output or local preview can support preparation, but neither establishes production routing or the deployed result.

This distinction also protects a staged writing assignment. A full draft can be ready for independent review while remaining unpublished. The writer shouldn't be asked to claim a production result from a Markdown file, and the absence of publication permission shouldn't prevent delivery of the requested draft.

The graph therefore has several meaningful endings. A staged packet can end at handoff to review. An authorized release can continue to deployment and live inspection. A source dispute can end at an owner decision without inventing the missing fact. Naming the boundary keeps each participant's done useful to the next one.

A feature rollout needs a join, a hold state and a tested reverse path

A software rollout changes both the product and the conditions under which people use it. Code can be ready while data preparation is incomplete. A feature can function while the events needed to evaluate its rollout are absent. The graph needs to represent those dependencies before the release decision arrives.

This example is a design exercise, not a report of a particular customer release. Its branch structure and traffic stages illustrate the method. A real team must choose its own measurements, permissions and recovery conditions.

The specification can start several kinds of work

The specification states the intended behavior, data changes and acceptance criteria. It also identifies how the team will observe the result. Several tasks can begin from that information if their contracts don't require unfinished outputs from one another.

Feature development writes the behavior. Migration work prepares the data shape. Instrumentation work prepares the measurements used in rollout decisions. Documentation work prepares the customer and operator explanation.

Those branches are candidates for parallel work. They become independent only after the relevant interfaces are agreed. An event designer may need the final event names from implementation. A documentation author may need a working interaction to verify instructions. Put those dependencies on the graph instead of assuming every branch is independent because they share a specification.

Migration also needs its own safety condition. A change intended to run before the feature must be compatible with the system currently serving users. A destructive change or a data rewrite requires a different authorization and recovery plan. Drawing migration beside build doesn't establish that either may run against production.

The same care applies to instrumentation. A metric gate depends on measurements that actually arrive and describe the relevant behavior. An event definition in a document doesn't establish collection. A dashboard doesn't establish that its underlying query uses the intended population.

A gatekeeper stands at a heavy gate in a stone wall, shading their eyes and peering into thick fog. Beside the gate, a lookout tower has been taken down to a stump, its timbers stacked on the ground and its signal lantern dark.
The metric gate reads what instrumentation writes. Cut instrumentation to make a deadline and the gate is left squinting into fog, waving work through on whoever's impression of the numbers sounds most sure.

The integration join should require the outputs the release needs. If all four branches are mandatory, it waits for all four. If documentation can legitimately follow under a specific release policy, that's an explicit exception owned by someone authorized to accept it. The join must preserve the difference between required work completed and required work waived.

The metric decision routes to ramp, hold or rollback

Integration and staging checks precede exposure to real users. A canary then limits the initial exposure so the team can observe actual behavior under an agreed risk policy. The observation should be tied to the release, the traffic population and the measurement period chosen by the team.

A metric gate can route to ramp, hold or rollback. Ramp means the evidence permits the next exposure level. Hold means the current evidence doesn't justify expansion or reversal. Rollback means the trigger for the reverse path has been met.

Hold needs a contract as much as ramp does. Name what evidence is missing, what additional observation is permitted and when the decision leaves the hold loop. Otherwise hold becomes a repeated meeting in which the same ambiguous data produces a different answer depending on attendance.

Missing data also needs a route. A collection failure isn't evidence that the feature is healthy. Nor does every collection failure require the same recovery as a confirmed customer-impacting defect. The release policy should say whether to halt expansion, revert or seek an authorized decision.

The condition should include guardrails alongside the intended benefit. An improvement in one aggregate can conceal a serious regression for another group. The process owner has to decide which consequences matter before the router can evaluate them. The graph records that decision; it doesn't choose the trade-off on its own.

A changed criterion creates a new decision rule. Record why it changed and who approved it. Quietly moving the threshold after seeing an inconvenient result makes a gate appear to pass while its meaning changes.

Rollback is an action with a trigger and an owner

A rollback document can be useful. The operational test is whether the team can connect a recognized condition to an authorized action and a known destination state.

Name the condition that fires the reverse path. Name the person or system that may fire it. Name the state to restore and how the team will know restoration succeeded. Those details make rollback executable rather than an intention to decide during an incident.

Rehearse the path where it's safe and authorized. The rehearsal should reach the recovery state, not merely demonstrate that a button exists. Database compatibility, queued work and external effects may mean reverting code alone doesn't restore the earlier operating condition.

Some releases need a forward repair because the previous state can't safely be restored. That belongs in the recovery design too. The graph should represent the available action instead of drawing an attractive backward arrow that the system can't traverse.

Separating trigger from blame helps the person making the decision. They can point to the agreed condition and record that it was met. It doesn't remove judgment or responsibility. It makes the basis for action available to everyone who must respond.

A finite ramp still needs bounded waiting

An illustrative ramp can use traffic stages of 1%, 5%, 25% and 100%. Treat those as illustrative parameters, not a recommended schedule. Their teaching purpose is that a finite list can bound one part of a loop.

After each stage, the metric gate evaluates the result before the next stage starts. Reaching the final stage exhausts the list of expansion steps. That prevents indefinite ramping, but it doesn't bound repeated holds, retries or a return to an earlier stage.

Give those paths their own rules. A hold can end at an owner decision. A failed check can permit a named correction and a limited retry. A rollback can end the current rollout and require a new authorized attempt. One counter shouldn't obscure which kind of repetition occurred.

The release history should preserve the exposure level, evidence and resulting action at each transition. That record lets the team explain why it expanded, waited or reversed. The same idea becomes more human, and less numerical, when the gate is a buyer deciding whether a proposal addresses their actual problem.

A proposal needs the buyer's agreement before it needs polished prose

A proposal can be well written and still answer a problem the buyer doesn't recognize. The workflow has to discover that mismatch before the team commits to producing the full document. Qualification and a read-back of the problem are useful gates because they can send work somewhere other than proposal writing.

I start with a problem that exists independently of what I'm selling. The statement "they need an agentic workflow" describes a proposed solution. It doesn't establish what the customer is trying to change or what consequence makes that change worthwhile.

Qualification decides whether a proposal should exist

The proposal example begins with information about budget, authority, the problem, the consequence of leaving it unresolved and what success would look like. Those questions help determine whether the work is understood and whether an engagement is appropriate.

They need more than a single yes-or-no field. A confirmed mismatch and an unanswered question are different states. No available budget may justify decline. An unknown budget may justify a clarification step, if the opportunity is worth that work. The policy should decide which unanswered questions may remain before writing begins.

Authority requires the same care. The person in a discovery conversation may be a useful advocate without being the signer. Record their role and the approval path. Treating every non-signer as irrelevant can discard information; treating enthusiasm as purchasing authority can create a proposal with no decision-maker.

I use budget, authority, need, timeline and engagement to qualify leads. The proposal graph adapts that commercial discipline to its own decision. It also asks what the problem costs and what success means. Those are explicit design choices rather than a claim that every opportunity follows one universal filter.

A decline node should produce a real response. It can state the mismatch, identify what would need to change and point to something useful when an appropriate resource exists. That preserves the difference between deliberately declining work and allowing an opportunity to disappear in a queue.

The gate only works when the false route is available. A rule that says qualify while every incentive and every outgoing edge leads to write proposal hasn't made a selection. It has added a form before the same action.

On the left, an ornate stone bridge spans a river and stops against a blank cliff with no road beyond. On the right, nothing is built yet; a surveyor plants a stake and shines a lantern across to a path on the far bank.
The costly proposal failure is a handsome document answering a problem the buyer doesn't have. So the first gate checks budget, signer, the problem's cost, the price of waiting and what success looks like, before anything gets written.

Discovery needs commercial and organizational evidence

A useful discovery design separates the technical problem, the economics and the organizational conditions around a change. These questions can be investigated independently where that preserves attention, then brought together in a problem statement.

Technical discovery asks what happens now, what systems are involved and what constraints the proposed change must respect. Economic discovery asks what the existing problem costs and what outcome would justify intervention. Organizational discovery asks who uses the result, who approves it and whose work or authority would change.

The organizational branch should examine stated roles and documented concerns. It shouldn't invent a private motive for someone who hasn't supplied one. A person opposing a change may have a valid requirement the current plan doesn't meet. Recording them as a political obstacle can make the team dismiss the information it most needs.

I helped a team preparing a funding case for a crypto-focused radio initiative. The work included a programming plan, audience information, collaborators, budget flows and a CRM with internal and public-facing information. I helped with consulting, copy, systems and handling objections. I wasn't leading the initiative.

That case supports the value of a proposal whose supporting operations can be inspected. It doesn't establish that the team ran the exact graph described here, or that any one gate caused its funding result. The transferable lesson is to make the plan, responsibilities and use of funds concrete enough to examine.

Read the problem statement back to the buyer

The discovery join synthesizes a problem statement under a constraint: it must describe the customer's situation in language they recognize. The statement should preserve the distinction between what the buyer reported, what the team observed and what remains an inference.

Then put the statement in front of the buyer. Their correction is useful output. A changed condition, a missing stakeholder or a disagreement about the consequence can route the work back to discovery before a solution is built around the wrong premise.

Recognition alone doesn't guarantee the statement is complete. A polite yes can conceal misunderstanding, and the person responding may not represent every affected user. Ask for concrete corrections, examples and a description of success. Record who agreed to what rather than turning a conversation into customer approved everything.

In a warmly lit fitting room, a customer tries on a jacket before a tall mirror and checks a sleeve while a tailor kneels with pins. In the dim background, three tailors stand admiring the same jacket on a dress form.
A team can pass every internal check and still have tailored the problem to a dress form. Reading the problem statement back to the buyer is the fitting: they recognize it, or the work returns to discovery.

This is an external gate because the delivery team can't satisfy it through its own confidence. A proposal team can check its arithmetic internally. It can't establish the customer's intended outcome without contact with the customer or an explicitly authorized source of that requirement.

The external response also has a scope. Agreement on the problem doesn't authorize the proposed price, scope or implementation. Those are later decisions. Keeping them separate prevents a valid discovery finding from becoming an implied commitment.

Objections can require a reply or a return to discovery

Before submission, a reviewer who didn't write the proposal can challenge its claims, figures and strongest objections. A derived number must retain its source's qualification. A peak rate multiplied across a period isn't an observed total unless the record supports that assumption.

After submission, distinguish two kinds of objection. A question already answered in the document may need a concise response pointing to the relevant passage. An objection revealing a missed requirement needs a return to discovery, followed by updates to the affected solution, scope or evidence.

Defending the existing document is the wrong action when its premise changed. The return edge makes that distinction explicit without pretending the earlier work never happened. Preserve the earlier assumption and the new information so the next reviewer can see why the proposal changed.

Bound the follow-up too. Name the next agreed action and the condition under which the opportunity closes, pauses or returns for a new engagement decision. A proposal can end in acceptance, a reasoned decline or a recorded hold. The graph earns its place by making those outcomes usable, including the ones that produce no sale.

An agent needs a work contract and a verification path

An agent profile can describe judgment or tone, but those descriptions leave basic execution questions open. Which files may it read? Which result must it produce? Which actions are outside its permission? What happens when the required input is unavailable?

Those questions belong in a node contract. My Agent Redwood material treats agent design as a scoping exercise across dimensions such as mission, constraints, tools, memory, evaluation and integrations. Redwood is a design method. LangGraph is one possible orchestration tool. Confusing them would turn a planning discipline into a software capability it doesn't claim.

The contract names an artifact and a non-success result

An implementation node needs an assigned source boundary, authoritative inputs and an output the next step can inspect. It also needs the acceptance criterion supplied by the task owner. A request for clean code doesn't identify which behavior must work or what evidence would establish it.

The failure condition should cover missing input as well as bad output. A task can be blocked by unavailable credentials without having failed implementation. An agent should preserve that distinction instead of replacing an inaccessible service with plausible local data and reporting a completed integration.

A worker steps back from a bench where a kit tray has one empty compartment, tools set down, and holds up a lit lamp. Behind, at an identical bench, another worker carves a wooden stand-in for the missing part and paints it to look like metal.
An agent can fill a missing input with a plausible guess. Its contract should instead specify when it must stop and report the missing input.

A file is inspectable evidence of what was written. It isn't proof of its own correctness. A commit establishes a source change, while a deployment record establishes another event. The contract needs to say which state the current task is authorized to reach.

The same principle limits research. An exact question about a local function may need one direct source read. It shouldn't automatically create a repository survey, multiple researchers and a new verification program. The graph should make required work explicit without expanding every task into the largest process available.

The spot-fix excerpt shows the control flow

The original article includes this wiring excerpt for a LangGraph spot-fix workflow. It's reproduced as a historical excerpt, not a complete runnable program or a fresh inspection of deployed code. Its node functions, state definition and routing bodies aren't present here:

builder = StateGraph(SpotFixState)

builder.add_node(RECON, recon_node)
builder.add_node(PLAN, plan_node)
builder.add_node(EXECUTE, lambda state: {})   # routing hub
builder.add_node(EXECUTE_TASK, execute_task_node)
builder.add_node(VERIFY, verify_node)
builder.add_node(MERGE_GATE, merge_gate_node)

builder.add_edge(START, RECON)
builder.add_edge(RECON, PLAN)
builder.add_conditional_edges(PLAN, route_after_plan,
                              {EXECUTE: EXECUTE, GATE: MERGE_GATE})
builder.add_conditional_edges(EXECUTE, fan_out_execute, [EXECUTE_TASK])
builder.add_edge(EXECUTE_TASK, VERIFY)
builder.add_conditional_edges(VERIFY, route_after_verify,
                              {EXECUTE: EXECUTE, GATE: MERGE_GATE})

The sequence begins with reconnaissance and planning. The execute node is a routing hub rather than a worker: its function returns no state update. The conditional route can dispatch task invocations. Task execution then leads to verification, and the verification router can return to execution or continue toward a merge decision.

That last route makes the retry cycle visible. Its safety depends on the routing body. The excerpt alone doesn't show which tasks retry, how results are combined, how the attempt cap is counted or what the merge gate accepts. A graph diagram generated from this wiring couldn't establish those properties either.

The current Graph API documentation supports the underlying distinctions: nodes can be ordinary functions, conditional edges route from state and Send can dispatch invocations with different input states. The operational policy still has to be implemented in the omitted functions.

Missing and broken checks can't become passing checks

The verification design described with the excerpt runs a task's declared verification command after execution. A passing result can mark the task verified for that criterion. A failing result records the failure and follows the permitted retry or escalation path.

Two cases need explicit routes. A task with no verification command remains for a human gate because it can't be machine-verified through that path. A command that returns non-zero or times out records failure with captured detail. Neither case should be converted to success because there's no ordinary assertion failure to report.

Keep the statuses precise. No check declared means unverified by this mechanism. Check failed to run means the intended evidence wasn't obtained. Check ran and failed means an observed result didn't meet the criterion. Those cases may require different next actions even though none permits a verified label.

An exhausted attempt budget also needs a destination. The described system uses ABANDONED and sends the task to a human. The useful contract is that the failed criterion, attempted correction and remaining decision travel with the task. Stopping without that information merely transfers diagnosis to someone else.

A green command can still be the wrong proof. Compilation doesn't establish rendered behavior. A source-format check doesn't establish that an external service stored the intended record. The task author needs to select evidence that reaches the consequential result, and the evaluator needs to inspect the artifact named by that criterion.

Deterministic code belongs where the decision is mechanical

A node doesn't need a model merely because it sits inside an agent workflow. Copying a file, invoking a command, checking a declared status and routing a bounded result can be ordinary code. A model is useful where the work requires interpretation or judgment that the contract actually assigns to it.

A deterministic command produces a result according to its code, which can still be wrong, incomplete or pointed at the wrong target. Determinism makes the result repeatable under its assumptions. It doesn't establish that the assumptions match the acceptance condition.

A long shelf holding a row of plain unadorned wooden crates lit warm, with a single ornate brass machine sitting in shadow at one end of the same shelf, carrying nothing.
Most of the load sits on the boring nodes: a file copy, a lint run, a deterministic router. The interesting node is one occupant among many, and treating every node as an agent is how a graph becomes expensive without becoming better.

Use a deterministic limit where model output determines how much work will be launched. A planner's task list shouldn't authorize an unlimited fan-out. Bound task count, scope and allowed destinations before dispatch, and return an explicit planning failure when the output exceeds that contract.

The result is a workflow whose mechanical parts are inspectable and whose judgment calls have named owners. It still needs durable state and isolated mutations, because an accurate decision can be lost or overwritten between the moment it's made and the next node's read.

Durable state and isolated work preserve what a process needs to resume

A graph can be clear while its execution history exists only in chat. The next person opens the task, sees completed and has no way to identify the output, the decision or the version involved. They have to ask someone who remembers.

State that outlives a session needs a durable home. The home should preserve the distinction between an artifact, a report about that artifact and the evidence used to accept it. A process can't resume reliably if all three collapse into the last status message.

Persist the decision and what it depended on

A useful handoff record identifies the input, the output, the action performed, the resulting state and the next permitted action. A review adds its criterion, finding and artifact identity. A blocked task adds the missing dependency and the party able to resolve it.

The record needn't copy every source into every message. It can point to an immutable artifact, a repository commit or a versioned record. The next participant should be able to reopen the evidence without guessing which similarly named file was intended.

A status transition also needs its basis. Approved because a named reviewer inspected a particular revision is useful history. Approved with no actor, criterion or revision leaves the next person to infer the meaning. That inference becomes dangerous when later work treats the status as permission.

The same applies to failure. Preserve the command or operation, the actual result and what was changed before a retry. An unsuccessful attempt can still supply useful evidence. Replacing its record with a later success loses the information needed to explain recurring failures.

Don't store secrets merely to make the history complete. A record can identify an access failure without copying a credential into a log. A useful evidence contract includes what may be retained and who may read it. Durability without data protection creates another class of operational problem.

Checkpointing doesn't restore every external effect

The described spot-fix implementation attaches a SQLite-backed checkpointer at compilation. That's a claim about the described implementation, whose complete code isn't reproduced here. The general capability is documented: LangGraph can attach a checkpointer when the graph is compiled and persist state for continued execution.

A checkpoint answers a state question at a particular point. What did the graph store, and where can execution continue? It doesn't automatically answer whether every external action happened once, whether an external service still has the same state or whether a changed node remains compatible with the saved run.

Imagine an illustrative node that submits a request to another service and then records completion. A process interruption between those actions leaves a recovery question. Repeating the node may repeat the request. Skipping the node may omit the completion record. The operation needs an identifier or read-back that lets recovery determine what actually happened.

That's why durable orchestration and safe side effects must be designed together. Record the identity of the external action and the result needed to distinguish already completed from not yet attempted. The precise mechanism depends on the system and its authority.

Temporal uses replay against an event history to resume workflow execution. It imposes its own requirements on workflow behavior and external effects. A business audit trail is an analogy to that recovery information, not a claim that stored meeting notes provide the same execution guarantee.

A worktree isolates files, not the whole operation

A separate Git worktree gives a worker a separate working copy. That helps keep one implementation effort from overwriting another effort's uncommitted files. A commit then presents an explicit candidate for integration.

Private state in the actor model provides a useful comparison. The comparison is useful at the point of ownership: a participant changes its own copy and communicates an explicit result. It ends before the stronger claim that the whole system has no shared state or data races.

Worktrees share a repository's object database and can still use the same external services, credentials, ports and deployment targets. Two isolated file trees can both write to one database. File isolation doesn't grant permission to mutate that database, and it doesn't resolve those concurrent writes.

Three carpenters at three separate benches, each shaping their own copy of the same part, with a single shared shelf frame glowing in the foreground where the finished parts are joined.
Each bench owns its copy and nobody reaches across. Joining happens once, in the open, at a place both parties can see.

Name the shared resources separately. One worker may own a source path, another a deployment decision and another a data migration. If tasks touch the same live entity, their contracts need coordination at that entity even when the code changes live in different directories.

A shared checkout can also be operated safely under strict path ownership and scoped commits, but it has a different risk. The index and working tree are shared coordination points. Treating them as private because each person has a different task title doesn't create isolation.

Integration is another owned transition

A merge is the point where separate candidate changes become shared source. It should have an owner and the evidence required by the repository's operating rules. A clean textual merge establishes that the files can be combined without that class of conflict. It doesn't establish that their behavior composes correctly.

The same distinction applies outside code. A reviewer suggesting a change and an author continuing from an older draft can create conflicting revisions. Keep findings separate from body ownership, then apply edits at a named point. The policy must survive the tools people actually use.

A source of truth should be identified per fact. The repository owns source history. A task system owns the operational status it records. A deployment system owns its release event. None should silently imitate another by inferring a successful release from a pushed commit or a completed task.

The practical recovery test is a fresh participant reopening the task after the original worker is unavailable. Can they find the exact output, understand the accepted and unaccepted states, and identify the next action within their permission? If they can, the process has preserved something useful across sessions. The written specification should make that same contract explicit before execution starts.

The graph gives a specification contracts that can be examined

A specification needs prose because people must understand what the work is for, which trade-offs matter and what a result means. A graph contributes a different kind of clarity. It makes dependencies, choices and return paths explicit enough to examine separately from the surrounding explanation.

Neither form eliminates ambiguity by itself. An edge labeled acceptable is as vague as a paragraph using the same word. The graph becomes useful when its elements connect to written contracts and real evidence.

An isometric concrete slab with a floor plan drawn across it in glowing lines. A worker under a standing lamp sets the first block down exactly on one of the drawn lines, while the walls of a storey above already stand at the far edge of the slab.
Draw the plan first and the document comes out of the drawing rather than out of a blank page.

Translate each element into an obligation

Each node needs a description of its work, inputs, outputs and failure behavior. Each edge needs a sequencing or routing rule. Each shared state key needs a shape, a writer and an update rule. That gives the specification a structure another person can challenge before implementation.

A conditional edge should identify both permission and non-success. The work may proceed when a named condition holds. If it doesn't hold, a named destination receives the result and the reason. A requirement that says accepted when X leaves the reader to invent the false route unless another part of the contract supplies it.

Keep the authority beside the rule. A reviewer may judge whether a result meets a criterion without permission to redefine that criterion. A release owner may accept a stated operational risk while remaining unable to change a legal requirement. Those are separate decisions.

Data contracts prevent another common ambiguity. The field name alone doesn't tell a worker whether a value is a draft, an observation or an approved result. State which entity the field belongs to, which system writes it and which event justifies the update.

A changed graph then produces a meaningful change to review. A new node adds work. A rerouted edge changes who may proceed and when. A new writer changes authority over state. The prose diff remains important, but the graph can identify which operational relationship the text intends to change.

Each workflow needs an outcome worth achieving

A workflow needs a reason to run and an observable outcome to pursue. The project needs a concrete scope and a deliverable. Those choices determine whether the workflow is worth running at all.

The lower rungs connect that direction to execution. Task names a bounded job. Action names an operation within it. Decision names a choice and its authority. Data names the representation the system uses. Event names the occurrence it observes.

A project can be represented by a graph and a task can often be represented by a node, but the mapping isn't a rigid equivalence. A complex task may contain a subgraph. A node may be a deterministic action inside a larger task. Use the hierarchy to test completeness rather than force every process into one node size.

The decision and event rungs deserve particular attention. A routing function implements a heuristic; an authority owns the exception or ambiguity. A recorded event connects the model to something that happened, such as a submitted form, a completed payment or an inspected page.

A graph whose decisions use only its own predictions can be internally consistent while describing no delivered value. The specification should identify where real events enter and how the system captures them. A field populated with a plausible substitute on failure breaks that connection while making downstream screens look populated.

The hierarchy also limits irrelevant work. A technically elegant node that contributes nothing to the project's outcome shouldn't survive merely because it fits the diagram. Trace its output to a consumer and its consumer to the intended result. The graph has to serve the purpose that justified the task.

Walk the structure before trusting its execution

Three drawing checks expose structural gaps. They expose defects worth addressing before a team builds or automates the process:

  1. Trace forward from the start. Every required node should be reachable under a condition that can actually occur. An orphaned approval step may represent an old requirement or a missing incoming path.
  2. Trace toward an ending from each reachable node. Work needs a route to a meaningful terminal state, including rejection, cancellation or an owner decision when appropriate. A queue with no exit is a process obligation left unresolved.
  3. Inspect every cycle. Name what changes on another pass, what permits exit and what happens when the ordinary success condition never arrives. A visible exit arrow alone doesn't establish that its condition will occur.
A tabletop marble run lit by a lamp. A person drops a marble in at the top. One side ramp connects to nothing, one cup holds marbles with no way out, a circular loop keeps a marble circling, and the main track ends in a basket.
Before anyone builds, trace the drawing three ways: can every step be reached, can every step reach an end, and does every loop have an exit.

Those checks are deliberately informal. A path drawn on paper may be impossible because its guards contradict one another. A join may wait for mutually exclusive branches. A node may be reachable in the topology but unavailable because its required resource never arrives.

Examine those cases with actual state. For a choice, follow each permitted outcome. For a join, identify which branches were activated and which completions are required. For a retry, inspect what changed from the previous attempt. A repeated failure with unchanged input is evidence about the loop's design.

Formal soundness needs more than a tidy diagram

Workflow-net research gives soundness a more precise meaning than a visual review can establish. In the usual formulation, completion remains possible from reachable markings, completed work leaves the proper final marking and no transition is dead. These are properties of the formal execution model.

The whiteboard checks help locate candidates for dead work, stranded work and endless revision. They don't prove soundness, guarantee termination or establish the quality of a node's output. A reachable release step can still publish an incorrect page.

A specification should therefore distinguish structural checks, implementation checks and acceptance evidence. Structural checks examine the model. Implementation checks examine whether the system follows it. Acceptance evidence establishes whether the result meets the human requirement.

The point of drawing first is to find a missing dependency or recovery route while it's still an inexpensive change to the design. It doesn't justify modeling every operation in detail. The next decision is whether this particular job has enough coordination, repetition or consequence to repay that effort.

Use a simpler structure when it already answers the operational question

Modeling creates another artifact to maintain. Someone must update the nodes when work changes, revise the conditions when evidence improves and remove paths that no longer exist. A stale graph can mislead a new participant precisely because it looks deliberate.

The test is whether the model prevents enough consequential confusion to justify that cost. That judgment depends on the work. Applying a state-machine model to every action would produce an operation that spends much of its effort describing itself.

Fixed sequences may need only a checklist

A stable sequence with omission as its main failure mode can be well served by a checklist. The list is easy to inspect, carry and update. A graph that restates every line as a box may add nothing the person executing it needs.

Check the real sequence before assigning it to that category. Payroll can include exceptions and approval conditions. Laptop provisioning can wait on access decisions. Month-end close can uncover discrepancies that require a return. The name of a process doesn't determine whether its actual execution is linear.

Keep the list where the list is sufficient. Add explicit conditions or a small exception path where they're needed. A hybrid can preserve the familiar checklist while making the consequential handoff visible.

The same reasoning applies to deterministic work. A script that validates input, performs a calculation and writes a result may already express its control flow clearly. Putting another workflow engine around it creates a new place for configuration and failure. Use that layer only when coordination or durability requires it.

A solo task may have no handoff to model

One person doing a bounded job in one sitting may already hold enough context to act correctly. The value of a graph rises when state outlives that sitting, another participant needs the result or failure has consequences that memory shouldn't govern.

Those conditions can exist in solo work too. A person performing a consequential maintenance action may need a recovery route even without a team. A recurring personal process may benefit from a short state record. Solo is a clue about coordination cost, not an exemption from consequence.

Choose the smallest useful representation. A task note naming the input, output and stop condition can be sufficient. It doesn't need a visual editor, a graph database or an orchestration library to count as an explicit contract.

The question is what the future reader needs that the current worker would otherwise leave implicit. If there's no future consumer and no meaningful recovery problem, skip the extra model.

Unknown work needs observation before detailed routing

A detailed graph for work nobody has attempted can give assumptions the appearance of established procedure. The boxes are precise while the relationships remain guesses. A team can then follow the drawing because it looks authoritative.

Use a provisional model when it helps identify risk, but mark what's assumed. Keep unknown dependencies visible. Observe an actual attempt and compare its path with the proposed one before promoting the drawing into a reusable operating rule.

The first attempt also has to respect the risk. Do the thing once is reasonable for a reversible learning exercise. It's insufficient for a destructive migration or another action whose failure can't be safely absorbed. Those cases need analysis, constraints and an authorized rehearsal or decision before execution.

After a bounded attempt, draw the work that happened. Include the clarification that changed the plan, the review that sent it back and the resource that caused waiting. Those details are often the reason the next run needs a graph at all.

A one-off needs a consequence test

Repeated work offers repeated opportunities to recover the cost of modeling. A genuine one-off has no later run over which to spread that cost. A simple unique task may therefore be better executed directly, with a useful record left afterward.

A complex one-off can still justify a graph. Several independent teams, irreversible actions or a recovery requirement may create enough coordination risk on the first run. Repetition is one source of value, not the only one.

The decision should compare a specific modeling effort with a specific failure it could prevent. A page of dependencies may be useful. An elaborate catalog of every minor action may not. Cost belongs to maintaining the representation as well as drawing it.

An unused diagram isn't automatically worthless, but it's a reason to ask how people actually coordinate. If everyone follows a smaller set of rules, inspect those rules and decide whether the diagram should be simplified or retired. Don't make reading an obsolete model another mandatory step.

Incidents need authority as well as prepared paths

An incident requires a named commander, clear escalation and permission to act under uncertainty. A team shouldn't debate the entire process model while a consequential failure remains active. The authority structure supplies a way to decide when information is incomplete.

Prepared runbooks can still help. A known rollback condition, a safe recovery procedure and a way to inspect the result are useful during an incident. The hierarchy resolves authority; the workflow can preserve actions already understood well enough to execute.

A condition that can't currently be evaluated needs an escalation rule. Treating unknown state as healthy is unsafe. Treating every unknown as permission for the most destructive response is unsafe too. The incident policy should state which actions are permitted while the evidence is incomplete.

Capture the decision and its basis without interfering with response. Afterward, examine which parts of the event can become a better prepared path. Some uncertainty can be removed. Some will remain a judgment call assigned to a person with authority.

A corridor filling with pale smoke. One figure raises a bright lamp and points the way while others move toward the exit. A large intricate diagram hangs on the wall behind them in shadow, unread.
During an incident the authority chain identifies who decides, while prepared recovery paths can still guide action.

These limits keep the model connected to the operation. A process that needs one condition should receive one condition. A process that needs a graph should receive a graph someone actually uses. Start with the recurring failure, then choose the least representation that lets the next participant act without guessing.

An enormous forty-node flowchart covers a wall, cobwebbed at the corners and dusty at the base. At a desk beside it, one operator works the actual three-step job on a single sheet of paper without looking up. A thread leaves the wall and fades out before it reaches the desk.
The tell that a model has stopped being an operating system: the work happens from memory and the drawing is the thing nobody opens.

Improve one failing transition before mapping the whole company

Choose a recurring process with a failure you can name from an actual run. Start with evidence of that failure: a returned draft, an unacknowledged handoff, an overwritten field or a release whose result wasn't inspected. That gives the model a concrete job.

Drawing the whole company first can bury that job under a large inventory. A smaller model lets the participants decide whether one explicit condition changes what happens. Expand only where another relationship needs to become visible.

Draw the work that actually happened

The first pass has four steps. Each should produce something the people doing the work can inspect:

  1. Identify the real nodes. Name the work, its input and its output, including informal checks people perform before they trust a handoff. Keep job titles separate from those contracts.
  2. Connect the dependencies. Mark which transitions are unconditional and which require a choice. Include the return path work actually takes when a result is incomplete.
  3. Locate the failing handoff. Use the observed run to identify what the next person needed and what they received instead. Distinguish a missing artifact, a missing decision and a missing permission.
  4. Add one executable condition. Name the evidence, evaluator, allowed destinations and stop rule. Record the state update that makes the decision visible to the next participant.

Then run the process on real work within the authority already assigned. Observe whether the transition follows the rule. A condition written in a document hasn't yet established that participants use it, and a successful first traversal hasn't established that every failure route works.

The first useful result may be a contradiction. Two people may both believe they own the same field. The reviewer may lack access to the evidence. A proposed false route may send work to someone who has no capacity or permission to act. Finding that contradiction is a design result, not a reason to redraw the boxes until they look orderly.

Resolve the affected contract and preserve the decision. Another process can then reuse the rule where the same problem appears, with its own actors, evidence and limits. Reuse the relationship only after checking that it serves the new job.

Diagnose over-modeling through actual use

A model can acquire detail long after the extra detail stops helping execution. Every exception becomes another node, and every earlier failure becomes another gate. The people doing the work eventually maintain the real sequence elsewhere because the official drawing is too costly to use.

Ask when someone last opened the model without being asked. If that answer is unclear, inspect the process people do use. They may have a smaller checklist that carries the consequential decisions. They may also be depending on a coordinator whose memory supplies the missing conditions.

Those cases require different responses. A working smaller representation may replace the elaborate graph. An implicit process held by one person may need a few explicit contracts. More detail isn't the default repair for either.

The graph should also change when the work changes. Remove an obsolete edge deliberately and record which earlier assumption no longer holds. Keeping dead steps for completeness makes the next participant's task harder and can give an outdated requirement continuing authority.

A long avenue of ceremonial stone arches receding into darkness, each one more ornate than the last. At the near entrance one person kneels on a small mat doing the actual work with three simple tools.
Every arch was added by somebody solving a real problem. The work still happens on the mat at the front, and each new arch is paid for by everyone who walks the avenue afterward.

Inspect gates and joins before adding workers

A gate with an undefined false route can appear to provide quality control while changing no action. Follow a known failure through it. What result is recorded, who receives the work and what prevents ordinary progression? A diagram that can't answer those questions needs a routing repair.

A gate can also be wrong in the other direction. It may reject valid work because its condition measures a proxy that no longer matches the requirement. Examine a disputed failure against the actual acceptance condition before editing the artifact merely to quiet the check.

A fan-out with no declared fan-in has a different defect. The process pays for separate work, then improvises what to keep. Before launching the branches, state whether the join selects, concatenates, ranks or synthesizes, and what happens when a required branch doesn't return.

The merge rule should preserve attribution. A downstream decision-maker needs to know which finding came from which branch, what assumptions it used and whether the branches disagree. A smooth combined answer can conceal the very distinction the fan-out was meant to discover.

Adding another worker doesn't resolve either defect. Fix the condition or the join first. Then decide whether the additional independent work produces something the next node can use.

Find the fields whose ownership is disputed

Choose a field that repeatedly requires reconciliation. A lifecycle stage, a quoted price or a draft body can each become contested state when several participants update it without a rule.

Name the authorized writer and the input another participant may contribute. A reviewer can submit findings. A marketing automation can submit a score. A pricing approver can accept a change. None of those contributions requires granting every participant the same write permission.

If several writers are genuinely necessary, specify how their updates combine and how stale or conflicting updates are handled. Then inspect a real collision. A policy that says coordinate has left the decision to whoever notices first.

The illustrative page change lacked evidence for the transition from deployed to live-verified. The useful repair names the release, requires an inspection of the actual page and returns a failed result to someone who can act on it.

That repair doesn't guarantee the site will never be wrong. It establishes a narrower, inspectable fact: the work can't receive that particular completion status without the required evidence. Another person can reopen the record and see why the transition occurred.

A workshop at the end of a shift. A drawn plan is pinned open on the wall under a warm lamp and the finished piece stands on the bench beneath it matching the plan. Two workers leave through the door without consulting anyone.
What the model buys is a shop where the drawing and the object agree and nobody had to be in the room to make that happen.

The reusable unit is small enough to write down. A work contract tells the next participant what they will receive. A transition rule tells them when they may proceed. A state rule tells them what they may change. Preserve those decisions where the work happens, and the next handoff can depend on something more durable than the person who remembered to ask.

// RELATED
This is the structural entry for the Operational Systems cluster. For the practitioner surface that applies it to a single process end to end, see Workflow Design. For the agent-side treatment, see Agent Systems and Systems Design. For the diagnostic that decides which process is worth modeling in the first place, see People · Product · Process. For the qualification gate in the proposal example, see The Velvet Rope, and for the customer lifecycle as a state machine, see CRM Automation.

Visuals 25

Keep reading