Skip to content
Forward Deployed

Forward Deployed
Lessons and contents
Agentic Workflow PatternsLesson 2 of 7
7 lessons
Learn

Prompt chaining with quality gates

Source
From the RAG & Agents Engineering course
By
Sourav Banerjee
Last updated
9 Nov 2026

Report an issue

Workflow vs agent

What you'll learn

  • Explain the difference between a workflow and an agent by who chooses the next step.
  • Map each of the five T7.3 patterns to the one decision it hands the model.
  • Trace a gated chain through its pass path and its retry-limit path, call by call.
  • Diagnose why a gate leaks, loops or lets an unusable result through.

T7.2 ended with an agent that picks its own tools. This module goes the other way: five patterns where your code draws the path and the model fills in one kind of decision.

A Larkspur customer writes I want my money back for last month. A useful reply needs the plan and the purchase date before it can apply the refund-window policy. A chain that drafts straight away turns those missing inputs into a polished guess. This lesson builds the guard against that, and first separates two kinds of system.

Who picks the next step

The distinction comes from Anthropic's Building Effective Agents (December 2024). In a workflow, LLM calls and tools run along code paths you defined in advance. In an agent, the model directs its own process: it picks the next tool, reads the result and decides when to stop. The ReAct agent of T7.2 is an agent. All five T7.3 patterns are workflows.

The two differ in what you can know before a request runs:

Workflow (T7.3) Agent (T7.2)
Who picks the next step Your edges; the model at most chooses among edges you wrote The model, on every turn
LLM calls per request Known, or bounded by a cap in your code Known only when it stops; bounded by a step limit
Testing Each node and each router, like a function Whole trajectories, end to end
A failed run Ends at a node you named, with a reason Shows in the trajectory: a repeated tool call, an early stop
Fits Tasks you can draw before they run Tasks whose steps depend on what the model finds

Table 1: Workflow and agent, side by side.

A Larkspur refund reply has a shape you can draw: pull out the plan and the date, check them, draft, polish. Investigating why one customer's servers keep rebooting has no such shape, and that is where an agent earns its extra calls.

One decision per pattern

Each workflow pattern hands the model exactly one kind of decision and keeps the rest in code:

Pattern Code fixes The model decides
Prompt chaining (24.1) the order of the steps each step's content, and a gate's verdict
Routing (24.2) the set of handlers which single handler runs
Parallelization (24.3) the branches and the merge each branch's content, each vote
Orchestrator-worker (24.4) the worker's job and the merge how many workers run, and what each one gets
Evaluator-optimizer (24.5) the criteria and the iteration cap the grade, and so whether to go round again

Table 2: The five patterns by who decides what.

The gated chain in this lesson shows how little the model controls. Its compiled graph has five nodes and eight edges, and only three edges are conditional:

From To Kind
start extract_points fixed
extract_points check_points fixed
check_points write_draft conditional (pass)
check_points extract_points conditional (reject, try again)
check_points fail_validation conditional (retries used up)
write_draft polish_final fixed
polish_final end fixed
fail_validation end fixed

Table 3: The recorded edge list of the gated chain. All three conditional edges leave the gate.

Everything the model decides happens inside a node. Where the run goes next is decided by code you can read, which is what the next section relies on.

Quality gates

Prompt chaining splits one task into a fixed sequence of focused calls, each reading the previous step's output. The lesson's chain turns a topic into an email in three steps: extract the key points, draft, polish. A quality gate sits between two steps and decides whether the intermediate result may go on.

Where the gate sits

The gate checks the cheapest artefact that can already be wrong. Failing after extraction costs one check. Failing at the end costs a draft and a polish written from nothing:

Prompt chain with a quality gate A topic goes to an extract step, then a gate run by a temperature-0 judge. The abstract topic is rejected on attempts 1, 2 and 3; each rejection loops back to extract, and the third ends the chain at a stop node, so draft and polish never run. A concrete topic passes the gate on attempt 1 and goes on to draft and polish. Topic Extractkey points Gatejudge pass Draft Polish concrete topic:passed on attempt 1 reject, try again 3 rejects Stop draft and polish never run abstract topic: attempt 1: reject attempt 2: reject attempt 3: reject
  1. The abstract topic, The meaning of life and happiness, goes in. Step 1 lists three key points at temperature 0.7.
  2. The temperature-0 judge returns actionable False: no request, decision or next step. Attempt 1 of 3.
  3. The router sends it back to extract for a fresh sample. Attempt 2 is rejected too.
  4. Attempt 3 is rejected, and retry_count has reached MAX_VALIDATION_RETRIES, 3.
  5. The router takes the fail edge. The stop node writes why; draft and polish never run. Six LLM calls in all.
  6. A concrete topic, the deadline-extension request, passed on attempt 1 and went on to draft and polish: four LLM calls.

Figure 1: The gated chain. The gate can pass the key points on, send extraction round again, or stop the run with a reason.

We call the failure this prevents writing from nothing: later steps spend calls polishing a result whose input was never usable.

The three parts of a gate

A gate is three separate pieces, and keeping them apart is what makes each one testable:

