// Foundations · ~13 min
Tool Use / Function Calling
Reach for it when: When the model must call structured tools instead of inventing facts.
// 60-second mental model
How to hold it in your head
Give the model named tools with schemas. It picks a tool and fills arguments. You run the tool. It reads the result — it does not invent the payload.
Tool use / function calling binds the model to declared tool schemas; the runtime validates args, executes the tool, and returns observations as structured data.
// Mini architecture
Schema → select tool → validate args → execute → observe
┌──────────────┐
│ User request │
└──────┬───────┘
▼
┌──────────────┐ schemas ┌────────────┐
│ Model │ ◄────────────── │ Tool catalog│
│ (pick+args) │ └────────────┘
└──────┬───────┘
▼
┌──────────────┐
│ Validate args│ ── reject → ask model to fix
└──────┬───────┘
▼
┌──────────────┐
│ Run tool/MCP │ → observation → model → answer
└──────────────┘No tool call means no invented “API result”. If the schema rejects the args, fix and retry — do not freehand JSON.
// Mini-project
Weather via typed MCP tool (stub)
Claude Code / MCP function-calling stub
Goal: Answer “What is the weather in X?” only through a typed `get_weather` tool — never from model memory.
- Declare `get_weather({ city: string, units: "c"|"f" })` with a JSON schema.
- Model must emit a tool call; reject free-text “answers” that skip the tool.
- Validator rejects missing city or bad units; model retries once.
- Stub tool returns canned `{ temp, conditions }`.
- Final answer cites the tool payload fields only.
- Log schema violations separately from tool failures.
Stub the MCP server. The lesson is schema discipline and “no tool, no fact” — not live weather APIs.
// Common failure
What goes wrong
Symptom
Hallucinated tool results — the model “remembers” an API response without calling anything.
Fix
Gate the final answer: if no successful tool observation exists for the claim, refuse and force a tool call.
// Self-reflection
Sit with this
Where does your agent still narrate tool output instead of requiring a real call?
Session only. Nothing is saved.