The meeting has just ended. You save the notes in your working directory and send OpenClaw a short request:
Read
notes/meeting.mdand list the three things I need to do.
First, the screen says, “Let me look at the meeting notes.” Then the file read finishes. Finally, a tidy list of action items appears. It feels straightforward: you ask, the assistant gets to work, and it hands back the result.
Slow this hypothetical scene down, though, and an interesting gap appears: if the file has already been read, why isn't the answer finished? Who hands the file contents back to the model? And if the assistant says only “Let me look” before falling silent, should the system count the request as successful?
In the previous article, we stood at the Gateway and watched it distinguish accepting a request from finishing a run. This time, let's follow those meeting notes inside an Agent execution.
The source snapshot is OpenClaw v2026.5.22, following the path that selects its built-in Pi harness. This version pins the Pi packages to 0.75.4. OpenClaw supports other execution paths, so this journey does not describe every harness's internals. The dependency pins and harness selection code establish that scope.
The Message Arrives. The Model Can Wait a Moment.
Imagine an assistant written in a few dozen lines: receive some text, attach the conversation history, call a model, and display its answer. If the model asks to read a file, read it and call the model again. That is enough for a demonstration.
Now let that assistant live in your working environment. Two messages may arrive in the same conversation at once. Earlier turns have left a history. The working directory determines where “this file” lives. Available tools cannot simply be whatever the model decides they should be. None of these concerns disappears when you switch model providers.
OpenClaw therefore does some organizing before the model call. Along the path we are tracing, the request enters a session queue and is also subject to a global execution queue. Model, workspace, session history, and tools are then prepared. This does not mean the entire machine can do only one thing at a time: the different queue layers define different concurrency boundaries. Queue entry point
For our meeting notes, the purpose is practical. Another task in the same conversation should not arbitrarily interfere with the context this run is using. And the model needs more than a bare “read this for me”: it needs to know which capabilities are available.
OpenClaw then hands the prepared run to the selected harness. The built-in Pi harness enters OpenClaw's preparation for a single execution attempt, creates a Pi AgentSession, supplies its model and tools, and submits the user's prompt. OpenClaw prepares the working environment; Pi's core loop advances the exchange between model and tools. Session management and event subscriptions connect the layers, so this is more than a simple function forwarding a request. Session creation and prompting
The First Response Proposes an Action
The model now sees your request. Suppose it decides to read the file and writes, “Let me look at the meeting notes.”
What follows may be a structured tool call rather than more prose: a tool named read, a file path among its arguments, and a call ID for matching the result. To make that relationship visible, we can simplify it as follows; the precise arguments depend on the registered tool:
assistant
text: Let me look at the meeting notes.
toolCall: read(path="notes/meeting.md"), id="read-1"
The model has finished one response, but the three action items do not exist yet. It has handed over the next action to perform.
The file is actually accessed by a tool function registered in the host program. Pi looks up the tool, validates its arguments, runs the before-tool hook, and calls the tool's execute function. When the tool returns, the loop packages its output as a toolResult, using toolCallId to connect it to the requested action. Tool execution entry point
This division is worth pausing over. If the model saying “read successfully” counted as evidence that a file had been read, the system could not distinguish an event from a sentence. Structured calls keep them separate: the model proposes an action, the program performs it, and an actual result is recorded. Tool names and arguments also create a boundary that can be inspected, rather than prose the runtime must guess how to interpret.
That does not mean an execute function automatically provides complete security. OpenClaw's tool selection, permissions, and sandbox constraints belong to the surrounding runtime. For now, remember the distinction: a model expressing an action does not mean it has performed that action itself.
Reading the File Only Gets Us Halfway
The read tool retrieves the notes. Suppose they contain three action items: confirm the scope, run regression checks, and send the release notes.
If the answer is already in the file, why not simply display the tool output? Because your request was to list the three things you need to do. Real meeting notes may also include the discussion, other people's assignments, and plans that were later dropped. The file is evidence; the answer still needs to be organized around your question.
Pi puts the tool result back into the current context and calls the model again. This time, the model sees more than the original question: it sees the user request, the read action it proposed, and the contents returned by the tool. The tool result does not pretend to be another user message. It has its own role and correlation ID. Loop implementation
One request in this simple scene therefore produces four important records:
user → Read the notes and list my three action items
assistant → Let me look + a read tool call
toolResult → The actual contents of the meeting notes
assistant → The three organized action items

