When I first started building agentic pipelines, I managed project state the way humans do: I wrote a master plan in markdown and told the agents to read it. It worked well enough for small scripts. As soon as the project gained real complexity, the system broke down. Agents got confused about what was ready, duplicated work, or stalled completely.
I needed a better data structure. I call it "state-graph expansion." It means moving dependencies out of hand-authored prose and into a machine-readable Directed Acyclic Graph (DAG). Here is why that matters, and how you can implement it.
The Problem with Prose
Markdown is great for human alignment. We read a document, understand the implied order of operations, and get to work. But markdown is terrible for state machines.
If block C depends on block A being finished, an LLM reading a markdown file has to parse the prose, infer the dependency, and hope it guesses right. When you have 30 blocks of work across multiple phases, the context window gets noisy. I needed a way to derive focus automatically without hoping the agent would parse my intent correctly on every run.
Most people try writing stricter prompt instructions first. That breaks because prompts do not provide structural guarantees. You are just begging the model to pay attention. "Please, make sure you don't start C before A." That is not engineering; it's wishful thinking.
The Machine-Readable DAG
I moved the execution state into a state.json file. The structure is a pure DAG where every block of work explicitly declares its dependencies.
Instead of asking a planning agent to read a markdown file and guess what's ready, the orchestration engine walks the DAG. The litmus test for whether something belongs in the graph became simple: Would a machine need to walk this to answer what's next? If the answer is yes, it belongs in the graph.
Here is a look at how this state graph is structured in my actual orchestration engine:
In this model, block-d absolutely cannot start until both block-b and block-c report a closed status. The orchestration engine enforces this via topological sorting, not the LLM prompt.
Deriving Focus Automatically
With the DAG in place, I built tools to derive the focus table automatically. The orchestration engine checks the graph, finds the nodes with zero blocking dependencies, and feeds only those tasks to the working agents, organizing them into parallel execution waves.
In Rust (which drives my core validation spine), deriving the next unblocked blocks looks something like this:
No more guessing. No more orphan worktrees. The pipeline became deterministic. I could run a multi-block branch train and know exactly what order the PRs would land in. The orchestration layer handles the graph math, and the agents just do the work they are handed.
Structure Dictates Behavior
If your agents are getting lost in your project plans, stop tweaking the system prompt. Give them a data structure they can actually read.
Moving from narrative prose to a strict DAG fundamentally changes how reliable your agentic pipelines can be. It removes the ambiguity of language from the critical path of execution state. When you give machines data structures they can parse deterministically, you stop hoping they will follow instructions, and start engineering systems that simply cannot fail in the same way again.