Tool use is how agents affect anything outside their own reasoning. A tool is a function, with a name, description, parameter schema, that the LLM can request to call. The orchestrator executes it and returns the result.
Every major LLM provider offers native tool-use support:
All three follow the same basic shape: you provide tool definitions, the model returns structured tool calls, your code executes them and feeds results back.
{
"name": "search_web",
"description": "Search the web for recent information. Returns top 5 results with snippets.",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "search query"},
"recency": {"type": "string", "enum": ["day", "week", "month"]}
},
"required": ["query"]
}
}
The model sees your tool name, description, and parameter schema. That's it. It doesn't see your code. Everything the LLM needs to know about when to call the tool, how to call it, and what it returns must be in the description.
Modern APIs support calling multiple tools in a single step. "Search these three things at once." Saves latency when tools are independent.
When a tool fails (network error, invalid args, no results), return a structured error the LLM can reason about:
{
"error": "rate_limit",
"message": "Rate limited. Try again in 60 seconds.",
"retry_after": 60
}
The agent can see the error type and decide whether to retry, pivot, or ask the user.