Tool Use: Giving Agents Hands
Master tool use: function calling, MCP, structured outputs, and tool design patterns. Learn how agents interact with APIs, databases, and external systems.
Premium Course Content
This lesson is part of a premium course. Upgrade to Pro to unlock all premium courses and content.
- Access all premium courses
- 1000+ AI skill templates included
- New content added weekly
An agent without tools is just a chatbot with a fancy system prompt. Tools are what make agents agentic — the ability to search, compute, communicate, and create.
🔄 Quick Recall: In the previous lesson, you learned the ReAct pattern: Thought → Action → Observation. The “Action” step is tool use. Now you’ll learn exactly how that works — the protocols, formats, and patterns that connect AI to the real world.
How Function Calling Works
Function calling is the most common tool-use mechanism. Here’s the full cycle:
Step 1: Define the Tool
You describe the tool to the LLM using a JSON schema:
{
"name": "get_weather",
"description": "Get current weather for a city. Use when the user asks about weather conditions, temperature, or forecasts.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. 'San Francisco'"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius"
}
},
"required": ["city"]
}
}
Step 2: The LLM Decides to Call It
When the user says “What’s the weather in Tokyo?”, the LLM returns:
{
"tool_call": {
"name": "get_weather",
"arguments": {"city": "Tokyo", "units": "celsius"}
}
}
The LLM doesn’t execute the tool — it requests the call. Your code executes it.
Step 3: Return the Result
Your code calls the actual weather API and returns the result to the LLM:
{
"tool_result": {
"temperature": 22,
"conditions": "partly cloudy",
"humidity": 65
}
}
Step 4: The LLM Formulates the Response
The LLM uses the tool result to generate a natural language answer: “It’s currently 22°C and partly cloudy in Tokyo, with 65% humidity.”
✅ Quick Check: The LLM receives a tool result that says “Error: API rate limit exceeded.” Should the LLM hide this error and make up an answer? (Answer: Absolutely not. The LLM should transparently communicate the issue: “I wasn’t able to check the current weather — the service is temporarily unavailable. Would you like me to try again in a moment?” Hiding errors leads to hallucinated data, which destroys trust. Transparency about failures is essential for reliable agents.)
Model Context Protocol (MCP)
MCP is an open standard created by Anthropic that standardizes how AI agents connect to external tools and data sources. Think of it as USB-C for AI.
Before MCP
Every tool integration was custom:
Agent → Custom code → Slack API
Agent → Different custom code → GitHub API
Agent → Yet more custom code → Database
With MCP
Tools expose a standard interface:
Agent → MCP Protocol → Slack MCP Server
Agent → MCP Protocol → GitHub MCP Server
Agent → MCP Protocol → Database MCP Server
What MCP Provides
An MCP server can expose three types of capabilities:
| Type | What It Offers | Example |
|---|---|---|
| Tools | Actions the agent can take | “Create a GitHub issue”, “Send a Slack message” |
| Resources | Data the agent can read | File contents, database records, API responses |
| Prompts | Templated prompts for specific tasks | “Summarize this PR”, “Review this code” |
MCP in Practice
Claude Code, for example, connects to MCP servers for file access, web browsing, database queries, and more. When you configure an MCP server, the agent automatically discovers what tools are available — no manual integration code needed.
Structured Outputs
Structured outputs guarantee that the LLM produces valid, parseable data — not just free-form text.
The Problem Without Structured Outputs
Prompt: "Return the data as JSON"
LLM Output: "Sure! Here's the JSON:
```json
{\"name\": \"Tokyo\", \"population\": 13960000}
Is there anything else you’d like to know?"
The LLM wrapped the JSON in explanatory text and code fences. Your parser breaks.
### With Structured Outputs
You define a schema, and the LLM is *constrained* to output only valid JSON matching that schema:
```json
{
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"population": {"type": "integer"}
},
"required": ["name", "population"]
}
}
Output (guaranteed):
{"name": "Tokyo", "population": 13960000}
No preamble, no code fences, no explanatory text. Just valid JSON that matches your schema.
✅ Quick Check: Your agent extracts meeting details from emails and stores them in a calendar API. Without structured outputs, 15% of extractions have formatting errors that crash the calendar integration. With structured outputs, that drops to 0%. Why is this especially important for agents vs. chatbots? (Answer: Agents pass data between steps automatically — a formatting error in step 3 cascades into failures in steps 4, 5, and 6. In a chatbot, a human reads the output and compensates for formatting issues. In an agent pipeline, there’s no human in the loop to catch malformed data. Structured outputs eliminate this entire class of cascading failures.)
Tool Design Patterns
Pattern 1: Confirmation Before Action
For destructive or irreversible actions, require human confirmation:
Agent: "I'm about to delete 47 files matching *.tmp from
the production server. Should I proceed?"
User: "Yes, go ahead."
Agent: [executes deletion]
Pattern 2: Tool Chaining
One tool’s output becomes the next tool’s input:
search("quarterly earnings report") →
read_file(result.url) →
extract_data(file_content, schema="financials") →
create_chart(data, type="bar")
Pattern 3: Fallback Tools
If the primary tool fails, try an alternative:
Primary: database_query("SELECT * FROM users WHERE...")
Fallback: search_api("/users?filter=...")
Last resort: ask_user("I couldn't access the database. Can you provide the user data?")
Practice Exercise
- Write a tool definition (name, description, parameters) for a task you do regularly
- Think about error cases: What happens if the tool fails? What’s the fallback?
- Design a three-tool chain where each tool’s output feeds the next
Key Takeaways
- Function calling is the core mechanism: define tool → LLM decides to use it → your code executes → LLM processes the result
- Tool descriptions are critical — vague descriptions cause wrong tool selection
- MCP standardizes tool integration with an open protocol, eliminating custom integration code per tool
- Structured outputs guarantee valid data format, preventing cascading failures in agent pipelines
- Design patterns (confirmation, chaining, fallbacks) make tool use robust in production
Up Next
In the next lesson, you’ll learn to build multi-agent systems — teams of specialized agents that collaborate, delegate, and orchestrate complex workflows together.
Knowledge Check
Complete the quiz above first
Lesson completed!