📝 LLM & AI

Tool Use in the Claude API: Agents with Tools

P
Author
Pyland
📅
Published
30.06.2026
⏱️
Reading time
1 min
👁️
Views
80
🌳
Level
Advanced

Tool use lets Claude call functions in your code — fetching weather, reading files, running searches. Claude decides when to call a tool; you decide how to execute it.

How the Protocol Works

  1. You send messages + a list of tools
  2. Claude responds with stop_reason="tool_use" and a tool_use block in content
  3. You execute the tool and return a tool_result
  4. Claude generates the final text response

Tool Definition (JSON Schema)

TOOLS = [
    {
        "name": "get_weather",
        "description": "Получает текущую погоду для города. Используй когда спрашивают о погоде.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "Название города на английском"
                }
            },
            "required": ["city"]
        }
    }
]

First Request with tools=

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=TOOLS,
    messages=[{"role": "user", "content": "Какая погода в Москве?"}]
)

print(response.stop_reason)  # "tool_use"

Handling a Tool Call

for block in response.content:
    if block.type == "tool_use":
        tool_name = block.name          # "get_weather"
        tool_input = block.input        # {"city": "Moscow"}
        tool_id = block.id

        # Execute the tool
        result = get_weather(tool_input["city"])

        # Return the result to Claude
        messages.append({"role": "assistant", "content": response.content})
        messages.append({
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": tool_id,
                "content": result
            }]
        })

Full Agentic Loop

def run_agent(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]

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

        if response.stop_reason == "end_turn":
            return response.content[0].text

        # Handle all tool calls
        messages.append({"role": "assistant", "content": response.content})
        tool_results = []

        for block in response.content:
            if block.type == "tool_use":
                result = execute_tool(block.name, block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result
                })

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

Your reaction to the article

💬 Comments (0)

🔐 Sign in to leave a comment
🚪 Login
💭

No comments yet

Be the first to share your opinion about this article!

🔗 Similar

Similar articles

Continue learning with these materials

📝

httpx: A Modern HTTP Client for Python

httpx is a next-generation HTTP client. Its interface is similar to requests, but it supports...

📅 30.06.2026 👁️ 108
📝

AI Agents: ReAct Loop and Autonomous Actions

A chatbot answers questions. An agent takes action: it calls tools, retrieves real data, and...

📅 30.06.2026 👁️ 101
📝

Typer: CLI Applications Without the Boilerplate

Typer builds CLIs from Python type annotations. No argparse, no manual parsing — just decorators...

📅 30.06.2026 👁️ 88

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!