Artificial IntelligenceAnthropicAI Agents

What is an AI Agent? Building Your First Agent with Claude

TT
TopicTrick
What is an AI Agent? Building Your First Agent with Claude

Every AI application you have built so far in this series follows the same pattern: user sends a message, Claude responds, done. This works perfectly for question answering, document analysis, classification, and most conversational use cases. But some tasks do not fit a single-turn pattern.

Imagine asking Claude to: research a company, find its tech stack, check if they are hiring for roles matching your skills, and draft a personalised outreach email. That is not one task — it is four sequential tasks, where each step depends on what the previous step found. No single API call can handle this. You need an agent.

An AI agent is a Claude application that plans a multi-step approach, takes actions autonomously using tools, observes the results, and continues working until the goal is complete. This post introduces the agent concept, explains the plan-act-observe loop, and walks you through building a functioning agent from scratch.


What Makes an Agent Different from a Chatbot?

A chatbot responds to each message independently. An agent pursues a goal.

The technical distinction is straightforward:

  • A chatbot: Receives input → generates a single response → stops
  • An agent: Receives a goal → plans → takes action (tool call) → observes result → updates plan → takes next action → repeats until goal is complete

Agents have three capabilities that chatbots typically lack:

  • Tool use: The ability to call functions that interact with external systems
  • Multi-step reasoning: The ability to plan a sequence of steps and execute them in order
  • Self-direction: The ability to decide what to do next based on what just happened, without being told step by step

The Plan-Act-Observe Loop

Every agent — whether built on Claude or any other model — follows this fundamental loop:

  1. Plan: Given the goal and current context, what is the next action to take?
  2. Act: Execute the chosen action via a tool call
  3. Observe: Incorporate the tool result into context
  4. Evaluate: Is the goal complete? If yes, produce the final response. If no, return to step 1

In Claude's case, this loop runs automatically through repeated API calls. Claude sees the conversation history, the available tools, and all previous tool results, and decides what to do next on each iteration.

Claude Does the Planning, Your Code Runs the Loop

