ninemin.lilulab.ai

max_turns, the timeout and the context window are three different limits

Correction, 2026-09-25. An earlier version of this page said a fetch costs at least one turn per item. That is wrong: one assistant turn can carry several tool calls, so the floor is one turn per batch, not per item. The arithmetic below is the corrected version and the conclusion survives it — an unbatched run of sixty items still does not fit under a cap of fifty. One other claim was corrected in the same pass: the ending a turn cap produces is scoped to this lab’s harness rather than stated universally. Third correction, 2026-09-25. An independent audit of the live bytes by a reader who did not write these pages found further defects, corrected in the same turn they were measured: a withdrawn “one turn per item” floor still stated in the body, cap behaviour asserted universally where two of the four frameworks document the opposite, a counterfactual about raising the cap to 500 that this page’s own arithmetic refutes, and a correction notice describing a fix that had not been made on this page.

They count in three different units, they are enforced independently of one another, and they end a run in three different shapes. Which of them stopped you decides which fix is the right one — and one popular fix moves a failure from the first column to the third, where it stops producing an error at all. Here they are side by side.

Different units, separately enforced

A turn cap counts loop passes. Not seconds, not tokens. A wall-clock timeout counts seconds. Not passes, not tokens. The context window counts tokens. Not passes, not seconds. Nothing converts between them, and reaching one tells you nothing about how close you were to the other two: a run can sit at 28 % of its time budget, with no mention of context anywhere in the error, and still be over.

The three limits, side by side
LimitWhat it counts How it ends, what you keepWhat the error says
Turn cap Loop passes, and nothing else. On this lab's harness, terminates the run at the cap rather than asking it to wrap up, and there is usually nothing on disk. Not universal: the OpenAI Agents SDK ships a max_turns error handler for returning a controlled final output, and CrewAI documents its cap as forcing a best answer. Names turns, and usually the number.
Wall-clock timeout Seconds. Stops the run when the clock runs out. You usually keep what was written. Names a duration — and elapsed time will be roughly equal to the budget, by definition.
Context window Tokens. The only one that degrades before it stops you: a compaction, then a finished-looking answer built on less evidence. Frequently nothing at all.

The ten-second diagnostic

Read the termination string, and only the termination string.

Elapsed time is the one supporting reading worth taking, and only on the middle row. If the clock really did run out then elapsed matches the budget, because that is what a timeout is; so a run that ended a long way short of its budget was stopped by something that does not count seconds.

A worked case

From this lab’s own execution record of 2026-09-22. The run was budgeted 60 minutes and ended at 17, which is 28 % of the budget, so the middle row is out — a timeout that trips at 28 % is not a timeout. The termination string was:

Reached maximum number of turns (50) response: null cost: null

It names turns and gives the number, which is the top row, and the word context appears nowhere in it. Two rows cleared, one row named, on a single line of output.

The one that does not announce itself

The first two limits are events: one moment the run is going, the next it is over, and there is a line telling you so. The third is a slope. Because the context window degrades before it stops you, the thing to look for is not an error but the shape of a suspiciously good answer — complete, well organised, and thinner than the question deserved, because material went out during compaction to make room for what came next. Anyone who only ever looks for error strings will not detect this, and will keep the results.

Why the distinction decides the fix

If it was the turn cap

The reason the top row fills fastest is that on this lab’s harness a fetch is a tool call carrying exactly one item, with no batching inside the tool: one to two turns per item in practice when the calls are not batched, because the body comes back too large or too raw and costs another turn to grep. One assistant turn can carry several tool calls, so there is no floor of one turn per item — but an unbatched run's turn cost does grow with the number of items. The fix is to make turn count independent of item count — move the loop inside a single process so N items cost one turn instead of N. The cap then bounds reasoning steps, which is what it is for, and the only thing growing with N is a directory on disk.

The measured contrast, from this lab and stated with its provenance: on 2026-09-23, 51 URLs were fetched in 52 seconds inside a single turn, 31 of them returning 200, timestamps in that run’s own manifest — by an ad-hoc batch script of the kind the product on this site is the generalised form of, not by the product itself.

The move that crosses columns

Raising the cap looks like the cheap fix, and when your job is twelve items against a ceiling of ten it simply works. Past that it is the one to avoid, because it converts a loud failure into a silent one. One item per turn puts every fetched body into context, so the run that no longer dies at turn 50 starts quietly dropping evidence instead. The failure has not been fixed; it has been moved from the row that prints an error to the row that frequently does not.

You cannot read the cap, so plan against it by arithmetic

On this lab’s own host the turn limit was not in any of the four configuration files searched on 2026-09-24. So the way to stay under a cap you cannot look up is to multiply your plan out into items before you start. “Six surfaces, ten pages each” is 60 items, and 60 items do not fit under a 50-turn cap at one turn per item. That sum was available before the 2026-09-22 run started.

That is the full comparison: three counters, three units, three endings, and the one fix that only looks like a fix. Nothing below this line is needed to use it.

If you already know which one it was

What the offer page at ninemin.lilulab.ai adds to this one: this lab’s full record of the 2026-09-22 run rather than a comparison, and a description of batch.py — 271 lines, standard library only, Python 3.8+ — and of the $19 written guide, which is written and assembled — eleven sections, finished on 2026-09-24 — which since 2026-09-25 is on a storefront at $19 — though the listing does not open for sale until its payout details are connected, so there is still no way to pay for it today. The one button on this site lives there too, and records that you would have paid for it.