AI Story

AI Story: Tool Use

tool definitions, the request/tool-use/tool-result loop, error handling

9.  Tool Use

Tool use (also called function calling) lets a model request that your code execute a function and return the result. The model does not call the function directly — it produces a structured tool_use content block describing the call, your code executes it, and you send the result back in a tool_result block. This is what gives AI agents the ability to read files, run searches, call APIs, and take actions in the world.

9.1  Tool Definitions

Each tool is described by a name, a description (shown to the model), and a JSON Schema for the input parameters. The quality of the description directly affects whether the model calls the tool correctly.
tools = [
    {
        "name": "read_file",
        "description": "Read the contents of a file at the given path. "
                       "Returns the file text or an error message.",
        "input_schema": {
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Absolute or relative path to the file."
                }
            },
            "required": ["path"]
        }
    }
]

9.2  The Tool-Use Loop

A single tool-use exchange takes three API turns:
  1. Send the user message with tools defined. Model responds with a tool_use block.
  2. Execute the function. Append the assistant’s response and a user turn containing the tool_result.
  3. Model generates a final text response using the result.
import anthropic, json, pathlib

client = anthropic.Anthropic()

def read_file(path):
    try:
        return pathlib.Path(path).read_text(encoding="utf-8")
    except OSError as e:
        return f"Error: {e}"

messages = [{"role": "user", "content": "Show me the first 5 lines of README.md"}]

while True:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        tools=tools,
        messages=messages
    )

    # append assistant turn
    messages.append({"role": "assistant", "content": response.content})

    if response.stop_reason != "tool_use":
        # model finished; print final text
        for block in response.content:
            if block.type == "text":
                print(block.text)
        break

    # execute each tool the model requested
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            if block.name == "read_file":
                result = read_file(block.input["path"])
            else:
                result = f"Unknown tool: {block.name}"
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": result
            })

    messages.append({"role": "user", "content": tool_results})

9.3  Reporting Tool Errors

If a tool fails, set is_error: true in the tool result. The model will see the error and can decide to retry with different arguments or tell the user the operation failed.
tool_results.append({
    "type": "tool_result",
    "tool_use_id": block.id,
    "content": "File not found: README.md",
    "is_error": True
})

9.4  Multiple Tools

Include multiple tool definitions in the tools list. The model may call them in sequence across multiple loop iterations, or request several in a single response (parallel tool use). Each call must receive a matching tool_result in the next user turn before the loop continues.

9.5  References

ResourceDescription
Tool Use Overview Anthropic’s full tool use guide including parallel tool calls.
CodeBites: Agent AI Working Python agent examples using the tool-use loop.
Next: Agents Building agents with tool use: loops, state, safety constraints.