Context
An LLM workflow is a directed graph: steps are nodes, and the transitions each step permits are edges. Structural mistakes in that graph, such as a transition to a step that no longer exists, a step with no way out, or a cycle that can never terminate, are present the moment the workflow is written. They do not depend on model output or user content.
Despite that, these errors usually surface only at runtime, in production, minutes into a real conversation, when a step hands off to a target that was renamed or loops until something times out.
This is the same class of failure as an invalid configuration file, and it is the application of ADR-001 one layer up: from configuration values to the shape of the workflow itself.
Problem
Most guardrails for LLM systems limit volume rather than validate structure. A maximum number of tool calls, a timeout, or a retry cap will cut off a runaway loop after the fact, but they treat the symptom. The loop still exists, and nothing explains why the workflow was able to loop in the first place.
If a structurally invalid workflow is allowed to start, the failure appears far from its cause, at the worst possible moment, and teaches the operator nothing about the underlying defect.
Decision
Workflow topology will be validated at load time, before any step executes.
The validator analyzes the declared graph and refuses to start the workflow if it is broken. Each step declares three things, and each is a checkable rule:
allow_transitions: the only steps this step may hand off to. Any other target is an invalid transition.
allow_reentry: whether the step may be entered more than once, which turns "is there a cycle" into "is there a cycle that is actually a problem."
max_invocations: a hard ceiling that must be greater than zero, or the step can never run.
Declared entrypoints name the authoritative roots of the graph, so the validator does not have to guess where execution begins and can flag any step that no path can reach.
The validator reports every structural problem in one pass, not just the first, so a large config can be fixed in a single edit cycle.
Alternatives Considered
Rely on runtime guardrails (call caps, timeouts, retries)
Rejected. These bound the blast radius of a bad workflow but never prevent it, and they surface the failure at runtime with no structural explanation.
Catch structural errors during execution
Rejected. The error already exists at load time. Deferring detection to execution reproduces the exact failure mode this decision exists to remove.
Validate only that the YAML parses
Rejected. Syntactically valid YAML can still describe an unreachable step, a dead end, or a non-terminating cycle. Structural validity is a separate property from parse validity.
Consequences
Positive
Structural defects are caught before a single step runs.
Errors are reported at their source, in the graph, rather than mid-conversation.
Dead ends, unreachable steps, invalid transitions, and unsafe cycles become explicit failing checks.
The execution layer can assume it received a valid topology.
Structural rules become documented and testable.
Trade-offs
The workflow format must declare transitions, reentry, and invocation limits explicitly, which is more up front work than an implicit graph.
Validation rules must stay consistent with the execution semantics they protect.
Evidence & Related Work
Implementation Evidence
The validator ships in the source-available llm-workflow-router package. A workflow is expressed as declarative YAML, and python -m router.cli validate <config>.yaml returns a clean exit on a valid graph and a structured report of every defect on an invalid one.
PyPI:
Related article:
Relationship to the Broader Engineering Approach
This ADR extends the principle in ADR-001 from configuration values to workflow structure:
Invalid states should be made difficult or impossible to reach the execution layer.
A workflow graph is one more input that can be validated at a boundary rather than trusted and executed.
Decision Outcome
Topology validation is treated as a load-time boundary:
Workflow definition → Topology validation → Validated graph → Execution
rather than:
Workflow definition → Execution → Runtime loop or dead end
This ADR should be revisited if a future workflow model requires structure that cannot be fully validated before execution begins.