Most people treat prompt chaining like a relay race. Pass the baton, hope the next runner catches it. That works fine for simple three-step workflows. It completely falls apart when you're doing anything with real complexity, multiple decisions, branching logic, or tasks that take more than a few exchanges to complete.
I've built a lot of these systems. Client onboarding pipelines. Research-to-draft workflows. Code review loops. Feature spec generators. The ones that broke almost always broke for the same reason: the chain had no memory of what it decided earlier.
Each prompt was essentially starting fresh with a summary of what came before. That summary was either too thin to be useful or too long and diluted to stay accurate. Claude would drift. Contradict earlier outputs. Lose the thread of a decision made in step two by the time it hit step six.
This post is about how I fixed that.
The Core Problem With Most Prompt Chains
When you build a prompt chain, you're managing state. Every decision, constraint, and piece of established context from earlier steps needs to survive into later steps. The question is how you carry it.
Most builders do one of two things:
- Dump the entire prior output into the next prompt and hope the model picks out what matters
- Write a manual summary and inject it as a context block
Both approaches have failure modes. Full output dumps bloat the context fast and bury the signal in noise. Manual summaries require you to be in the loop for every transition, which defeats the point of automation.
What actually works is treating state like a structured object, not a blob of text.
The State Object Pattern
Before I run any multi-step chain, I define a state schema. Not a complex one. Just a simple structure that captures the decisions and constraints that need to survive the whole run.
It looks something like this in practice. Say I'm running a feature spec pipeline. My state object tracks things like: the core user problem, the constraints we've locked in, the approach we ruled out, and the acceptance criteria we've already agreed on.
At the end of each step, I have the model output the updated state object in a consistent format, usually JSON. That object, not the full output, gets injected into the next prompt. The full output gets stored separately if I need it for review.
This does two things. It forces the model to summarize what actually changed and matters. And it gives each subsequent step a clean, structured anchor instead of a wall of prose to parse through.
The Update Prompt
The trick that makes this work is adding an explicit state update step at the end of each chain node. Not as part of the main task prompt. As a separate follow-up.
After Claude does the work of step three, for example, I send a second prompt in that same call or immediately after. It says something like: given what we just decided, here's the current state object, update only the fields that changed, return the updated object in the same schema.
This keeps the state clean. Claude isn't trying to do the work and update the ledger at the same time. Two jobs, two prompts, one turn.
Where the Chain Gets Injected
The state object becomes the system-level anchor for every subsequent step. I put it near the top of each prompt, after the role definition but before the task instructions. Something like: here is the established context for this project, treat these as locked decisions unless the current step explicitly revisits one.
That last clause matters. You want to give the model permission to surface a conflict if new information contradicts something in the state. Otherwise it'll silently override it or get confused about which source to trust.
I've seen chains fail because Claude respected a bad earlier decision all the way to the end and never flagged it. Giving it explicit permission to raise a conflict catches those cases early.
Branching Without Losing the Thread
Some workflows branch. You evaluate something mid-chain and take one of two paths depending on the result. This is where most visual workflow tools get messy and where pure prompt chaining breaks down fast.
The way I handle branching is with a decision log field in the state object. Every time the chain hits a fork and chooses a direction, that decision gets logged with a short reason. Not a paragraph. One sentence max.
When the branches reconverge later, or when I need to audit why the output looks a certain way, the decision log tells the story. Claude also has access to it, so if a downstream step produces something that seems off, it can reference why we made the call we did.
It's a small thing but it closes a big gap. Most chains are black boxes after the fact. This makes them readable.
What to Put in the State Object vs. What to Leave Out
Not everything belongs in state. If you try to capture every output, you're back to the same bloat problem. The rule I use is simple: if a later step could make a wrong decision without knowing this, it belongs in state. If it's just context or color, store it elsewhere and reference it only if needed.
Typically that means state holds constraints, locked decisions, scope boundaries, and any explicit user preferences or rules. It does not hold full drafts, code blocks, or research output. Those live in a separate store and get pulled in only when the specific step needs them.
The schema, exact prompts, and implementation details for n8n and Cursor are behind the gate above. If you want the full system including how I handle compression and versioning, that's all inside Inner Circle.