In our previous documentation, we explored sequential, parallel, and conditional architectures. However, for complex tasks where quality is paramount, a single pass is often insufficient. This eighth installment introduces Iterative or Looping Workflows, which allow an agent to repeat a cycle of tasks to continuously improve an output until it meets a specific quality threshold.
1. The Need for Iteration: The “First-Draft” Problem #
When using LLMs to generate content—such as a professional tweet or a technical report—the output from the first prompt is often mediocre or fails to meet strict formatting rules. Iterative workflows solve this by creating a feedback loop between specialized nodes to refine the result.
Common Use Case: An automated social media manager that doesn’t just “post” but evaluates its own work against strict criteria like humor, length (e.g., under 280 characters), and originality.
2. The Iterative Architecture: Generation, Evaluation, Optimization #
A production-grade iterative workflow typically involves three primary components:
- The Generator: Takes a topic and creates the initial draft.
- The Evaluator: Acts as a strict critic. It reviews the draft against specific guidelines and decides if it is “Approved” or “Needs Improvement”.
- The Optimizer: If the draft is rejected, the Optimizer takes both the original draft and the Evaluator’s feedback to generate a revised, higher-quality version.
The Loop: The Optimizer sends its new draft back to the Evaluator, and the process repeats until the content is approved or a limit is reached.
3. Engineering for Stability: The Max Iteration Limit #
One of the biggest risks in looping workflows is the infinite loop. This happens if the Evaluator is too strict or the Optimizer is unable to satisfy the requirements, causing the agent to loop forever.
To prevent this, engineers must define a max_iterations variable in the State. The routing logic is then updated to terminate the workflow if:
- The content is approved.
- OR the current iteration count exceeds the maximum limit (e.g., 5 attempts).
4. Implementation Framework: The Looping Logic #
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
count: int
def increment(state: State):
return {
"count": state["count"] + 1
}
def check_condition(state: State):
if state["count"] >= 5:
return "end"
return "continue"
builder = StateGraph(State)
builder.add_node("increment", increment)
builder.add_edge(START, "increment")
builder.add_conditional_edges(
"increment",
check_condition,
{
"continue": "increment",
"end": END
}
)
graph = builder.compile()
result = graph.invoke({"count": 0})
print(result)
Using LLM
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
class State(TypedDict):
question: str
answer: str
score: int
attempts: int
# 1. Generate answer
def generate_answer(state: State):
response = llm.invoke(
f"""
Answer this question clearly and accurately:
{state['question']}
"""
)
return {
"answer": response.content,
"attempts": state["attempts"] + 1
}
# 2. Evaluate answer
def evaluate_answer(state: State):
response = llm.invoke(
f"""
Evaluate the following answer.
Question:
{state['question']}
Answer:
{state['answer']}
Give a score from 1 to 10.
Return ONLY the number.
"""
)
score = int(response.content.strip())
return {
"score": score
}
# 3. Decide whether to continue
def route(state: State) -> Literal["improve", "end"]:
if state["score"] >= 8:
return "end"
if state["attempts"] >= 3:
return "end"
return "improve"
# 4. Improve answer
def improve_answer(state: State):
response = llm.invoke(
f"""
Improve the following answer.
Question:
{state['question']}
Current answer:
{state['answer']}
Current score:
{state['score']}/10
Return only the improved answer.
"""
)
return {
"answer": response.content
}
# Build graph
builder = StateGraph(State)
builder.add_node("generate", generate_answer)
builder.add_node("evaluate", evaluate_answer)
builder.add_node("improve", improve_answer)
builder.add_edge(START, "generate")
builder.add_edge("generate", "evaluate")
builder.add_conditional_edges(
"evaluate",
route,
{
"improve": "improve",
"end": END
}
)
builder.add_edge("improve", "evaluate")
graph = builder.compile()
result = graph.invoke({
"question": "Explain gradient descent in simple terms.",
"answer": "",
"score": 0,
"attempts": 0
})
print(result["answer"])
print("Score:", result["score"])
print("Attempts:", result["attempts"])
Summary Table: The Evolution of Workflows
| Workflow Type | Movement | Best Used For… |
|---|---|---|
| Sequential | Linear (A → B) | Simple, predictable tasks. |
| Parallel | Simultaneous (A + B) | Speed and multi-aspect analysis. |
| Conditional | Branching (A OR B) | Decision making and routing. |
| Iterative | Looping (A ↔ B) | Quality control and refinement. |
Q.1 In the context of LangGraph, how does an iterative workflow differ from a sequential workflow?
It executes tasks in a strictly linear fashion without repeating steps.
It chooses only one path out of many based on a specific condition.
It allows the system to loop between nodes to refine or improve an outcome.
It executes multiple tasks simultaneously to save time.
Explanation
Unlike a sequential workflow, an iterative workflow can repeatedly execute a set of nodes until the desired quality is achieved or a stopping condition is met.
Q.1 What is the main purpose of an iterative workflow in LangGraph?
To execute every node exactly once.
To repeatedly execute nodes until a condition is satisfied.
To execute all nodes simultaneously.
To remove the need for state management.
Explanation
An iterative workflow repeatedly executes one or more nodes and uses a condition to determine when the loop should stop.
Q.3 Why is a max_iteration variable included in the LangGraph state?
To prevent the workflow from entering an infinite loop if approval is never achieved.
To speed up the first tweet generation.
To ensure at least five LLMs are used.
To define the minimum number of iterations.
Explanation
The max_iteration variable limits the number of optimization cycles, preventing endless loops when the desired quality cannot be achieved.
Q.4 Which two conditions cause the workflow to transition to the END node?
The topic changes or the LLM fails.
The tweet is approved OR the iteration count reaches the maximum limit.
The tweet is rejected and the iteration count is below the limit.
The Evaluator provides feedback and the iteration count is zero.
Explanation
Execution ends either when the Evaluator approves the generated tweet or when the maximum number of iterations has been reached, preventing infinite execution.
Q.5 Why is a Pydantic schema used together with with_structured_output() for the Evaluator?
To enable access to external tools.
To ensure the LLM returns predictable fields such as evaluation and feedback.
To generate longer tweets.
To eliminate the need for prompts.
Explanation
Structured output guarantees that fields such as evaluation, feedback, and score are always returned in a consistent format, making them easy for downstream nodes to process.
Q.6 What is the role of the reducer function (such as operator.add) for tweet_history?
It subtracts failed iterations.
It counts the number of words.
It shortens tweets to 280 characters.
It appends each newly generated tweet to the existing history instead of replacing it.
Explanation
Using operator.add as a reducer allows every generated tweet to be added to the tweet_history list, enabling the workflow to maintain the complete optimization history.
Q.7 Why is an iterative workflow particularly useful for tasks such as content generation, code generation, or essay writing?
Because it guarantees perfect output in a single LLM call.
Because the output can be repeatedly evaluated and improved until it satisfies predefined quality criteria.
Because it removes the need for an evaluator.
Because it always reduces the number of LLM calls.
Explanation
Iterative workflows allow an AI system to generate an initial draft, evaluate its quality, apply targeted improvements, and repeat the cycle until the desired quality is achieved or the maximum iteration limit is reached.
Q.8 True or False: In LangGraph, creating a loop simply involves connecting a later node back to an earlier node with a normal edge.
True
False
Explanation
True. LangGraph supports iterative workflows by allowing edges to point back to previously executed nodes, creating controlled execution loops.
Q.9 What does the Evaluator check before approving a generated tweet?
Whether it uses highly academic English.
Criteria such as humor, originality, viral potential, and adherence to formatting rules.
Whether it contains more than 500 characters.
Which LLM generated the tweet.
Explanation
The Evaluator assesses the generated tweet against predefined quality criteria such as creativity, clarity, originality, engagement, formatting, and viral potential before approving it.
Q.10 Which node executes first when the iterative workflow begins?
Route.
Generate.
Evaluate.
Optimize.
Explanation
The Generate node creates the initial tweet based on the input topic. This draft is then evaluated and, if necessary, refined through subsequent optimization cycles.