Day 111 ยท Giving the polymath hands

Tool Use & Function Calling

You will be able to
  • Explain the full tool loop: request โ†’ tool_use โ†’ execute โ†’ tool_result โ†’ final response
  • Define tools with JSON Schema and write descriptions the model can route on
  • Implement the loop in runnable code with multiple tools, parallel calls, and error feedback
  • Return tool errors as is_error results so the model can recover instead of crashing the loop
  • Apply safety boundaries: input validation, never eval, allowlists, and loop caps
Today's ~120 minutes
Spaced-rep warm-up: due cards (schemas, extraction)10 min
Tech read: protocol, design, safety boundaries20 min
Guided: the full loop with three tools35 min
Guided: routing probes15 min
Practice: save_note with guardrails20 min
Project: ToolBelt class + quiz + flashcards20 min

Builds on: Day 106 โ€” The request & message roles ยท Day 110 โ€” Schemas & validation ยท Day 107 โ€” The client wrapper

The analogy

The polymath knows nearly everything but can DO nothing: no calculator, no weather station, no filing cabinet. Tool use gives them hands โ€” with a twist that surprises everyone the first time: the model never executes anything. You hand the polymath a card describing each tool on the wall โ€” its name, what it is for, what information it needs. When a question needs a tool, the polymath does not act; it writes you a work order: "please run calculator with expression 23.7 times 481." YOUR code runs the tool, writes the result on a slip, and hands it back. The polymath reads the slip and either writes another work order or gives the final answer.

That is the whole trick โ€” a conversation with homework between turns. The model contributes judgment: which tool, what arguments, when to stop. You contribute execution: real code, real APIs, real consequences. Which is why safety lives on your side of the counter: the polymath can ask for anything; your code decides what requests are legal, checks every argument, and refuses politely when the work order says "delete the production database." Give the polymath hands, but you keep the keys.

Why this matters on the job

Tool use is the hinge between "language model" and "system that does things" โ€” it is how LLMs get calculators (fixing Day 96's arithmetic embarrassments), fresh data (fixing the knowledge cutoff), and the ability to act. Every agent you build from Day 120 onward is literally this loop plus planning and memory; MCP (Day 124) is a standard for distributing the tool cards. It is also the sharpest safety boundary you will own: the difference between an assistant that reads your calendar and one that can be tricked into emailing it to a stranger is the engineering you learn today. Modern AI-engineer interviews routinely ask you to whiteboard exactly this loop.

Watch it happen

Giving the polymath hands โ€” one tool call, end to end

step 1 / 5
Your appholds the toolsโ†’LLMdecidesโ†’Tool runsyour codeโ†’LLMcomposesโ†’Answer
โœ‰ messages + tools: [get_weather(city), search_docs(query)]

Your app sends the question plus a MENU of tools (name, description, JSON schema). The model can't run anything โ€” it can only ask.

Guided practice

guided 1

The full loop, from scratch

35 min
  1. Create toolbelt.py with the starter: three tools โ€” a safe AST-based calculator, a mock weather lookup, and a mock docs search โ€” plus the complete loop.
  2. Run question 1 ("What is 23.7 * 481 - 19?") and watch the trace: tool_use โ†’ your execution โ†’ tool_result โ†’ final answer.
  3. Run question 2 ("Compare the weather in Lisbon and Warsaw") โ€” observe PARALLEL tool_use blocks in one response, both answered in one user message.
  4. Run question 3 ("Find the retry policy in the docs and calculate the total wait for 4 attempts") โ€” a genuine multi-step chain.
  5. Trigger the error path: ask "What is ln(-5)?" and confirm the is_error result comes back and the model explains the problem instead of crashing.
  6. Read your printed trace end-to-end once โ€” this trace IS the tool-loop visual, produced by your own code.
๐Ÿ python โ€” editable, runs in your browser
Ctrl/โŒ˜+Enter runs ยท Tab indents ยท numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)
guided 2

Probe the routing

15 min
  1. Ask a question needing NO tool ("What is a context window?") โ€” confirm the model answers directly with stop_reason end_turn. Good routing includes not using tools.
  2. Sabotage a description: change the calculator description to just 'A tool.' and re-ask question 1. Does the model still route correctly, do math itself, or misroute? Restore the description and write the one-line lesson (descriptions are the routing signal โ€” Day 108 specificity again).
  3. Ask something no tool covers ("What is the weather on Mars?") and observe the honest failure path via the error result.
  4. Count iterations for the multi-step question and note how the cap protected you.

