Module 2: Tool Use Fundamentals

1. Introduction: Agents need hands

Overview

In Module 1 you understood what an agent is: a system that perceives its environment, reasons about what to do, and acts to reach a goal. You drew the perceive-reason-act loop, classified agents by taxonomy, and built a ReAct agent from scratch. But that agent had a fundamental problem: its "actions" were trivial functions returning hardcoded strings. It didn't really search the web, didn't really calculate, didn't really read files. It had a brain, but no hands.

This module gives the agent hands. Tool use is the foundational capability that turns an LLM that generates text into an agent that acts on the world. Without tools, an agent is a brain floating in a void — it can think, but it can't do anything. With tools, it can search the web, check the current weather, run exact calculations, read files from the system, and connect to any external API. The difference isn't incremental: it's categorical. An LLM without tools only generates text. An LLM with tools solves real problems.

The LangChain & LangGraph guide (#9) introduced you to @tool and bind_tools at a basic level. Enough for a tutorial, not enough for production. This module goes deeper: complex Pydantic schemas that guide the model precisely, the tool execution loop step by step (not as a black box but as a flow you control), tools wired to real external APIs with real latency and real errors, error handling as a first-class concern, and advanced patterns like InjectedToolArg for dependency injection. By the end, you'll be able to build any tool an agent needs, with the solidity production demands.


Where are we in the guide?

Context

This guide has 10 modules organized into 3 phases:

Phase 1: Agent Foundations (Modules 1-3)
├── Module 01: Anatomy of an AI Agent            ✓ COMPLETED
├── Module 02: Tool Use Fundamentals             ← YOU ARE HERE
└── Module 03: Function Calling Patterns

Phase 2: Agent Architecture (Modules 4-7)
├── Module 04: State Machines for Agents
├── Module 05: Multi-Step Reasoning and Planning
├── Module 06: Memory Systems for Agents
└── Module 07: MCP and Advanced Tool Integration

Phase 3: Multi-Agent & Production (Modules 8-10)
├── Module 08: Multi-Agent Orchestration
├── Module 09: Testing and Evaluating Agents
└── Module 10: Agents in Production and Alternatives

Where are you coming from?

In Module 1 you built the conceptual base:

  • What an agent is: Formal components — perception, reasoning, action, memory
  • How it thinks: The perceive-reason-act loop and its relationship with ReAct
  • What types exist: Reactive, deliberative, hybrid — a taxonomy for designing the right type
  • When to use them: Decision framework for agent vs chain vs workflow
  • What's out there: The 2025-2026 framework landscape
  • The manual loop: You implemented a ReAct agent without a framework to understand what happens under the hood

That conceptual base is the agent's "brain." Now you give it hands.

Where are you going?

Phase 1's progression is deliberate:

  1. Module 1 — What an agent is → You understand the architecture and decide with judgment
  2. Module 2 — How you give it tools → You build solid tools, connect them, handle errors ← HERE
  3. Module 3 — How you orchestrate those tools → Parallel calls, routing, composition, retry

Module 2 is the bridge between knowing what an agent is and knowing how to orchestrate complex agents. Without solid tools, there are no function calling patterns (M3), no state machines with tools (M4), no MCP (M7), no multi-agent (M8). Everything that comes later depends on what you learn here.

Think of it this way: Module 1 gave you the blueprints of the house. Module 2 teaches you to build the tools you'll build it with. Module 3 teaches you to use those tools with professional patterns. You can't build without tools. And you can't use tools professionally if you don't know how to build them well.


What makes tool use different from what you already know

What guide #9 covered (LangChain & LangGraph)

In guide #9 you learned to use tools inside the framework:

  • The @tool decorator to turn functions into tools
  • bind_tools() to connect tools to a model
  • create_react_agent, which handles the loop internally
  • ToolMessage as a message type in the conversation
  • Basic tools like TavilySearch

That's enough to follow a tutorial and build a working demo. But if someone asks you: "how do you control which tool the model uses?", "what happens if the API fails mid-loop?", "how do you design a schema so the model always passes the right arguments?", "how do you inject the user_id into a tool without the model seeing it?" — guide #9 didn't prepare you for that.

What this module covers (Building AI Agents)

Guide #9 (LangChain & LangGraph):
  → Basic @tool, bind_tools, create_react_agent
  → Enough for: demos, tutorials, quick prototypes
  → Doesn't cover: complex schemas, manual loop, error handling, real APIs

Guide #11 — Module 2 (this module):
  → @tool with complex Pydantic schemas (nested, enums, constraints)
  → bind_tools with tool_choice (auto, any, specific tool)
  → The manual tool execution loop, step by step
  → Real external APIs with real latency, errors and rate limits
  → Error handling as a first-class concern (not an afterthought)
  → InjectedToolArg for dependency injection
  → Debugging tool calls (inspecting tool_calls, validating schemas)

The difference in a table

AspectGuide #9This module
@toolSimple functions with a docstringPydantic schemas with constraints, descriptions, nested models
bind_toolsConnect tools to the modeltool_choice: auto, any, force a specific tool
Execution loopcreate_react_agent handles itManual loop step by step + when to use manual vs framework
External toolsTavilySearch as an example5+ real APIs: weather, calculator, file reader, datetime
Error handlingBasic or nonexistentNetwork errors, timeouts, rate limits, graceful degradation
SchemasBasic type hintsNested Pydantic, enums, optional fields, InjectedToolArg
DebuggingConsole.log of the resultInspect AIMessage.tool_calls, validate schemas, tracing

The analogy: guide #9 taught you that a hammer exists and how to drive a nail. This module teaches you to pick the right hammer for each material, to use it without bending nails, and to build your own hammer when the ones on the market don't work for your project.


Prerequisites

From Module 1 (Anatomy of an AI Agent)

You need these concepts to be clear:

  • The perceive-reason-act cognitive architecture: You understand an agent's fundamental loop — it perceives (receives input), reasons (decides what to do), acts (runs tools)
  • The concept of a tool_call in an AIMessage: You know that when a model "calls" a tool, it actually returns an instruction (tool_call) that you execute
  • ToolMessage: You know a tool's result is sent back to the model as a ToolMessage so it can decide the next step
  • ReAct agent: You implemented the loop manually — user → model → tool_call → execute → result → model → response
  • Decision framework: You know when an agent is the right solution vs a chain or a workflow

If any of these points doesn't feel familiar, go back to Module 1 before continuing. This module assumes you already have the conceptual architecture down.

From guide #9 (LangChain & LangGraph)

From the framework, you need to be comfortable with:

  • The @tool decorator: You know how to decorate a function so an LLM can invoke it
  • bind_tools(): You know how to connect a list of tools to a model
  • create_react_agent: You used it to build a basic agent
  • Message types: HumanMessage, AIMessage, ToolMessage — you know what each one contains and when it shows up in the conversation
  • Basic Pydantic: You know how to create models with BaseModel, type hints, and basic validation

Tools for this module

  • Python 3.11+
  • langchain v1.2+ and langchain-openai
  • langgraph v1.0+
  • An OpenAI API key (GPT-4.1 or GPT-4.1-mini)
  • tavily-python for web search (free API key at tavily.com)
  • requests for calls to external APIs
  • python-dotenv to manage environment variables
pip install langchain langchain-openai langgraph tavily-python requests python-dotenv

Module 2 objectives

By the end of this module you'll be able to:

  • Create tools with professional schemas: Use @tool with Pydantic schemas that include strict types, descriptions that guide the model, constraints (min/max, regex), and nested models for complex arguments
  • Control which tools the model uses: Configure bind_tools with tool_choice — auto (the model decides), any (it must use some tool), or specific (force a particular tool) — and know when to use each mode
  • Implement the tool execution loop manually: Write the full cycle user → model → tool_call → execute → ToolMessage → model → response without relying on create_react_agent, and know when the manual loop is the better option
  • Integrate real external APIs: Connect your agent to web search (Tavily), weather APIs, calculators, file readers, and datetime — with real latency, real errors, and real rate limits
  • Handle errors without crashing the agent: Implement robust error handling — network failures, timeouts, API rate limits, invalid arguments — with graceful degradation that informs the model instead of breaking the loop
  • Design advanced schemas: Use nested Pydantic models, enums as arguments, optional fields with defaults, and InjectedToolArg to inject context (user_id, session_id) without exposing it to the model
  • Debug tool calling: Inspect tool_calls in an AIMessage, verify the model generates correct arguments, and use tracing to understand the full execution flow

Module map

#CapsuleWhat you'll learn
02The @tool decorator and tool schemasThe @tool decorator in depth: docstrings as instructions for the model, type hints as schema, Pydantic models for complex arguments, field descriptions and constraints
03bind_tools and the tool calling flowConnecting tools to the model with bind_tools, controlling selection with tool_choice (auto/any/specific), the anatomy of an AIMessage with tool_calls
04The complete tool execution loopThe cycle user → model → tool_call → execute → ToolMessage → model implemented step by step. Manual loop vs create_react_agent. When to use each one
05Built-in tools and external toolsTavilySearch, DuckDuckGo, Wikipedia as ready-made tools. Building wrappers for external REST APIs. Adapters to integrate third-party tools
06Tool validation and error handlingValidation with Pydantic, handling network errors, timeouts, rate limits, invalid arguments. Retry logic. Graceful degradation
07Advanced tool schemasNested Pydantic models, enums as arguments, optional fields, InjectedToolArg for dependency injection the model never sees
08Project: agent with 5 real external toolsComplete mini-project: an agent with web search, weather, calculator, file reader, datetime. Error handling, validation, coherent combination

Learning flow

The module follows a progression that builds capability layer by layer.

First you learn to create tools (capsule 02): the @tool decorator, how docstrings and type hints become the schema the model reads, and how to design schemas with Pydantic so the model knows exactly which arguments to pass and when to use each tool. Without a well-designed schema, the model guesses — and it guesses wrong.

Then you learn to connect tools to the model (capsule 03): bind_tools() isn't just passing a list — you can control whether the model chooses freely (auto), is forced to use some tool (any), or must use a specific tool. You'll understand what the model returns when it "decides" to call a tool: it doesn't return the result, it returns an instruction (tool_call) that you execute.

With creating and connecting under control, you implement the complete loop (capsule 04): user → model → tool_call → execute → ToolMessage → model → response. You do it manually, without a framework, to understand each step. Then you compare it with create_react_agent and decide when the manual loop suits you better. This is the most important concept in the module — the heart of how an agent uses tools.

Capsules 05 and 06 give the system robustness. First you integrate real tools (capsule 05): not mocks returning fixed strings, but real APIs with real latency, real errors, and real rate limits. Then you protect those integrations (capsule 06): what happens when the API fails, when the model sends invalid arguments, when the timeout is exceeded. Error handling isn't a "nice to have" — a tool without error handling is a bug waiting to trigger.

Capsule 07 takes schemas to the professional level: nested arguments (nested Pydantic models), enums to restrict options, and InjectedToolArg — a pattern that lets you inject context like user_id or session_id into the tool without the model seeing it as an argument. It's the difference between tutorial schemas and production schemas.

Finally, the project (capsule 08) puts it all together: you build an agent with 5 real external tools, each one with validation and error handling, combining results from multiple sources coherently.


Connection with the project

This module's project: an agent with 5 real external tools

You'll build an agent that integrates 5 tools wired to real functionality:

ToolAPI/SourceWhat it demonstrates
Web SearchTavily APIReal-time search, variable results
WeatherOpenWeatherMap or wttr.inExternal REST API, JSON parsing
CalculatorSafe expression evaluationA tool with no API, local logic
File ReaderLocal file systemReal reads, handling missing files
DatetimePython's datetime moduleA simple tool, but crucial for temporal context

Each tool has:

  • A Pydantic schema with descriptions that guide the model
  • Error handling that doesn't crash the agent
  • Input validation
  • Formatted responses the model can interpret

The agent receives questions that require combining multiple tools: "What's the weather in the city mentioned in the file config.txt?" requires file_reader → weather. "What's the square root of the number of results for searching 'AI agents 2026'?" requires search → calculator.

Estimated duration: 45-60 minutes.

Connection with the evolving project

The evolving project (AI Research Agent) starts in Module 4, but the tools you build here are its foundation:

Module 2 (now):      Individual tools (search, weather, calculator, file, datetime)
     ↓
Module 3:            Those tools orchestrated with patterns (parallel, routing, retry)
     ↓
Module 4:            Tools integrated into a custom state machine (Research Agent)
     ↓
Module 5:            The agent uses tools as part of planning and reflection
     ↓
Module 6:            Tools + persistent memory (results saved cross-session)
     ↓
Module 7:            Tools reimplemented as MCP servers
     ↓
Module 8:            Each sub-agent has its own subset of tools

The tools you build in this module aren't throwaway exercises. They're the pattern you'll follow in every later module. How solidly you build them here — clear schemas, error handling, validation — determines how solid everything that comes after will be.


What this module does NOT cover

  • Advanced function calling patterns — Parallel calls, routing, composition, retry, circuit breakers. That's all of Module 3. Here you learn to create and execute individual tools; there you learn to orchestrate them with professional patterns
  • MCP (Model Context Protocol) — Integrating tools via MCP is Module 7. Here you build tools directly with @tool; in M7 you reimplement them as MCP servers for interoperability
  • Multi-agent tool sharing — How multiple agents share or isolate tools is Module 8. Here you work with a single agent and its tools
  • State machines — The execution loop you implement here is linear (user → model → tool → model). Loops with state machines, branching and conditional routing are Module 4 with LangGraph
  • Testing tools — Unit testing, integration testing, and trajectory evaluation of tool calls is Module 9. Here you verify tools work; there you test them formally
  • Re-teaching LangChain APIs — We won't re-explain what a HumanMessage is, how invoke() works, or the framework's basic syntax. You have that from guide #9
  • Production agents — Deployment, scaling, monitoring and cost control are Module 10. Here you build production-ready tools; there you take them to real production

The boundary is clear: Module 2 = build solid tools. Module 3 = orchestrate them with patterns. Module 4+ = use them inside complex architectures.


The central analogy: tools as the agent's hands

This analogy will stay with you all module long. Internalize it:

An agent without tools is a brain without hands

Picture someone with a brilliant brain — they can analyze problems, plan strategies, decide what to do. But they have no hands. They can't write the email they planned, can't look up the information they need, can't call the supplier, can't open the file. They can only think and talk.

That's an LLM without tools. It can reason about what to do, but it can't do it.

With tools, the agent acts on the world

Now give it hands. Suddenly, it can:

  • Search for information it doesn't have in its training (web search)
  • Calculate with mathematical precision instead of "approximating" (calculator)
  • Query real-time data that changes minute to minute (weather, stock prices)
  • Read files that contain context specific to the user (file reader)
  • Modify the environment — create files, send emails, update databases

The hand doesn't decide what to do — the brain decides. The hand executes. But without the hand, the brain's decision is useless.

Hands need dexterity

Having hands isn't enough. A surgeon and a 3-year-old both have hands, but the difference in what they can do is enormous. Dexterity comes from:

  • Well-designed schemas = hands that grip precisely (the model knows exactly which arguments to pass)
  • Error handling = hands that don't drop things at the first stumble (the agent recovers from failures)
  • Validation = hands that check before acting (the tool doesn't run with invalid inputs)
  • Real APIs = hands that touch real objects, not simulated ones (tools that connect to the real world)

This module teaches you to build dexterous hands. Not clumsy hands that sometimes work — professional hands that execute precisely, recover from errors, and work against the real world.


The key concept: schemas as documentation for the model

Before starting the technical capsules, there's one concept you need clear because it runs through the whole module.

When you create a tool with @tool, the docstring and the type hints become a JSON schema the model reads to decide:

  • Does this tool do what I need?
  • Which arguments should I pass?
  • What format do the arguments have?
  • What constraints must I respect?

The schema isn't irrelevant technical metadata. The schema is the documentation the model reads. If your schema is vague, the model guesses and fails. If your schema is precise, the model understands and gets it right.

This means designing a tool isn't just writing the function — it's writing the instructions the model will follow to use it. It's like writing the manual for an instrument: if the manual is clear, anyone uses it well. If it's ambiguous, everyone interprets it differently.

Consider the difference:

Vague schemaPrecise schema
query: str — "Search for something"query: str — "Search query for recent news. Use specific keywords, not full sentences. Max 5 words."
city: str — no descriptioncity: str — "City name in English. Use official city name, e.g. 'Mexico City' not 'CDMX'"
expression: str — "Calculate"expression: str — "Mathematical expression using +, -, *, /, **. Example: '(17 * 23) + 5'"

The model makes decisions based on what the schema tells it. If your schema says "search for something," the model interprets freely. If your schema says "search query, max 5 words, specific keywords," the model follows precise instructions.

In every capsule of this module, pay attention to the schemas. They matter as much as the tool's implementation.


The cost of badly built tools

Before getting into the technical capsules, understand what happens when tools aren't well built. This isn't theory — these are problems you'll hit in production:

ProblemCauseConsequence
The model calls the wrong toolAmbiguous descriptions in the schemaWrong answers, extra cost from unnecessary iterations
The model passes invalid argumentsImprecise type hints, no constraintsThe tool fails, the agent enters a retry loop or crashes
The agent stops with no answerThe API fails and there's no error handlingBroken UX, the user gets no response
Token costs blow upTools with no clear description → the model tries them all3-5x more tokens per request than necessary
Inconsistent resultsMocks in development, real APIs in prod"It worked on my machine" — the classic

Each of these problems has a direct solution in one of this module's capsules:

  • Clear schemas (capsule 02) eliminate the wrong tool and invalid arguments
  • The manual execution loop (capsule 04) gives you total control of the flow
  • Real APIs (capsule 05) eliminate the dev-prod gap
  • Error handling (capsule 06) prevents crashes and broken UX
  • Advanced schemas (capsule 07) optimize the model's precision

The time you invest in building solid tools pays off on every request your agent processes.


Evidence of success

By the end of this module, you'll know you succeeded if:

  • ✅ You can create a tool with a Pydantic schema that includes descriptions, constraints, and nested models — and the model uses it correctly with no extra instructions in the prompt
  • ✅ You can draw the tool execution loop from memory: user → model → tool_call → execute → ToolMessage → model → response
  • ✅ You can implement the loop manually (without create_react_agent) and explain what you gain vs what you lose compared to the framework
  • ✅ You can configure bind_tools with tool_choice and explain when to use auto vs any vs forcing a specific tool
  • ✅ Your agent with 5 external tools works against real APIs — not mocks — and handles network errors, timeouts and rate limits without crashing
  • ✅ You can use InjectedToolArg to inject context into a tool without the model seeing it as an argument
  • ✅ Facing a tool that fails in production, you know where to look: wrong schema, missing error handling, insufficient validation, or a broken execution flow

Quick self-assessment

Ask yourself these questions after completing the module:

  1. "If I need to create a tool that queries a REST API with 3 required parameters and 2 optional ones, can I design the schema in under 5 minutes?" → If yes, you've got Pydantic schemas down
  2. "Can I explain what happens internally when an agent calls get_weather('Madrid') — step by step, from the model's decision to the final answer?" → If yes, you've got the execution loop down
  3. "If the weather API fails with a timeout, does my agent keep working and tell the model about the error instead of crashing?" → If yes, you've got error handling down
  4. "Can I inject a user_id into a tool without the model having to specify it as an argument?" → If yes, you've got InjectedToolArg down

If you answered yes to all four → you're ready for Module 3 (Function Calling Patterns). If you answered no to any → review the corresponding capsule before moving on.


How to use this module

If you're coming straight from Module 1

You're on the right track. Module 1 gave you the theory; now comes the practice of tool creation. Read the capsules in order — each one builds on the previous.

If you already used @tool and bind_tools in guide #9

Capsules 02 and 03 have content you'll recognize, but they go deeper (complex Pydantic schemas, tool_choice). Read them quickly and focus on:

  • Capsule 04 (Tool execution loop) — the most important concept in the module
  • Capsule 06 (Error handling) — what's most often missing in tutorial-level tools
  • Capsule 07 (Advanced schemas and InjectedToolArg) — the professional differentiator

If you have experience building tools in production

Go straight to capsules 06 and 07. If your error handling and schemas are already robust, jump to the project (capsule 08) and check that you can build 5 real tools in 45 minutes.

Estimated time

  • Reading and practice: ~60-75 minutes (capsules 02-07)
  • Project: ~45-60 minutes (capsule 08)
  • Total: ~1.7-2.3 hours

Summary

  • Tools are the agent's hands: without them, an LLM only generates text — with them, it acts on the real world
  • Tool use is the foundational capability of every agent. Everything that comes later (function calling, state machines, MCP, multi-agent) depends on well-built tools
  • This module goes deeper than guide #9: complex Pydantic schemas, manual execution loop, real APIs, robust error handling, InjectedToolArg
  • Schemas are documentation for the model: a well-designed schema = an agent that uses tools correctly. A vague schema = an agent that guesses
  • Error handling is first-class: a tool without error handling is a bug waiting to trigger. Every tool must handle network failures, timeouts, rate limits
  • You'll build an agent with 5 real external tools (web search, weather, calculator, file reader, datetime) as a mini-project
  • The tools you build here get reused and evolved in modules 3-10 of the evolving project

Resources

  1. LangChain Tools Documentation — Official reference for creating and using tools in LangChain
  2. OpenAI Function Calling Guide — How function calling works at the OpenAI API level (the underlying mechanism of tool use)
  3. Pydantic V2 Documentation — Pydantic reference for complex schemas, validation and nested models
  4. Tavily API Documentation — Web search API optimized for AI agents
  5. LangGraph Tool Calling How-To — LangGraph guide for integrating tools into stateful agents
  6. Building Effective Agents — Anthropic — Anthropic's perspective on agent design, including tool use