Lesson 02 · Workflows · 11 min
Prompt chaining
The first workflow pattern is the plainest: break the task into steps that always happen in the same order, and make each model call handle one of them. Draft, then check, then polish.
What makes chaining more than a long prompt is the gate. Between steps, ordinary code looks at the output and decides what happens next — and because it is code, it is deterministic and free. In the lab, a regular expression checks the draft for promises. If it finds one, a rewrite step runs; if not, that step is skipped.
const draft = await ask("draft", task);
// The gate is code, not a model. That is what makes it a gate.
const promises = /\b(will|guarantee|within \d+ days?)\b/i.test(draft);
if (promises) {
draft = await ask("remove promises", draft);
}
return ask("polish", draft);Chaining suits tasks with fixed sub-tasks, where decomposition trades latency for accuracy — each step is easier than the whole, so each call does better work. It does not suit tasks whose steps depend on the input, which is what routing and orchestration are for.
- Keep each step's prompt narrow. The point is that a small job is done well.
- Put as much of the checking into code gates as you can; they cost nothing and never hallucinate.
- Watch the latency: three sequential calls take three times as long, and chaining is the slowest pattern per unit of work.
Try the task that invites a promise. The single call usually makes the promise; the chain catches it in the gate and rewrites. That gate is three lines of code doing the job a second model would be asked to do in the evaluator-optimiser pattern — at zero cost.
Checkpoint
Produce a run where the chain's gate fires and a run where it is skipped.