Trace a Tool Call and Session

Exercise objective

Trace one read_file Tool Call and observe how data changes across the Provider response, ToolRegistry, checkpoint, next model input, and final Session.

Prerequisites

  • Complete the previous Tool-free Turn exercise.
  • Understand the OpenAI function schema.
  • Use a separate lab workspace.

Source to read

  1. nanobot/agent/tools/filesystem.py::ReadFileTool
  2. nanobot/agent/tools/registry.py::ToolRegistry.execute
  3. nanobot/agent/runner.py::_execute_tools
  4. nanobot/agent/runner.py::_run_tool
  5. nanobot/agent/runner.py::_emit_checkpoint
  6. nanobot/agent/loop.py::_state_save
  7. tests/agent/test_runner_tool_execution.py
  8. tests/agent/test_runner_persistence.py

Predict before running

  • What shape does the Tool Call have in the first Provider response?
  • Under which role is the tool result appended to messages?
  • Is the complete Session persisted immediately after Tool execution?
  • Which messages appear in the second Provider request but not the first?
  • Does the user receive both the raw tool result and a natural-language answer?

Procedure

1. Prepare a read-only fixture

$nanobotLab = Join-Path $env:TEMP "nanobot-learning"
$fixture = Join-Path "$nanobotLab\workspace" "turn-observation.txt"
Set-Content -LiteralPath $fixture -Encoding utf8 -Value "marker=NANOBOT_TOOL_OK"

This writes only to the lab workspace; it does not modify nanobot source code.

2. Set breakpoints

  • after AgentRunner._request_model() returns;
  • in _execute_tools();
  • before and after validation in ToolRegistry.execute();
  • in ReadFileTool.execute();
  • in _emit_checkpoint();
  • at the next _request_model() call;
  • in _state_save().

3. Send an explicit request

python -m nanobot agent `
  --config "$nanobotLab\config.json" `
  --workspace "$nanobotLab\workspace" `
  --session "learning:tool-call" `
  --message "You must use read_file to read turn-observation.txt, then reply with the marker value only."

A real model may still choose differently. If it does, preserve that observation and complete a deterministic trace with the fake Provider used in the tests.

4. Build a message-shape table

MomentRoleKey fields
Initial inputusercontent
First Provider responseassistanttool_calls
After Tool executiontooltool_call_id, name, content
Second Provider responseassistantfinal content

Do not copy the complete prompt. Record only the structure and a short summary.

5. Inspect the checkpoint

After _emit_checkpoint(), inspect the running checkpoint in Session metadata:

  • phase;
  • iteration;
  • model;
  • assistant_message;
  • completed_tool_results;
  • pending_tool_calls.

After a normal SAVE, determine whether that checkpoint was cleared or materialized into official history.

6. Inspect the Tool schema

Before the first Provider request, evaluate:

spec.tools.get_definitions()

Find read_file and compare its schema with the arguments returned by the model.

Expected observations

sequenceDiagram
    participant P as Provider
    participant R as AgentRunner
    participant T as ToolRegistry
    participant S as Session

    R->>P: messages + Tool schemas
    P-->>R: assistant(tool_calls)
    R->>S: checkpoint awaiting_tools
    R->>T: execute read_file
    T-->>R: marker=NANOBOT_TOOL_OK
    R->>S: checkpoint tools_completed
    R->>P: + assistant Tool Call + tool result
    P-->>R: final text
    R-->>S: SAVE final Turn

The central conclusions are:

  • Tool schemas are generated before the model request;
  • Registry validates arguments again in Python;
  • a tool result is the model’s observation in the next iteration, not a direct user response by default;
  • checkpoints support recovery after cancellation or interruption;
  • a normal SAVE writes valid messages from this Turn to the Session.

Completion criteria

  • Identify the difference between messages in the two Provider requests.
  • Correlate the assistant invocation and tool result through their Tool Call ID.
  • Explain the difference between a checkpoint and the final Session.
  • Obtain the final response NANOBOT_TOOL_OK.
  • Do not modify source code.

Verification

Run the deterministic tests:

Set-Location "example\nanobot\code-EN"
python -m pytest tests\agent\test_runner_tool_execution.py -q
python -m pytest tests\agent\test_runner_persistence.py -q

Single-step through one test and compare its object shapes with the real DeepSeek invocation.

Review questions

  1. Why is the Tool schema both shown to the model and validated locally?
  2. If a Tool has already written a file when the Runner is canceled, can the checkpoint roll that write back?
  3. Why can the final assistant message not be omitted?
  4. How does an oversized tool result affect the next model request?

Next: Reproduce streaming, cancellation, and retry