On your own

Extend the belt: a real tool with guardrails

20 min

Add a fourth tool with real side effects handled safely: save_note(title, content) that writes a markdown file into a notes/ directory.

Requirements: schema with both fields required; filename derived from the title but sanitized (strip path separators and dots โ€” the model must not be able to write to ../../etc/anything); reject titles over 100 chars with a helpful is_error message; and a dry-run mode flag that reports what WOULD be written. Then ask: "Search the docs for rate limits and save a note summarizing them" โ€” a chain of read tool into write tool.

Hints: path traversal via model-controlled filenames is a real vulnerability class (Day 132 formalizes it); use pathlib and verify the resolved path stays inside notes/; this validate-before-execute pattern is exactly Day 125's approvals story in miniature.

Ship before you stop

toolbelt.py โ€” the loop you will reuse for weeks

Harden today's code into the toolkit: a ToolBelt class where tools register with name, description, schema, and function; a run() that executes the loop with iteration caps, per-call logging to your JSONL format (tool name, args, latency, error flag), and a transcript printer for debugging. Ship the four tools, plus a README section "Adding a tool safely" codifying your rules (validate args, no eval, sanitize paths, cap loops, is_error on failure). Push it. Day 120 imports this file verbatim as the substrate of your first agent; Day 124 replaces its registry with MCP.

Rubric โ€” check what you completed (0/6)

Common mistakes & misconceptions

  • Believing the API executes tools. It only emits work orders; execution, and therefore all risk, is your code. This also explains why tools can do anything your code can do โ€” no more, no less.
  • Dropping the assistant's tool_use message from the transcript. The tool_result must follow the assistant turn containing its tool_use_id โ€” mismatched or orphaned ids break the conversation.
  • Answering parallel tool calls across several user messages. All results for one assistant turn go back in ONE user message, one tool_result block per id.
  • Raising exceptions out of the loop on tool failure. Return is_error results instead โ€” the model reads errors and self-corrects; your crash handler cannot.
  • Writing lazy descriptions. The model routes on descriptions; "A tool." causes misrouting that no amount of loop code fixes.
  • Leaving the loop unbounded. Tool ping-pong can run forever and bill accordingly; cap iterations and spend, and surface the cap as an honest failure.
Knowledge check

Q1. Who executes a tool call?

Q2. A response contains two tool_use blocks. The correct reply isโ€ฆ

Q3. Why return failures as is_error tool_results instead of raising?

Go deeper โ€” curated resources

docsClaude Docs โ€” Tool use overview (the protocol, schemas, tool_choice) โ†—30 minarticleLilian Weng โ€” LLM Powered Autonomous Agents (tools as the action space) โ†—25 min (tool-use sections)docsModel Context Protocol โ€” where tool definitions are heading โ†—10 min (skim, full treatment Day 124)
If you have a third hour
  • tool_choice and forced calls โ€” The API can force a specific tool (tool_choice) โ€” useful for guaranteed-extraction patterns. Explore when forcing beats letting the model route, and how it interacts with structured outputs.
Done means
  • All three trace types observed: single, parallel, and chained tool calls
  • Error path verified: is_error result produced and model recovered
  • save_note blocks a path-traversal attempt (demonstrated, not assumed)
  • ToolBelt class pushed with logging, caps, and the safety README
  • Quiz โ‰ฅ 2/3
How this connects

โ† Back: Tool arguments are Day 110's schema-constrained outputs in another costume; the descriptions you wrote are Day 108's specificity doing routing work; and the loop's transcript rules extend Day 106's message anatomy.

Forward โ†’: Day 112 stress-tests everything this week built. Day 120 wraps this exact loop with planning and budgets to make your first agent; Day 124 standardizes tool distribution with MCP; Day 125 adds approvals for side-effect tools; and Day 132 attacks โ€” then defends โ€” this boundary.

Unlocks: D112 Week 16 Checkpoint: The Prompt Lab ยท D118 Advanced RAG Patterns ยท D120 Agents I โ€” The Loop ยท D123 Multi-Agent & Workflow Patterns