Every lesson so far in this course has described tool use from the outside: what a tool declaration looks like, what a `tool_use` block contains, what a `tool_result` is supposed to reply with. None of that description tells you what actually breaks when you wire it up yourself for the first time — the ordering bug that silently corrupts a conversation, the id that almost matches but doesn't, the loop that never terminates because nothing told it when to stop. This lesson is where you build the thing rather than read about it.
By the end you will have written two real tools with genuine input schemas, a dispatcher that validates arguments and never lets an exception escape unhandled, and an agent loop that runs while `stop_reason` is `"tool_use"`, appends messages in the order the API requires, and gives up cleanly after a fixed number of turns instead of spinning forever. The final run answers a question that genuinely needs two different tools called one after another, and prints the full message trace so you can see the conversation grow turn by turn.
Every code block in this lesson runs without an API key. A small `FakeClient` class returns scripted responses shaped exactly like the real `anthropic` SDK's `client.messages.create(...)` output — same `.content` list of blocks, same `.stop_reason` string — so the loop logic you write against it is identical to the loop logic you would run against `anthropic.Anthropic()`. The swap from fake to real is a single line, marked clearly where it happens, and nothing else in the loop changes. That is not a simplification for teaching purposes; it is the actual point of building the fake client this way.