Building Your First Claude Agent from Scratch
Learn how to build your first Claude AI agent from scratch using the Anthropic Python SDK. A step-by-step tutorial covering tool use, agentic loops, and real-world automation patterns.
AI agents are transforming how developers build software. Unlike a simple chatbot that responds and forgets, an agent can reason over a problem, use tools, take actions, verify results, and loop until the job is done. Claude is one of the most capable models for building agents — and with Anthropic's Python SDK, you can have your first working agent running in under 30 minutes.
In this tutorial, we'll build a real agent from scratch: one that can search files, read them, and summarize their contents — all autonomously.
What Makes an Agent Different from a Chatbot?
A standard LLM call is stateless: you send a message, get a reply. An agent is a loop:
The key ingredient is tool use: giving Claude the ability to call functions you define, so it can interact with the real world beyond just generating text.
Prerequisites
Before we start, you'll need:
- Python 3.10+
- An Anthropic API key (get one at console.anthropic.com)
- Basic familiarity with Python
pip install anthropic
Set your API key as an environment variable:
export ANTHROPIC_API_KEY=your_key_here
Step 1: Define Your Tools
Tools are functions Claude can decide to call. You describe them using JSON Schema, and Claude figures out when and how to use them. Let's define three tools for our file summarization agent:
tools = [
{
"name": "list_files",
"description": "List all files in a given directory path.",
"input_schema": {
"type": "object",
"properties": {
"directory": {
"type": "string",
"description": "The directory path to list files from"
}
},
"required": ["directory"]
}
},
{
"name": "read_file",
"description": "Read the contents of a file.",
"input_schema": {
"type": "object",
"properties": {
"filepath": {
"type": "string",
"description": "The full path to the file to read"
}
},
"required": ["filepath"]
}
},
{
"name": "write_summary",
"description": "Write a summary to an output file.",
"input_schema": {
"type": "object",
"properties": {
"filename": {"type": "string"},
"content": {"type": "string"}
},
"required": ["filename", "content"]
}
}
]
Step 2: Implement the Tool Functions
Now write the actual Python functions that execute when Claude calls a tool:
import os
def execute_tool(tool_name: str, tool_input: dict) -> str:
if tool_name == "list_files":
directory = tool_input["directory"]
try:
files = os.listdir(directory)
return "\n".join(files)
except Exception as e:
return f"Error: {str(e)}"
elif tool_name == "read_file":
filepath = tool_input["filepath"]
try:
with open(filepath, "r") as f:
return f.read()
except Exception as e:
return f"Error reading file: {str(e)}"
elif tool_name == "write_summary":
filename = tool_input["filename"]
content = tool_input["content"]
try:
with open(filename, "w") as f:
f.write(content)
return f"Summary written to {filename}"
except Exception as e:
return f"Error writing file: {str(e)}"
return f"Unknown tool: {tool_name}"
Step 3: Build the Agentic Loop
This is the heart of any agent: a loop that keeps running until Claude stops requesting tool calls.
import anthropic
client = anthropic.Anthropic()
def run_agent(task: str) -> str:
messages = [
{"role": "user", "content": task}
]
print(f"Starting agent with task: {task}\n")
while True:
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=4096,
tools=tools,
messages=messages
)
print(f"Agent step — stop_reason: {response.stop_reason}")
# If Claude is done, return the final text response
if response.stop_reason == "end_turn":
for block in response.content:
if hasattr(block, "text"):
return block.text
# If Claude wants to use tools, execute them
if response.stop_reason == "tool_use":
# Add Claude's response to message history
messages.append({
"role": "assistant",
"content": response.content
})
# Execute each tool call and collect results
tool_results = []
for block in response.content:
if block.type == "tool_use":
print(f" Calling tool: {block.name} with {block.input}")
result = execute_tool(block.name, block.input)
print(f" Result: {result[:100]}...")
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
# Feed tool results back to Claude
messages.append({
"role": "user",
"content": tool_results
})
Step 4: Run Your Agent
if __name__ == "__main__":
result = run_agent(
"List all .py files in the current directory, "
"read each one, and write a summary of what "
"each file does to a file called SUMMARY.md"
)
print("\nFinal response:", result)
Run it:
python agent.py
You'll see Claude autonomously listing files, reading each one, and writing the final summary — all without any manual intervention.
Understanding the Message Flow
Here's what happens in each loop iteration:
user messageend_turn) or tool calls (tool_use)user messageend_turnThis back-and-forth is the fundamental pattern behind every Claude-powered agent, whether it's a coding assistant, a data pipeline, or a customer service bot.
Best Practices for Production Agents
Add a max iteration limit to prevent infinite loops:MAX_ITERATIONS = 20
for iteration in range(MAX_ITERATIONS):
# ... your loop logic
Use structured system prompts to guide agent behavior:
system = """You are a file analysis agent. Always:
1. List files before reading them
2. Read files completely before summarizing
3. Be concise in summaries — one paragraph per file"""
Log everything — agents are hard to debug without visibility into each tool call and result.
Handle errors gracefully — return meaningful error strings from tools so Claude can decide whether to retry or skip.
What to Build Next
With this foundation, you can extend your agent to:
- Search the web by adding a
web_searchtool using a Serper or Brave Search API - Query databases with a SQL execution tool
- Send Slack messages or create GitHub issues
- Write and execute code using a sandboxed Python runner
The pattern is always the same: define the tool, implement the function, feed results back to Claude. The model handles all the reasoning about when and how to use them.
Conclusion
Building a Claude agent boils down to three things: defining tools, implementing them, and running an agentic loop. Claude's intelligence handles the rest — deciding which tools to call, in what order, and when the task is complete.
This is just the beginning. In upcoming posts, we'll cover multi-agent orchestration, connecting agents to external services via MCP, and deploying agents to production with proper observability. For now, experiment with your new agent — add a tool, change the task, watch Claude adapt.
The future of software isn't just code you write. It's agents that write and run code for you.