A customer opens a support chat and asks where their order is. The window says “typing…”. Ten seconds pass. Thirty. A minute. They refresh, lose the conversation, and call a human, more annoyed than if the chat had never existed.
Nobody decided that should happen. It happened because nobody decided when the conversation must end.
This is an illustrative scene, not a customer story. But every part of it is a failure I reproduced on purpose in a test build of a support agent, and then closed.
What “termination” means
Termination is a guarantee: whatever the model does, every session ends in one of two states, resolved or escalated to a human, within a known time.
The guarantee has two halves. A step cap limits how many times the agent may think, call a tool and think again. A time limit limits how long any single wait may last. Both are enforced by ordinary program code that wraps the model, not by a sentence in the prompt asking the model to “stop after a few tries”.
An analogy. A pilot chooses the route, the altitude and the speed. But the fuel limit and the diversion rule are fixed before take-off, and when the fuel reaches the threshold the plane diverts, however well the flight seems to be going. Nobody relies on the pilot feeling that it is time to land.
session flow · 3 time limits, 1 escalation exit
There are two ways out. The model finishes and the session is resolved, or any limit fires and code sends the customer to a human. There is no third path where the session simply waits.
Why it is needed
An agent is a loop in which the model decides the next step. That is its strength, and it is also the problem: the thing deciding whether to continue is the same thing that may be confused.
In one test I gave the agent a lookup that never finished and told it, in the tool result, to call the same tool again. It did, on every step. The model never gave up. Only the step cap stopped it.
Three things follow for anyone running such a system:
• Cost. Every extra step is a paid model call, and nobody sees it happen.
• Customer harm. A person is waiting on the other side, and a hung session is worse than an honest hand-off.
• No audit trail. A session that never ends never produces the record of why.
A prompt line saying “stop after three attempts” does not fix this. It asks the confused component to notice that it is confused.
What I built
The support agent in my test project is a small system: a router, three narrow specialists and a human hand-off. Termination is built into the loop that every specialist shares.
• A step cap. The loop is a bounded for, not a while (true). Specialists get 4 steps. The default is 6.
• Four forced exits. If the cap is reached, the model API errors, the final reply is empty, or the model stops for a reason the code does not expect, the code escalates to a human. The model is not asked.
• Time limits on every wait. The classifier call and the planner call are each limited to 30 seconds. A specialist is limited to 60 seconds.
• A human request is never held up. The classifier alone decides when a customer asks for a person. A slow planner cannot delay it.
Add the router limit (30 s) to the specialist limit (60 s) and a session ends in about 90 seconds at most. When a limit fires, the customer gets one fixed line: “I’m passing you to a human agent who can help you from here.”
The loop, simplified:
for (let step = 1; step <= maxSteps; step++) {
const reply = await callModel(...); // an error -> escalate: api_error
if (reply.stop_reason === ‘end_turn’) { // empty text -> escalate: empty_final_reply
return resolved(reply);
}
if (reply.stop_reason !== ‘tool_use’) { // anything else -> escalate: unexpected_stop_reason
return escalate(’unexpected_stop_reason’);
}
// run only the tools this specialist is allowed, feed the results back, loop
}
return escalate(’step_cap’); // ran out of steps
Where it broke
After the loop test I had a bounded loop and a good feeling. Then I injected failures on purpose, predicting each result before the run and writing the predictions down first.
The loop was bounded. The code around it was not.
The router makes two model calls before any specialist runs: a classifier and a planner. Neither had a time limit. Three rows tested that:

Questions to ask your team
1. What is the longest a session can last, and the most steps it can take? Is that number set in code or in a prompt?
2. Does every external wait (the model, each tool, the database) have its own time limit?
3. What does the customer see when a limit fires, and who receives the hand-off, within how many minutes?
4. Can I see the failure log: which failures you injected, what you predicted, what happened before and after each fix?
5. What is still open, and what happens to a call you have given up on?
If the answer to the first question is “the model knows when to stop”, you have your answer.
The one-line takeaway
An AI system that cannot show you how every session ends is still a demo: ask for the termination guarantee, and ask to see the failure log.




