One problem with the sequential agent and parallel agent approaches is that all of the components are “one-shot” — they run once and finish. There’s no way to go back and refine the output of each step if it’s not good enough.
A LoopAgent solves this problem by running a set of agents repeatedly until either
- A specific condition is met, or
- A max number of iterations is reached
Imagine we want to write a story. We might create a writer agent to draft the story, and a critic agent to evaluate whether the story is good enough. If not, it sends the story to a refiner agent to revise.
# This agent runs ONCE at the beginning to create the first draft.
initial_writer_agent = Agent(
name="InitialWriterAgent",
model="gemini-2.5-flash-lite",
instruction="""Based on the user's prompt, write the first draft of a short story (around 100-150 words).
Output only the story text, with no introduction or explanation.""",
output_key="current_story", # Stores the first draft in the state.
)
# This agent's only job is to provide feedback or the approval signal. It has no tools.
critic_agent = Agent(
name="CriticAgent",
model="gemini-2.5-flash-lite",
instruction="""You are a constructive story critic. Review the story provided below.
Story: {current_story}
Evaluate the story's plot, characters, and pacing.
- If the story is well-written and complete, you MUST respond with the exact phrase: "APPROVED"
- Otherwise, provide 2-3 specific, actionable suggestions for improvement.""",
output_key="critique", # Stores the feedback in the state.
)We then need a way to tell the agent to stop, which we can do with a regular python function:
# This is the function that the RefinerAgent will call to exit the loop.
def exit_loop():
"""Call this function ONLY when the critique is 'APPROVED', indicating the story is finished and no more changes are needed."""
return {"status": "approved", "message": "Story approved. Exiting refinement loop."}And we define a Refiner Agent to revise the draft(s) OR call the exit_loop() function:
# This agent refines the story based on critique OR calls the exit_loop function.
refiner_agent = Agent(
name="RefinerAgent",
model="gemini-2.5-flash-lite",
instruction="""You are a story refiner. You have a story draft and critique.
Story Draft: {current_story}
Critique: {critique}
Your task is to analyze the critique.
- IF the critique is EXACTLY "APPROVED", you MUST call the `exit_loop` function and nothing else.
- OTHERWISE, rewrite the story draft to fully incorporate the feedback from the critique.""",
output_key="current_story", # It overwrites the story with the new, refined version.
tools=[FunctionTool(exit_loop)], # The tool is now correctly initialized with the function reference.
)And then we can bring everything together into a LoopAgent (which is itself within a SequentialAgent since we need the initial draft first):
# The LoopAgent contains the agents that will run repeatedly: Critic -> Refiner.
story_refinement_loop = LoopAgent(
name="StoryRefinementLoop",
sub_agents=[critic_agent, refiner_agent],
max_iterations=2, # Prevents infinite loops
)
# The root agent is a SequentialAgent that defines the overall workflow: Initial Write -> Refinement Loop.
root_agent = SequentialAgent(
name="StoryPipeline",
sub_agents=[initial_writer_agent, story_refinement_loop],
)