The two model calls belong to this particular example. If more files need to be read, the loop can continue.
This is why model-call counts cannot stand in for user-request counts. A single request can contain several rounds of model output and tool execution. The first response decides where to look; a later response uses what came back. The Agent feels continuous because the program connects these steps into one process.
The implementation also has entry points for steering and follow-up messages. A turn with no new tool calls does not necessarily end the loop: pending messages may keep it moving. Conversely, an explicit stop hook or tool results with termination semantics can end it early. “Read, then always call the model again” is therefore not a universal rule. It describes the ordinary read path in our example.
What If “Let Me Look” Is All You Get?
Now introduce a small mishap. The read completes, but the subsequent response never arrives normally. “Let me look at the meeting notes” is still sitting in the chat window.
To a person, that plainly does not look finished. To a program checking only whether any text was produced, however, the run could look successful. A polite sentence before the tool call might count as a valid answer.
An OpenClaw fix addressed exactly this problem. PR #76544 handles the case where text appears before a tool call but the final response afterward is missing: earlier text must not suppress incomplete-turn detection. In the snapshot we are reading, the relevant check looks at whether the last assistant message still ends with toolUse; previously visible text no longer hides that signal. Incomplete-turn detection
There is a useful lesson here. “The interface appears responsive” and “the runtime reached a valid endpoint” are different pieces of information. Progress narration is helpful, but it should not substitute for a terminal state.
Do not reverse that into a requirement that every tool execution must be followed by another natural-language paragraph. Some tools have already delivered a message to its destination; some paths explicitly terminate. Completion has to follow the execution protocol and the actual result, rather than force every task into the same conversational shape.
When Something Fails, Bring Back the Facts
Consider a different problem: the file does not exist, or the read tool throws an error.
On this Pi execution path, an exception from tool execution becomes a tool result marked with isError and is passed into the subsequent context. The model can then explain that the file could not be found, or adjust its next action if the available capabilities allow it. The conversation need not collapse into an unhandled program exception.
That differs from the model itself stopping with error or aborted, which ends the current core loop. Whether the surrounding runtime retries, switches models, or returns an error response is a question for OpenClaw's outer control flow. It cannot be inferred from the inner loop alone. Error and stop branches
Treating failure as a structured result is the second design worth learning from. It keeps “what happened” connected to “what happens next.” Recovery does not, however, justify repeating every operation without conditions. Reading a file is usually straightforward to repeat. Sending a message, creating a task, or charging an account is a different matter: a retry can perform a real-world action twice.
The List Is Written. There Is Still a Little Way to Go.
At last, the model produces the three action items, the current loop has nothing more to do, and Pi emits agent_end. The name makes it tempting to assume everything has finished.
On this OpenClaw path, though, the inner loop ending and the outer run reaching its terminal state remain separate. The outer layer processes the result and performs subsequent work such as reply delivery where applicable. The source explicitly defers the terminal lifecycle event to that outer processing. Outer completion boundary
Session records are not all saved in one batch at the very end, either. The session layer handles record appends as messages finish. Session event handling Leaving an execution attempt also involves pending tool results, event subscriptions, and session resources that must be cleaned up.
A concrete engineering lesson is tucked into that cleanup: do not “repair” a missing tool result too early. A source comment explains that if a tool in a retried execution is still running, prematurely filling gaps in the transcript can insert a synthetic missing-result error. Normal cleanup therefore makes a best-effort attempt to wait for the Agent to become idle before flushing pending results. The wait is bounded, and cancellation paths shorten or skip parts of it. It is not an indefinite guarantee that all background work has ended. Cleanup entry point and bounded waiting implementation
From the user's perspective, all of this hides behind a simple checklist. Yet it determines whether the next message encounters a usable conversation or a collection of intermediate states that no longer line up.
Putting the Story Into a Repeatable Experiment
To check the sequence, I ran a small experiment against the original published Pi 0.75.4 loop module pinned by OpenClaw. A deterministic model stub returns a read action on the first call and a checklist on the second. The read tool actually accesses a temporary local file. The fixture uses the shorter name meeting.md; its three items are written beforehand, and the final checklist is also preset by the stub.
The observation was one request, two model calls, and one file read. The second call did receive the file contents, and the record sequence was user → assistant → toolResult → assistant. Including branches for tool failure, stop hooks, and OpenClaw's cleanup waiting, 27 focused checks passed.
This verifies how the loop advances, not whether a model understands meeting notes. Argument validation was stubbed, and the experiment did not start the full OpenClaw runtime, connect to a real model, or reproduce a live channel. It is therefore not evidence of permission enforcement, model quality, or end-to-end reliability.
If I were building this small assistant from scratch, I would start with three clear interfaces: the model produces actions, tools return results with correlation IDs, and the loop decides whether to continue or stop. Sessions, concurrency, and recovery would follow. OpenClaw shows the complexity those capabilities acquire in a real product. Reading across responsibility boundaries makes that complexity easier to understand and replace than collecting everything into an ever-growing loop.
Return to the original “read this for me.” The interesting part is not only what the model eventually writes. It is whether the system can retrieve information when the model needs it, bring back facts when an action fails, and distinguish progress, results, and cleanup when it is time to stop. That apparently effortless checklist is assembled one step at a time.
Next, we will follow the same read call further: how are the tools presented to the model selected, and who decides whether they can actually execute?

