Agentic AI
I Gave Claude Hands: My First Tool-Use Agent in 20 Lines
Every explainer about "AI agents" seems to make it sound like there's some hidden trick. There isn't. An agent is a normal LLM call, plus one extra step: the model can ask you to run a function, you run it, and you hand the result back. That's it. That's the whole idea. Let's build the smallest possible version so the concept stops being abstract.
The mental model first
Without tools, talking to Claude looks like this:
You ask a question → Claude answers from what it already knowsWith tools, it looks like this:
You ask a question → Claude says "I need to run X first" → you run X → you hand the result back → Claude answers using that resultThat middle step — Claude asking to run something, instead of just answering — is the entire difference between "a chatbot" and "an agent." Nothing more mystical than that.
Step 1: give Claude one tool
Let's give it something genuinely useful to check: the weather. We describe the tool with a name, a description, and the shape of its inputs — Claude never runs any code itself, it just tells you which function it wants and with what arguments.
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from your environment
tools = [
{
"name": "get_weather",
"description": "Get the current weather for a city.",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "The city name, e.g. 'Hyderabad'"},
},
"required": ["city"],
},
}
]Step 2: the actual function behind the tool
This is just a normal Python function. In a real project this would call a weather API — here we'll fake it so the example runs with zero setup.
def get_weather(city: str) -> str:
fake_data = {"Hyderabad": "34°C, humid", "London": "17°C, rainy"}
return fake_data.get(city, "No data for that city")Step 3: the loop — this is the whole agent
messages = [{"role": "user", "content": "What's the weather in Hyderabad right now?"}]
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=tools,
messages=messages,
)
# Claude might answer directly, or ask to use a tool.
if response.stop_reason == "tool_use":
tool_call = next(block for block in response.content if block.type == "tool_use")
# Run the actual function Claude asked for
result = get_weather(**tool_call.input)
# Hand the result back, in the same conversation
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_call.id,
"content": result,
}],
})
# Ask Claude to finish its answer now that it has the data
final = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=tools,
messages=messages,
)
print(final.content[0].text)
else:
print(response.content[0].text)Run this, and you'll see Claude respond with something like "It's currently 34°C and humid in Hyderabad." — a real answer, built from a real function call, that Claude could not have known on its own.
What actually happened, in plain terms
- Claude read your question and decided it needed live data it doesn't have.
- Instead of guessing, it returned a structured request: "call
get_weatherwithcity: Hyderabad." - Your code — not Claude — actually ran that function.
- You sent the result back into the same conversation as a
tool_result. - Claude used that result to write its final answer.
Claude never executed anything. It only ever describes what it wants run; your code stays in full control of whether and how that happens. That distinction is the entire safety model behind tool use, and it's worth sitting with — it's why agents can be given real capabilities (send an email, run a command, hit an API) without the model itself having a hand on the keyboard.
Why this matters more than it looks
That five-step loop above — ask, decide, act, observe, answer — is not a toy simplification. It's the same loop underneath Claude Code editing your files, an MCP-connected agent querying your database, or a multi-step research agent chaining ten tool calls together. The only things that change as agents get more complex are: more tools, a loop that runs multiple rounds instead of one, and better error handling around each tool call. The core mechanic you just built stays exactly the same.
Where to go from here
- Add a second tool and watch Claude choose between them based on the question.
- Wrap the "ask → act → observe" block in a
whileloop so Claude can chain several tool calls in a row before answering — that's the actual definition of an agent loop, and it's next in this series. - Swap your hand-written tool definitions for an MCP server, which is the standardized way to expose tools so any MCP-compatible client (Claude Code, Claude Desktop, others) can use them without custom glue code.
Reference links
- Claude tool use overview: platform.claude.com/docs/en/agents-and-tools/tool-use/overview
- Official tutorial (this same example, built out further): platform.claude.com/docs/en/agents-and-tools/tool-use/build-a-tool-using-agent
- Anthropic Python SDK: github.com/anthropics/anthropic-sdk-python
- Model Context Protocol (MCP): modelcontextprotocol.io
- Claude API reference: platform.claude.com/docs/en/api/overview
Next in this series: "The Agent Loop — Why Every Claude Agent Is Just a While Loop."
Related articles
Agentic AI
The Agent Loop: Why Every Claude Agent Is Just a While Loop
Strip away the hype and every agentic system — Claude Code, MCP-connected agents, multi-step research bots — is running the same five-line loop underneath. Here it is, in full.
- #claude
- #agentic-ai
- #python
- #anthropic
- #fundamentals
Agentic AI
Building a Claude Agent That Remembers You (Without a Vector Database)
Memory is the first thing everyone asks about agents, and the first answer is always 'embeddings and a vector DB.' Here's the version that fits in a JSON file, and why you might not need more than that.
- #claude
- #agentic-ai
- #memory
- #python
- #anthropic
Agentic AI
5 Agent Mistakes I Made So You Don't Have To
Every one of these cost me real debugging time. Each has a one-line fix — here they are, with the code.
- #claude
- #agentic-ai
- #python
- #debugging
- #best-practices