Your First Tool-Using AI Agent in Python

Your First Tool-Using AI Agent in Python 1
⏱ 3 min readUpdated 13 October 2026

πŸ“˜ AI Agents & RAG Course Β· Lesson 2 of 7

In this article
  1. Setup
  2. Describe the tools
  3. The loop
  4. Three rules that save hours

Let’s build the loop from Lesson 1 for real. Our agent gets two tools β€” a GST calculator and a currency converter β€” and decides itself when to use them.

Advertisement

Setup

pip install anthropic
# set your key once (Windows: setx ANTHROPIC_API_KEY "sk-ant-...")
export ANTHROPIC_API_KEY="sk-ant-..."

Describe the tools

A tool is a name, a description the model reads, and a JSON schema for its inputs. Good descriptions matter more than clever code β€” the model chooses tools by reading them.

tools = [
    {"name": "gst",
     "description": "Add GST to an amount. Use for any GST question.",
     "input_schema": {"type": "object",
         "properties": {"amount": {"type": "number"}, "rate": {"type": "number", "description": "percent, e.g. 18"}},
         "required": ["amount", "rate"]}},
    {"name": "convert",
     "description": "Convert an amount between currencies using today's rate.",
     "input_schema": {"type": "object",
         "properties": {"amount": {"type": "number"}, "src": {"type": "string"}, "dst": {"type": "string"}},
         "required": ["amount", "src", "dst"]}},
]

RATES = {("USD", "INR"): 95.8, ("EUR", "INR"): 107.1}   # demo rates

def run_tool(name, args):
    if name == "gst":
        tax = round(args["amount"] * args["rate"] / 100, 2)
        return f"GST {tax}, total {args['amount'] + tax}"
    if name == "convert":
        r = RATES.get((args["src"].upper(), args["dst"].upper()))
        return f"{round(args['amount'] * r, 2)} {args['dst']}" if r else "rate not available"
    return "unknown tool"

The loop

import anthropic
client = anthropic.Anthropic()

messages = [{"role": "user", "content": "I paid 1,200 USD for software. What is that in INR, and the total with 18% GST?"}]
while True:
    response = client.messages.create(model="claude-opus-5-5", max_tokens=4000, tools=tools, messages=messages)
    if response.stop_reason != "tool_use":
        break
    messages.append({"role": "assistant", "content": response.content})
    results = []
    for block in response.content:
        if block.type == "tool_use":
            print("β†’", block.name, block.input)
            results.append({"type": "tool_result", "tool_use_id": block.id, "content": run_tool(block.name, block.input)})
    messages.append({"role": "user", "content": results})   # all results in ONE message

print(next(b.text for b in response.content if b.type == "text"))

Run it and you will see the agent call convert, read the result, then call gst on the INR amount, and finally answer in plain English. You didn’t write that order β€” the model chose it.

Three rules that save hours

  • Send every tool result back in one user message, each with the matching tool_use_id.
  • Return errors as text (“rate not available”) rather than crashing β€” the model can recover.
  • Cap the loop (e.g. 10 turns) so a confused agent can’t run forever. We add this properly in Lesson 6.

The Anthropic Python SDK also has a beta “tool runner” helper that writes this loop for you; writing it once by hand is the best way to understand what it does.

✨ Ask AI about this article

Stuck on a step? Ask a question and the AI answers using this article.

Free Β· AI can be wrong