22.3 Reading a session: events and stop reasons
- Approved by
- Panaversity ·
About fifteen minutes. In Chapter 20 your loop read the model's stop reason after every call. A hosted session reports one level up: the platform runs the whole loop and reports each step as an event. You learn to tell, from the log alone, why the session went quiet. Read each log, predict the last line, then compare.
In everyday life. A dispatcher at a delivery company watches a board of trucks. A truck that stops moving might be finished for the day, waiting at a loading dock for someone to sign, or out of fuel. The dispatcher does not guess. Each truck reports why it stopped, and the board shows it. In this concept, each truck is a session, and its reason for stopping is the stop reason.
What you will learn. How to read what a running worker reports, step by step, and how to tell from its last line why it went quiet: done, waiting for a person, or out of money.
Why it matters. A quiet worker is not always a finished one. A product that guesses can show a half-done answer, or leave a person's question waiting forever.
One request, start to finish. Luis signs in to the AP portal as Cedar Ridge and asks: "Which of our invoices are open?" The portal starts a session, sends the question, and listens. A few seconds later the session goes quiet. Is it done? Waiting for Luis? Out of money? The portal reads the last event and knows.
What are events and stop reasons?
An event is one message between your product and a session. Some go in: the person's question, an answer to a confirmation, an interrupt (a request to stop the current work, not a call waiting for approval). Most come out: the worker's tool calls, the tools' results, its answer, and the session's own status. A session's history is all of its events, kept by the platform in order, so your product can fetch them again later. The platform keeps them until you delete the session, so delete what you no longer need. Your server receives them as they happen through an event stream: server-sent events, one long web request that the platform keeps open and writes each event into. Your server forwards them to the person's page.
A session is either running, working through the loop, or idle, waiting. When it goes idle, it gives a stop reason. This is not the model's stop reason from 20.3. The model still stops after every call, but the platform handles those stops inside the session. What you see is why the whole session went quiet. Three reasons matter most:
| Stop reason | What it means | What your product does |
|---|---|---|
| Finished | The worker gave its answer, or your product interrupted it, and it has nothing more to do | Show the answer. The session can take another question |
| Needs action | A tool call is waiting for a person to allow or deny it (22.8) | Show the person the call, and send their answer back |
| Budget reached | The session hit its spending cap (22.5) | Tell the person, and raise the cap or end the run |
Two more states happen rarely. A session may be retried after a brief failure on the platform's side, and your product only needs to wait. And a session may be terminated, ended for good, by your product or by an error it cannot recover from.
How do you read the logs below?
The lab's logs have one event per line. In this concept they are shown in plain words, with the same fields every platform reports. These three logs are simplified. They follow the platform's event shapes, cut to the lines that matter, with long ids shortened. Your own lab run, in Tasks 3 and 4, gives you real ones to compare. Write your prediction down before you read the last line.
Log 1. A question that finishes
1 in message "Which of our invoices are open?"
2 status running
3 out tool call list_open_invoices {} permission: allow
4 out tool result 16 invoices, total $21,329.00
5 out message "Cedar Ridge has 16 open invoices, $21,329.00 in all. The largest is ..."
6 status idle stop reason: ?Predict: what is the stop reason on line 6?
6 status idle stop reason: finishedIn plain words: one question in, one tool call, one result, one answer, and nothing left to do. The permission: allow on line 3 says the call ran without asking anyone, because the builder reviewed that tool and allowed it (22.8).
Log 2. A tool that asks first, before it was reviewed
1 in message "What does our purchasing policy say about repairs?"
2 status running
3 out tool call search_policy {"query": "repairs"} permission: ask
4 status idle stop reason: ?Predict: this run was made before search_policy was reviewed for the hosted worker, so its policy was still "ask", the default for connector tools (22.8). The lab later sets it to "allow". What is the stop reason, and what happens if nobody answers?
4 status idle stop reason: needs action, waiting on event 3
5 in confirmation event 3: allow
6 status running
7 out tool result 2 passages, purchasing.md lines 5 and 6
8 out message "Purchases of $500.00 or less, such as a small repair, ..."
9 status idle stop reason: finishedIn plain words: the session stopped and named the call it was waiting on. It waits with no time limit. Nothing happens until a person answers, and here Luis allowed it on line 5. If the portal never shows him the question, the session waits forever.
Log 3. A run that hits its cap
The session has a budget, a cap in dollars, of $0.50. List cost is what the session has spent so far at the platform's published prices (22.5).
1 in message "For every open invoice, check its PO and its vendor's notes."
2 status running
3 out tool call list_open_invoices {} permission: allow
4 out tool result 16 invoices
5 out tool call get_purchase_order {"invoice_number": "INV-6201"} permission: allow
... (twenty more calls)
26 out usage list cost so far: $0.51 of $0.50
27 status idle stop reason: ?Predict: the cap was $0.50 and the cost is $0.51. Which stop reason, and why is the cost a cent over?
27 status idle stop reason: budget reachedIn plain words: the platform checks the cap between model calls, so the call already under way finished and pushed the cost a cent past it (22.5). The session keeps its history and its sandbox. It will not take a new question until the cap is raised.
Where do logs surprise you?
| What you might expect | What happens |
|---|---|
| A quiet session is a finished one | It may be waiting for a person, or out of budget. Read the stop reason |
| A session waiting for a person times out | It waits with no limit until your product answers |
| The cap stops spending at exactly the cap | The call under way finishes, so the total can land slightly past it |
| An event stream that drops loses the events | The history is kept. Open a new stream, read the history, and skip events you have already seen |
| Every tool call shows its permission | Every call to a connector or a built-in tool does. Tools your own product runs do not (22.8) |
What do you ask the agent about any log?
As in Chapter 19, each answer is checked against the log:
- "What is the last status line, and what is its stop reason?"
- "Which tool calls ran without asking, and which waited?"
- "What did this run cost, and what was its cap?"
- "Which event is the session waiting on, if any?"
At work. In Lab 22, Task 3, the builder asks Claude Code to start a session with no connector, stream its events to the terminal and stop before the last line. The builder writes down a prediction for the stop reason in ports/ch22.md, then lets the stream finish. In Task 4, the same happens with a one-cent budget.
The operating rule: never treat a quiet session as finished. Read its stop reason, and read the full history again whenever the stream drops.

Figure 22.7. One session, three ways to go quiet. The stop reason says which.
Check yourself
Question 1 / 8
0 answered
A session's last line reads idle. What must the portal do before telling Luis the answer is ready?
- Owner
- Panaversity