Course Content
LangGraph Agents
7 sections · 49 lessons
How do you design stopping criteria for iterative agent loops (budget, confidence, time)?
What you need to know
| Rule | Catches | Stored in state |
|---|---|---|
| Quality threshold | The normal, good finish | score, approved |
| Iteration cap | Slow convergence | attempts |
| Cost budget | Expensive loops | tokens_used or cost_inr |
| Deadline | Users waiting | deadline (a timestamp) |
| No progress | Stuck loops | last_outputs |
recursion_limit | Bugs in the above | Run config |
Python
1import time23def stop_or_continue(state) -> str:4 if state["score"] >= 0.9:5 return "finalise" # good enough6 if state["attempts"] >= 4:7 return "finalise" # iteration cap8 if state["cost_inr"] >= 20:9 return "finalise" # budget10 if time.time() > state["deadline"]:11 return "finalise" # user waiting12 if state["last_outputs"][-2:].count(state["last_outputs"][-1]) == 2:13 return "finalise" # no progress14 return "improve"Details that matter
- Set
deadlinein state at the start of the run, so a resumed run keeps the original deadline. - Record why the loop stopped (
stop_reason) for dashboards: if 30% of runs stop on the cap, the cap or the prompt needs work. - For
create_agent,ModelCallLimitMiddlewareandToolCallLimitMiddlewaregive run-level and thread-level caps without writing edges. - Keep the best candidate so far; the finalise node returns it with a note about what was not verified.
A real-life example
A research agent drafts a company profile and improves it until a grader scores 0.9. In production, logs showed: 61% of runs stopped on quality, 27% on the four-attempt cap, 9% on the 90-second deadline and 3% on no-progress. The 27% was high, so the team looked closer and found the grader penalised missing revenue figures for private companies, which can never be found. They changed the rubric; cap-stops fell to 8% and average cost per report fell from Rs 14 to Rs 9.
Follow-up questions to expect
- "Which rule matters most?" — The quality exit, because it defines success. The others are guards so that failure is cheap and visible.
- "How do you count cost inside the graph?" — Read token usage from each model response's
usage_metadataand add it to a state key with anoperator.addreducer. - "What should the user see when a budget stops the run?" — The best result, clearly marked with what is uncertain, and an option to continue.