Session Loop Tool Calls#
After you have a Session and sandbox, the agent loop turns model tool calls into real tool execution. run_session_loop(...) appends an assistant row, executes tools, writes tool_result, and feeds the result into the next model request.
Coverage#
Topic |
Result |
|---|---|
Request assembly |
The agent Session comes first, followed by the user Session. |
Tool schema |
Built-in and custom tools are merged into the schema visible to the model. |
Tool round |
The assistant emits tool calls, then the loop executes tools and appends |
Output Session |
The output Session inherits user-side rows and appends new rows. |
Sandbox sharing |
The input Session’s sandbox handle is shared with the output Session through refcounting. |
Step 1: Prepare Agent and User Sessions#
from rath import flow
from rath.session import Session, run_session_loop
agent_session = Session.from_agent_prompt(
"Use tools when the user asks for file work."
)
user_session = Session.from_user_message(
"Create a file, then read it back."
).to("local")
provider = flow.Provider(api_key="sk-...", model="gpt-5.5")
Key lines:
Line |
Explanation |
|---|---|
|
Creates a system chunk for the agent-side Session. |
|
Creates a user chunk for the user-side Session. |
|
Binds the user Session to the local Backend so tools have an execution location. |
|
Stores the model configuration for this request. |
Step 2: Run the Loop#
In real runs, run_session_loop(...) uses the default executor to issue an OpenAI-compatible request. Tests and tutorials can pass a scripted executor to make model responses deterministic.
out = run_session_loop(
user_session=user_session,
agent_session=agent_session,
agent_provider=provider,
executor=scripted_executor,
)
The executor is responsible for two operations:
Method |
Purpose |
|---|---|
|
Returns one chat completion response. |
|
Executes the selected |
When no executor is passed, OpenRath creates DefaultSessionLoopExecutor and uses the default OpenAI-compatible client. In that mode, configure the model gateway through process environment variables or your deployment secret store.
Step 3: Understand One Tool Round#
When the model returns a tool call, the loop appends an assistant row, executes the tool, then appends a tool result row:
user
assistant contains tool_calls
tool_result contains serialized tool output
assistant final answer or next tool_calls
This ordering comes from run_session_loop(...):
Stage |
What happens |
|---|---|
Completion |
The model returns an assistant message from the messages and tools. |
Assistant row |
If there is a tool call, the assistant row is added to |
Dispatch |
The loop finds the matching |
Tool result row |
The tool result is serialized as JSON text and written to a |
Next completion |
The next request includes the earlier assistant row and tool result row. |
Step 4: Inspect the Chunk Table#
for row in out.chunk_table.rows:
print(row.kind, row.payload)
If the model writes a file and then reads it back, the typical order is:
user
assistant # write_workspace_file call
tool_result # bytes_written
assistant # run_shell_command call
tool_result # command stdout / stderr
assistant # final answer
Observed behavior:
The
namein thetool_resultrow matches the called tool name.The
contentin thetool_resultrow is the tool output visible to the next model round.The output Session still starts with user-side content; the agent system prompt is not copied into it.
Step 5: Confirm Sandbox Sharing#
sandbox = out.require_sandbox()
print(sandbox.backend.name)
run_session_loop(...) shares the input user Session’s sandbox handle with the output Session (refcount +1). If another agent or Workflow runs later, tools can still use the same sandbox. Either Session can call close_sandbox() independently; the backend closes only after the last reference is released.
Troubleshooting#
Symptom |
Check |
|---|---|
Model did not call a tool |
Check whether the system prompt, user prompt, and tool schema are explicit enough. |
|
The tool name returned by the model is not in the tool table. |
|
The model returned JSON arguments that could not be parsed. |
Tool execution failed |
Check the message and detail in |
Tool cannot find a sandbox |
Confirm the user Session has already called |
Exercises#
Change the user prompt to “Answer only; do not call tools” and observe whether
tool_resultstill appears in the chunk table.Pass a custom tool into
run_session_loop(...)and confirm the tool table includes it.Run
run_session_loop(...)twice in sequence and confirm the second agent can see thetool_resultleft by the first agent.
Summary#
run_session_loop(...)assembles agent/user messages and starts a completion.Built-in tools come from
global_system_tools(), currently includingrun_shell_commandandwrite_workspace_file.Tool results are serialized into
tool_resultchunks for the next LLM request.The output Session is the core object for continuing work in later Workflows.