Your First Tool-Calling Agent

Build a Simple Agent

Let's build a weather research agent. It will search for weather information and fetch weather websites.

Step 1: Define Your Tools

Your agent needs tools to call. Let's define two tools:

def search_weather(query):
  """Search for weather information.
  
  Args:
    query: What to search for. Example: "weather in San Francisco today"
  
  Returns:
    List of dicts with 'title' and 'snippet'
  """
  # Imagine this calls a real API
  return [
    {"title": "Weather in SF", "snippet": "Sunny, 72F"},
    {"title": "10 Day Forecast SF", "snippet": "Next 10 days..."},
  ]

def fetch_weather_page(url):
  """Fetch a weather page and get the full text.
  
  Args:
    url: The URL to fetch
  
  Returns:
    Dict with 'title' and 'text'
  """
  # Imagine this calls a real API
  return {
    "title": "Weather in SF",
    "text": "San Francisco weather: Sunny, 72 degrees, light wind..."
  }

Step 2: Register Your Tools

Tell the agent which tools exist:

tools = {
  "search_weather": search_weather,
  "fetch_weather_page": fetch_weather_page,
}

tool_descriptions = {
  "search_weather": "Search the web for weather information. Use this first to find relevant weather pages.",
  "fetch_weather_page": "Fetch the full text of a weather website. Use this to get detailed weather data after you find a page.",
}

Step 3: Write the Agent Loop

def run_agent(user_question):
  conversation = []
  
  # System message tells the model what tools are available
  system_message = f"""You are a weather research assistant.
  You have these tools:
  - search_weather: Search for weather information
  - fetch_weather_page: Fetch the full text of a weather page
  
  User question: {user_question}
  
  Think step by step. First search for information, then fetch the best result.
  """
  
  max_iterations = 5
  for iteration in range(max_iterations):
    # Think: Ask the model what to do
    response = call_model(system_message, conversation)
    print(f"Agent: {response}")
    
    # Check if the model is done
    if "<tool_use>" not in response:
      # No tool call, model returned final answer
      return response
    
    # Act: Extract tool call from response
    tool_call = parse_tool_call(response)
    tool_name = tool_call["name"]
    tool_args = tool_call["args"]
    
    # Call the tool
    if tool_name not in tools:
      result = {"error": f"Unknown tool: {tool_name}"}
    else:
      result = tools[tool_name](**tool_args)
    
    print(f"Tool result: {result}")
    
    # Observe: Add to conversation
    conversation.append({
      "role": "assistant",
      "content": response
    })
    conversation.append({
      "role": "user",
      "content": f"Tool {tool_name} returned: {result}"
    })
  
  return "Max iterations reached"

Step 4: Test It

result = run_agent("What is the weather in San Francisco right now?")
print(f"Final answer: {result}")

How the Agent Works

  1. User asks: "What is the weather in San Francisco?"
  2. Model sees the question and the available tools.
  3. Model decides: "I should search for weather in San Francisco."
  4. Agent calls: search_weather("San Francisco weather today")
  5. Agent gets results: [search result 1, search result 2]
  6. Model sees results and decides: "I found a result. Let me fetch it."
  7. Agent calls: fetch_weather_page("https://...")
  8. Agent gets: Full weather page text
  9. Model reads the page and returns a summary to the user.

Using Real APIs

To make this real, replace the dummy functions with actual API calls.

Using OpenAI API with web search:

from openai import OpenAI

client = OpenAI(api_key="your-api-key")

def search_with_openai_api(query):
  # This would call a real search API
  import requests
  response = requests.get(f"https://api.search.example.com/search?q={query}")
  return response.json()

Using Anthropic API: Use Claude with the tool_use feature (https://docs.anthropic.com).

Using LangChain: LangChain handles the agent loop for you. You just define tools and let LangChain run the loop (https://www.langchain.com).

Using LangGraph: For more control, use LangGraph. It's a framework for building agent workflows (https://langchain-ai.github.io/langgraph/).

Common Mistakes

Mistake 1: Tool descriptions are too vague.

  • Bad: "search" (unclear what it searches)
  • Good: "Search the web for current weather information"

Mistake 2: Not handling tool errors. If a tool returns an error, tell the model. The model might try a different approach.

Mistake 3: No iteration limit. Without a max, the agent can loop forever. Always set a max_iterations.

Mistake 4: No cost tracking. Each API call costs money. Track your total cost and set a budget.

Next Steps

Now that you have a basic agent, let's learn how to write better tool descriptions. That's the key to making agents work well.

Discussion

  • Loading…

← Back to Tutorials