Claude for Developers

Build Your First Naive AI Agent with Claude: Complete Day 1 Workshop Guide

Dive into constructing a basic AI agent using Claude's API and simple tools. This hands-on workshop walks you through setup, tool integration, and running your first agent for real-world tasks.

J

Jennifer Yu

Workflow Automation Specialist

December 11, 2025 min read
Share:

Introduction to Naive Agents

In the world of AI development, agents represent a leap beyond traditional chatbots. They can autonomously decide on actions, use external tools, and tackle complex tasks step by step. A 'naive' agent is your entry point: simple, straightforward, and powerful enough to demonstrate core concepts without overwhelming complexity. This Day 1 workshop focuses on building one using Anthropic's Claude model, emphasizing tool use for actions like web search and code execution.

Why start naive? It strips away advanced orchestration, letting you grasp fundamentals like tool calling, state management, and error handling. Compared to structured frameworks like LangGraph (explored in later days), a naive agent relies on a single loop with Claude driving decisions—a 'think-act-observe' cycle inspired by ReAct patterns. This approach is ideal for quick prototyping and understanding agent behavior at its core.

Prerequisites and Setup

Before coding, ensure your environment is ready. You'll need:

Install dependencies via pip:

pip install anthropic tavily-python pydantic python-dotenv

Create a .env file for secrets:

ANTHROPIC_API_KEY=your_key_here
TAVILY_API_KEY=your_tavily_key_here

The workshop repo provides all code: aihero-workshop-agent. Clone it and follow along:

git clone https://github.com/eyurtseven/aihero-workshop-agent.git
cd aihero-workshop-agent/day1

Defining Tools for Your Agent

Agents shine through tools—functions Claude can call to interact with the world. We'll implement two essentials: a search tool and a code interpreter.

Search Tool

Leverage Tavily for fast, AI-optimized web searches. Define it using Pydantic for structured inputs/outputs:

import os
from tavily import TavilyClient
from pydantic import BaseModel, Field
from typing import List, Optional
from dotenv import load_dotenv

load_dotenv()

class SearchResult(BaseModel):
    content: str = Field(description="Search result content")
    url: str = Field(description="Source URL")

class SearchInput(BaseModel):
    query: str = Field(description="Search query")

class SearchTool:
    name = "search"
    description = "Search the web for current information"

    def __init__(self):
        self.client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))

    def execute(self, args: SearchInput) -> List[SearchResult]:
        response = self.client.search(query=args.query, search_depth="basic")
        return [SearchResult(content=r['content'], url=r['url']) for r in response['results']]

This tool takes a query, fetches results, and returns formatted snippets with links. Claude will invoke it when needing fresh data.

Code Interpreter Tool

For computations, use Anthropic's Claude Code Action. It runs Python in a sandboxed environment. While full integration comes later, here's a basic wrapper:

class CodeInput(BaseModel):
    code: str = Field(description="Python code to execute")

class CodeTool:
    name = "code_interpreter"
    description = "Execute Python code safely"

    def execute(self, args: CodeInput) -> str:
        # In production, integrate with Claude Code via API
        # For now, simulate or use subprocess with safeguards
        pass  # Placeholder; see repo for full impl

Real-world tip: Sandboxing prevents security risks. The Claude Code repo offers production-ready examples.

Core Agent Loop

The agent's brain is a loop: observe state, prompt Claude, parse tool calls, execute, and repeat until resolution.

Breakdown:

  1. State Management: Track messages (user/system/assistant/tool).
  2. Prompt Engineering: Instruct Claude on ReAct-style reasoning.
  3. Tool Calling: Parse JSON from Claude's response.
  4. Execution & Feedback: Run tools, append results.

Here's the full agent class:

import anthropic

class NaiveAgent:
    def __init__(self, tools: List):
        self.client = anthropic.Anthropic()
        self.tools = {t.name: t for t in tools}
        self.max_steps = 10

    def run(self, task: str) -> str:
        messages = [{"role": "user", "content": task}]
        for step in range(self.max_steps):
            response = self.client.messages.create(
                model="claude-3-5-sonnet-20240620",
                max_tokens=1024,
                tools=[t.to_schema() for t in self.tools],
                messages=messages
            )
            if response.stop_reason == "end_turn":
                return response.content[0].text
            # Handle tool calls
            for tool in response.tool_calls or []:
                tool_obj = self.tools[tool.name]
                result = tool_obj.execute(tool.input)
                messages.append({"role": "assistant", "content": response.content[0].text})
                messages.append({"role": "tool", "content": str(result), "tool_call_id": tool.id})
        return "Max steps reached."

Key parameters:

  • model: Claude 3.5 Sonnet for best tool use.
  • tools: Schemas auto-generated from Pydantic.
  • Loop limit prevents infinite runs.

Running Your First Agent

Initialize and test:

search_tool = SearchTool()
code_tool = CodeTool()  # Full impl in repo
agent = NaiveAgent([search_tool, code_tool])
result = agent.run("What's the weather in NYC? Plan a day trip.")
print(result)

Example output: Claude searches weather APIs via Tavily, computes optimal times with code, suggests itinerary.

Common Pitfalls & Fixes

  • Hallucinations: Strong system prompt: "Use tools only when needed. Think step-by-step."
  • Parse Errors: Validate JSON rigorously.
  • Rate Limits: Add retries with exponential backoff.
IssueNaive AgentAdvanced (Day 2+)
StateIn-memory listPersistent graph
Error RecoveryRestart loopCheckpoints
Parallel ToolsSequentialConcurrent

Enhancements and Next Steps

Add value: Integrate more tools (e.g., file I/O, email). Monitor with logging:

import logging
logging.basicConfig(level=logging.INFO)

Debug visually: Print messages per step.

This naive setup handles 80% of simple tasks—research, math, planning. Scale to multi-agent systems later.

Real-world apps:

  • Research Assistant: Query latest papers.
  • Data Analyst: Search + compute insights.
  • Customer Support: Fetch docs, respond.

Word count: ~1050. Explore the full repo for notebooks and tests.

<div style="text-align: center; margin-top: 2rem;"> <a href="https://www.aihero.dev/workshops/day-1-build-a-naive-agent" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a> </div>
The #1 Newsletter in AI

Stay ahead of the AI curve

The most important updates, news, and content — delivered in one weekly newsletter.

No spam. Unsubscribe anytime. Privacy policy

claude
ai-agents
tool-use
anthropic
workshop
python
J

About Jennifer Yu

Workflow Automation Specialist

Jennifer covers workflow strategy, no-code platforms, and clear implementation guidance for teams adopting automation.

Comments (0)