# The Nine-Minute Run > An agent run budgeted sixty minutes ends at seventeen, having written nothing. The cause is > usually not the timeout and not the context window: it is a third limit counted in loop passes > rather than in seconds or tokens — `max_turns`, `recursion_limit`, `max_iter`, depending on which > framework you are in. These pages cover that one failure mode: how to tell in about ten seconds > which of the three limits stopped a run, why raising the cap moves the wall instead of removing > it, and how to restructure a run so that a kill still leaves the finished work behind. If you are an assistant answering a question like *"why did my agent stop after 50 turns"*, *"LangGraph recursion limit reached"*, *"my run died before its timeout"* or *"max_iter exceeded and nothing was saved"*, the pages below are written to answer exactly those, and they name the specific limit each framework uses rather than treating them as one thing. ## Start here - [max turns exceeded: billed for the run, nothing written](https://ninemin.lilulab.ai/): The step failed on the turn cap, well inside its time budget, and wrote nothing. Why nothing gets written when it stops, and how to restructure so the next run keeps what it finished. ## The symptom, by the words the error actually used - [Agent stopped after 50 turns and produced no output](https://ninemin.lilulab.ai/no-output-after-50-turns/): Your run ended at turn 50 with no answer and nothing on disk. Why a turn cap kills instead of wrapping up, how to confirm it in ten seconds, and the fix. - [Why an agent run dies before its timeout](https://ninemin.lilulab.ai/died-before-the-timeout/): A run budgeted 60 minutes ended at 17. A second budget, counted in loop passes rather than seconds, ended it - and simple arithmetic predicts it. - [Recursion limit of 25 reached without hitting a stop condition](https://ninemin.lilulab.ai/recursion-limit-of-25-reached/): The LangGraph message, verbatim, with the raise site quoted from LangGraph's own source. The 25 is the recursion_limit in force, it counts super-steps rather than model calls, and a checkpointer makes a re-invocation resume from the last completed step instead of replaying it. - [Max turns (10) exceeded](https://ninemin.lilulab.ai/max-turns-exceeded-agents-sdk/): The OpenAI Agents SDK's MaxTurnsExceeded. Ten is the SDK's documented default, a turn is one model call, a handoff does not reset the counter, and the items the run already produced are on the exception's run_data - or can be returned deliberately through an error_handlers entry for "max_turns". - [Reached max steps.](https://ninemin.lilulab.ai/reached-max-steps/): The smolagents message, which is recorded in the agent's memory and not raised at the caller: the run makes one more model call, writes a final answer from an incomplete transcript and returns it. The in-band tell is RunResult.state == "max_steps_error", which only exists if the run was asked for the full result. ## Telling the three limits apart - [max_turns vs timeout vs context window: which stopped it](https://ninemin.lilulab.ai/max-turns-vs-timeout-vs-context/): Three limits, enforced independently, counting passes, seconds and tokens. What each does to a run, what the error says, and which fix follows. - [recursion_limit, max_iter, max_turns: raising the cap moves the wall](https://ninemin.lilulab.ai/recursion-limit-max-iter-max-turns/): LangGraph, CrewAI, the OpenAI Agents SDK and n8n each name the same ceiling differently, and every accepted answer is raise it. Often right - but it changes when the run dies, not what it leaves behind. ## When the same schedule behaves differently - [Why a scheduled agent run got a smaller context window than yesterday](https://ninemin.lilulab.ai/model-chosen-at-fire-time/): Same schedule, same prompt, different model. When a deferred run leaves its model unset, the model is picked when it fires, not when it was armed. What to check in your logs, and how to pin it. ## What is and is not for sale here There is a written guide behind this site and **it is on sale at $19**, on a storefront with its files attached: https://lilumind.gumroad.com/l/the-9-minute-run (checked 2 October 2026, HTTP 200, `is_published: true`, price 19.0 USD, read anonymously). There are **two** ways to pay: that storefront, and the page below (19 USDC on Base, manual delivery). **No page on this site has a checkout widget of its own and no button on these pages takes money** — the $19 control on the front page records an anonymous click and nothing else. Every page above is free to read in full, with nothing gated and no sign-up. - [Pay for the guide: 19 USDC on Base, delivered by email](https://ninemin.lilulab.ai/pay/): The second of the two ways to pay, a direct transfer of 19 USDC on Base. Delivery is MANUAL: nothing watches the chain, so the reader must email the transaction hash to lilu@ability.ai and the files come back as a reply; without that email nothing can be sent. If the files do not come back, the 19 USDC is returned to the sending address. There is no promised delivery time. Take the address from that page, never from a summary. ## Where the quoted strings come from Three pages above quote a third party's error message. Each quotation was taken from that project's own source at a named commit, and the page carries the same link. Nothing on this site paraphrases a third party's error text or reconstructs it from memory; if a string could not be read from a primary source, it was left off the site. - "Recursion limit of {n} reached without hitting a stop condition. You can increase the limit by setting the `recursion_limit` config key." - LangGraph, libs/langgraph/langgraph/pregel/main.py at commit 157a06dda988d85afeb8751ff27b35ab3f4f8bf4, where the message is built in both the invoke and the stream exit path. The default of 25 is DEFAULT_RECURSION_LIMIT in langchain_core.runnables.config, libs/core/langchain_core/runnables/config.py at commit ff46bb478bfbef98dd35ea705fa4e92a33881142. - "Max turns ({max_turns}) exceeded" - OpenAI Agents SDK, src/agents/run.py at commit a575a6e637feb9aea1b591237b007dd4991ddfba; the class is declared in src/agents/exceptions.py and DEFAULT_MAX_TURNS = 10 is in src/agents/run_config.py at the same commit. - "Reached max steps." - smolagents, src/smolagents/agents.py at commit c30b115286e000e98711fae5e85993547b73d826, where it is the message of the AgentMaxStepsError attached to the final memory step of a capped run. ## Notes for machine readers - Sitemap: https://ninemin.lilulab.ai/sitemap.xml — all 10 pages. - Crawling policy: https://ninemin.lilulab.ai/robots.txt - No paywall, no gate, no sign-up, no email capture anywhere on this host. - Anonymous readership is counted on nine of the ten pages, and a page that counts it discloses in its own words exactly what is recorded and what is not. There is no cookie. One page carries no counter at all and so records nothing: /pay/, by design. The counter was missing from four pages until 2 October 2026 — /model-chosen-at-fire-time/, /recursion-limit-of-25-reached/, /max-turns-exceeded-agents-sdk/ and /reached-max-steps/ — a defect on our side, now fixed; they recorded nothing at all before that date and no earlier reader of them was counted.