The agent loop itself — calling Claude, handling tool results, calling Claude again — is code you write. Claude provides the reasoning: it decides which tools to call, what arguments to use, and when the task is done. Your code provides the infrastructure: executing the actual tools and managing the back-and-forth API calls. The combination is what makes an agent.


    Your First Agent: A Research Assistant

    Let us build a simple research agent that can search the web, extract information, and produce a structured summary. The agent can decide how many searches it needs and in what order.

    python
    1import anthropic 2import json 3 4client = anthropic.Anthropic() 5 6# Define the agent's available tools 7tools = [ 8 { 9 "name": "search_web", 10 "description": "Search the internet for current information on a topic. Returns a list of relevant results with titles, URLs and descriptions.", 11 "input_schema": { 12 "type": "object", 13 "properties": { 14 "query": { 15 "type": "string", 16 "description": "The search query" 17 } 18 }, 19 "required": ["query"] 20 } 21 }, 22 { 23 "name": "extract_key_facts", 24 "description": "Extract and format key facts from search results into a structured list. Use this when you have gathered enough information and want to organise it.", 25 "input_schema": { 26 "type": "object", 27 "properties": { 28 "topic": { 29 "type": "string", 30 "description": "The topic being researched" 31 }, 32 "facts": { 33 "type": "array", 34 "items": {"type": "string"}, 35 "description": "List of key facts extracted from research" 36 }, 37 "sources": { 38 "type": "array", 39 "items": {"type": "string"}, 40 "description": "URLs of sources used" 41 } 42 }, 43 "required": ["topic", "facts", "sources"] 44 } 45 } 46] 47 48def run_search(query: str) -> dict: 49 """Simulated web search — replace with real search API in production""" 50 # In production: call Brave Search, SerpAPI, or Anthropic managed web search 51 return { 52 "results": [ 53 {"title": f"Result 1 for {query}", "url": "https://example.com/1", "snippet": f"Information about {query}..."}, 54 {"title": f"Result 2 for {query}", "url": "https://example.com/2", "snippet": f"More context on {query}..."} 55 ] 56 } 57 58def store_facts(topic: str, facts: list, sources: list) -> dict: 59 """Store extracted facts — in production, write to database or return to UI""" 60 return { 61 "status": "stored", 62 "topic": topic, 63 "fact_count": len(facts), 64 "source_count": len(sources) 65 } 66 67 68def run_research_agent(research_goal: str) -> str: 69 """Run the research agent until it completes the goal.""" 70 71 system_prompt = """You are a research agent. Your goal is to research the given topic thoroughly. 72 73Follow this process: 741. Search for the topic with relevant queries 752. Search for additional specific aspects if needed 763. When you have gathered sufficient information, use extract_key_facts to organise your findings 774. Provide a clear final summary 78 79Be systematic — search for multiple aspects of the topic before concluding.""" 80 81 messages = [{"role": "user", "content": research_goal}] 82 83 max_iterations = 10 # Safety limit to prevent infinite loops 84 iterations = 0 85 86 while iterations < max_iterations: 87 iterations += 1 88 89 response = client.messages.create( 90 model="claude-sonnet-4-6", 91 max_tokens=4096, 92 system=system_prompt, 93 tools=tools, 94 messages=messages 95 ) 96 97 # Check if agent is done 98 if response.stop_reason == "end_turn": 99 # Extract final text response 100 for block in response.content: 101 if block.type == "text": 102 return block.text 103 return "Research completed." 104 105 # Process tool calls 106 tool_results = [] 107 108 for block in response.content: 109 if block.type == "tool_use": 110 print(f"Agent is calling: {block.name}({block.input})") 111 112 if block.name == "search_web": 113 result = run_search(block.input["query"]) 114 elif block.name == "extract_key_facts": 115 result = store_facts( 116 block.input["topic"], 117 block.input["facts"], 118 block.input["sources"] 119 ) 120 else: 121 result = {"error": f"Unknown tool: {block.name}"} 122 123 tool_results.append({ 124 "type": "tool_result", 125 "tool_use_id": block.id, 126 "content": json.dumps(result) 127 }) 128 129 # Update conversation with assistant response and tool results 130 messages.append({"role": "assistant", "content": response.content}) 131 messages.append({"role": "user", "content": tool_results}) 132 133 return "Research agent reached maximum iterations without completing." 134 135 136# Run the agent 137result = run_research_agent( 138 "Research Anthropic's Claude 4.6 models: what are the key differences between Opus, Sonnet, and Haiku?" 139) 140print(result)

    Breaking Down the Agent Loop

    The critical part of the code above is the while loop and the stop condition:

    • response.stop_reason == "end_turn": Claude has decided it is finished and is producing a final text answer. Exit the loop.
    • response.stop_reason == "tool_use": Claude wants to call one or more tools. Execute them and continue the loop.
    • max_iterations guard: Always include a maximum iteration limit. Agents can get stuck in loops — a hard limit prevents runaway API costs and infinite loops from bugs in tool results.

    Always Set a Maximum Iteration Limit

    An agent without a maximum iteration limit can get stuck in a loop — for example, if a tool consistently returns an error and Claude keeps retrying it. Set a sensible upper bound (typically 10-20 iterations for most tasks) and implement fallback behaviour when that limit is hit. Log the full message history when this happens so you can debug what caused the loop.


      When to Use Agents vs Simple API Calls

      Not every task needs an agent. Use agents when:

      • The task requires multiple steps where each step depends on the previous result
      • The number of steps is not known in advance — the agent must decide based on what it finds
      • The task involves interacting with multiple tools or data sources
      • The task requires real-world actions, not just text generation

      Use simple API calls when:

      • The task is a single step (summarise this document, classify this text)
      • The steps are fixed, known, and can be coded directly without Claude deciding them
      • Latency is critical — every agent iteration adds API round-trip time

      Summary

      An AI agent is the combination of Claude's reasoning, tool use, and a loop that runs until the goal is complete. The key components:

      • Clear goal: The user's task stated as a complete objective, not just a single question
      • Well-defined tools: Tools with clear descriptions so Claude knows when and how to use them
      • The agent loop: A while loop that calls the API, handles tool results, and continues until stop_reason == "end_turn"
      • A maximum iteration limit: Safety against infinite loops and runaway costs
      • A guiding system prompt: Tells the agent how to approach its tasks and what its scope is

      In the next post, we go deeper into how this loop works under the hood — the full agentic reasoning cycle that enables Claude to self-correct, revise plans, and handle unexpected results: The Agentic Loop: How Claude Reasons, Acts, and Self-Corrects.


      This post is part of the Anthropic AI Tutorial Series. Previous post: Knowledge Check: Claude Tools & Capabilities Quiz.