Claude Agents Python: Agentic Tool-Use Loop

Build an autonomous Claude agent in Python using the Anthropic SDK. Agentic loop pattern: Claude calls tools, you execute them, Claude continues until done. Working code examples.

💥 50p impulse-buy: Power Prompts PDF (first 10 buyers) 30 battle-tested Claude Code prompts · 8-page PDF · paste into CLAUDE.md and never re-type a prompt again · 50p impulse-buy, no commitment

An agentic loop lets Claude autonomously call tools until it solves your task. Here's the complete pattern in Python.

Minimal agentic loop

import anthropic

client = anthropic.Anthropic()

def run_agent(user_task: str, tools: list, tool_executor) -> str:
    """Run Claude in an agentic loop until it completes the task."""
    messages = [{"role": "user", "content": user_task}]
    max_iterations = 15

    for _ in range(max_iterations):
        response = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=4096,
            tools=tools,
            messages=messages
        )

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

        if response.stop_reason == "end_turn":
            # Claude is done — extract final text
            for block in response.content:
                if hasattr(block, "text"):
                    return block.text
            return ""

        if response.stop_reason == "tool_use":
            # Execute all tool calls in this response
            tool_results = []
            for block in response.content:
                if block.type == "tool_use":
                    result = tool_executor(block.name, block.input)
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": str(result)
                    })
            messages.append({"role": "user", "content": tool_results})

    return "Agent hit iteration limit without completing."

Working example: file-writing agent

import anthropic, os, json

client = anthropic.Anthropic()

# Define the tools Claude can use
TOOLS = [
    {
        "name": "read_file",
        "description": "Read the contents of a file at the given path.",
        "input_schema": {
            "type": "object",
            "properties": {"path": {"type": "string", "description": "Relative file path to read"}},
            "required": ["path"]
        }
    },
    {
        "name": "write_file",
        "description": "Write content to a file. Creates the file if it doesn't exist.",
        "input_schema": {
            "type": "object",
            "properties": {
                "path": {"type": "string"},
                "content": {"type": "string"}
            },
            "required": ["path", "content"]
        }
    },
    {
        "name": "list_files",
        "description": "List files in a directory.",
        "input_schema": {
            "type": "object",
            "properties": {"directory": {"type": "string", "description": "Directory path (use '.' for current)"}},
            "required": ["directory"]
        }
    }
]

def execute_tool(name: str, inputs: dict) -> str:
    if name == "read_file":
        try:
            with open(inputs["path"]) as f:
                return f.read()
        except FileNotFoundError:
            return f"Error: file not found: {inputs['path']}"
    elif name == "write_file":
        with open(inputs["path"], "w") as f:
            f.write(inputs["content"])
        return f"Wrote {len(inputs['content'])} chars to {inputs['path']}"
    elif name == "list_files":
        entries = os.listdir(inputs.get("directory", "."))
        return json.dumps(sorted(entries))
    return f"Unknown tool: {name}"

# Run the agent
result = run_agent(
    user_task="List the files in the current directory, then write a SUMMARY.md file listing them.",
    tools=TOOLS,
    tool_executor=execute_tool
)
print(result)

Agent design principles

Adding prompt caching to agents

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=4096,
    system=[
        {
            "type": "text",
            "text": "You are an expert software engineer...",
            "cache_control": {"type": "ephemeral"}  # cache the system prompt
        }
    ],
    tools=TOOLS,  # tools are also cacheable
    messages=messages
)

Caching the system prompt saves ~90% cost on long system prompts after the first call. See the prompt caching guide for full details. For multi-agent orchestration patterns, see the tool use deep-dive.

Frequently asked questions

What is an agentic loop with Claude?
An agentic loop lets Claude autonomously call tools (functions you define) until it reaches a final answer. Claude sends a tool_use block, you execute the tool and send back the result, Claude processes the result and either calls another tool or gives a final text response. This repeats until Claude stops using tools.
How do I stop an infinite agent loop?
Set a max_iterations counter (typically 10–20). Break when response.stop_reason == 'end_turn' (Claude finished) or when you hit the limit. Always handle tool errors gracefully by returning an error string in the tool_result content — Claude will adapt and try another approach.
What tools should I give a Claude agent?
Give Claude only the tools it actually needs — over-tooling leads to confused behavior. Good starting tools: web_search, read_file, write_file, execute_python, get_current_date. Each tool should have a clear description and a narrow, well-defined purpose. Vague tool descriptions are the most common cause of agent failures.
Is Claude good at multi-step reasoning with tools?
Yes. Claude Sonnet 4.6 performs well on multi-step agentic tasks: it reliably plans a sequence of tool calls, adapts when tools return unexpected results, and knows when to stop. For complex agentic workflows, always use Sonnet or Opus — Haiku is less reliable at multi-step planning.

Free tools

Cost Calculator → API Cookbook → Diff Summarizer → Skills Browser →

More examples

Claude API Python QuickstartClaude API Node.js / TypeScript QuickstartClaude API Streaming in PythonClaude API Streaming in Node.js / TypeScriptClaude API Tool Use in PythonClaude API Tool Use in Node.js / TypeScript