Part In the reference chain Why it is built this way
The check A gpt-4o-mini judge at temperature 0 returns a structured verdict: actionable (yes or no) and a one-sentence reason A keyword rule leaks; a structured verdict cannot come back as free text
The router A pure function reads the stored verdict and the attempt count and returns write_draft, regenerate or fail No LLM call, so it is tested like any function
The bound Each extraction adds 1 to a counter; at MAX_VALIDATION_RETRIES = 3 the router takes the fail edge; a recursion limit of 12 steps backs it up A rejecting judge cannot keep the chain running

Table 4: Check, router and bound.

The counter uses a reducer, a rule for combining a node's update with the value already in state. Here the rule is addition, so each extraction's 1 accumulates into an attempt count.

Two recorded runs

The two recorded runs take the two exits of Figure 1:

Topic Attempts Gate verdicts Ended at LLM calls
Request for project deadline extension due to technical challenges 1 pass: the points outline a request, its reason and a new timeline the polished email 4 (extract, judge, draft, polish)
The meaning of life and happiness 3 reject three times: informative points with no request, decision or next step fail_validation, with a reason 6 (three extracts, three judges)

Table 5: Both exit paths, from the notebook's recorded output.

The second run spent three judge calls to avoid writing and polishing an email with no purpose. It also ended with a message a caller can show or log, which a crash or an empty email would not give.

Planted failures

Each piece of the gate exists because something specific goes wrong without it:

Planted failure What happens The guard
A keyword gate ("mentions request, deadline, support") Philosophical key points mention "support" and "progress", so vague topics pass An LLM judge with a yes-or-no verdict and a reason
Extractor at temperature 0 A regenerated attempt can repeat the rejected key points, so all three tries fail the same way Extract at 0.7, judge at 0
A bug in the router that never returns fail The reject edge loops forever The recursion limit of 12 steps stops the run
Typed output with useless content Every field is present and the email still has no purpose A schema checks shape; the gate still checks content

Table 6: One planted case per guard.

Pitfall: the repeating regenerator. A retry only helps when the next attempt can differ. At temperature 0 the extractor may return the same points, and lower temperature does not guarantee identical output either. Check that retries actually change the result, and that the judge grades the same text consistently.

Gates in other frameworks

The same gate appears in the two alternative builds of this lesson:

  • LCEL (LangChain Expression Language, which composes runnable steps with |): the gate is a step that passes the payload through or raises a rejection error. A retry wrapper re-runs extraction and gate together, playing the reject edge, and a fallback plays fail_validation.
  • Structured output at every hop: each step returns a validated object, so shape errors are caught without an extra judge call. Shape is all it checks.

In practice: the Larkspur refund ticket

The refund reply follows the same chain:

  1. Extract the plan, the purchase date and the request from the ticket.
  2. Gate: check that the ticket names a plan and a purchase date. Without them the refund-window chunk cannot be applied.
  3. On pass, draft from the refund policy and polish.
  4. On the third reject, end at a terminal node whose reason asks the customer for the missing date.

I want my money back for last month fails the gate before any drafting, and the customer is asked one precise question. In lesson 2 of T7.3 the same ticket meets a different decision: which queue, and which model, should handle it.

Limits of this evidence

  • Two runs. Table 5 comes from one recorded run per topic; a new run can extract different points and the judge can word its reasons differently.
  • One judge. The gate's verdicts were not compared against human labels, so its false-pass rate is unmeasured.
  • Left out: a gate per step. Add one after drafting when the draft itself can fail a check you can state, such as a missing policy citation.

Run the notebooks

The code for this lesson is in these notebooks. Colab runs one in your browser: install the packages its first cell imports and set the API keys it reads. To run every notebook as written, clone the repository and use its uv environment.

Notebook GitHub Colab
Prompt chaining LangGraph Open on GitHub Open in Colab
Prompt chaining structured output (optional) Open on GitHub Open in Colab
Prompt chaining lcel (optional) Open on GitHub Open in Colab

Key Takeaways

  • In a workflow your code fixes the path and the model makes one kind of decision; in an agent the model picks every step. Use a workflow for any task you can draw before it runs.
  • Put the gate after the cheapest step that can already be wrong. Check with an LLM judge that returns a structured verdict, and route in a pure function you can test without a model.
  • Bound retries with a counter and a terminal node that records why the chain stopped. A schema checks shape, never usefulness, so typed output still needs a gate.

Check yourself

1. Why does the quality gate sit right after extraction instead of checking the finished email?

Failing after extraction costs one check, while failing at the end costs a draft and a polish written from nothing. The gate stops unusable key points before later steps spend calls on them, and the chain ends with a reason a caller can show or log.

2. The topic about the meaning of life is rejected three times. How many LLM calls does the run make, and where does it end?

Six: three extractions and three judge calls. At the third rejection the router takes the fail edge to fail_validation, which records why the chain stopped. No draft or polish call runs.

3. You set the extractor to temperature 0, and the gate rejects the same key points three times in a row. Why did regenerating not help?

At temperature 0 the extractor may repeat the points it already produced, so each retry fails the same way. The reference chain extracts at 0.7 so a new attempt can differ, and judges at 0 so the verdict stays as consistent as possible. Neither setting guarantees identical or different output, so check that retries really change the result.

Rate your confidence and keep notes on the module page.