Skip to content

🍳 Cookbook: Integrating External APIs

The real power of agents comes from their ability to interact with the world. This guide shows you how to wrap any external REST API (Stripe, GitHub, Weather, etc.) into a type-safe tool your agent can use.

🎯 Goal

Build a "Weather Tool" that allows an agent to fetch real-time data from an external API.


πŸ—οΈ Phase 1: Define the Tool

We use the @tool decorator. Important: Type hints matter! The agent uses them to understand what arguments to send.

1. Requirements

We typically use httpx for async requests.

poetry add httpx

2. Implementation

In app/tools/weather.py:

import httpx
from app.tools.base import tool

API_KEY = "your_api_key"  # Load this from os.getenv() in production!

@tool(name="get_current_weather", category="info")
async def get_weather(city: str, country_code: str = "US") -> dict:
    """
    Fetches the current weather for a specific location.

    Args:
        city: The name of the city (e.g., 'London', 'New York')
        country_code: The 2-letter ISO country code (default: US)
    """
    url = f"https://api.weatherapi.com/v1/current.json"
    params = {
        "key": API_KEY,
        "q": f"{city},{country_code}"
    }

    async with httpx.AsyncClient() as client:
        resp = await client.get(url, params=params)
        resp.raise_for_status()
        data = resp.json()

        # Tip: Return only what the LLM needs to save context window space
        return {
            "condition": data['current']['condition']['text'],
            "temp_c": data['current']['temp_c'],
            "humidity": data['current']['humidity']
        }

πŸ”„ Phase 2: Registering the Tool

The Traylinx template has a specialized registry system. You usually just need to import your tool logic in app/tools/__init__.py to ensure the decorator runs.

# app/tools/__init__.py
from .weather import get_weather  # This registers it!

πŸ§ͺ Phase 3: Testing Without an Agent

Before confusing an LLM with it, test your tool directly in Python to ensure the API connection works.

import asyncio
from app.tools.weather import get_weather

result = asyncio.run(get_weather("Paris", "FR"))
print(result)
# {'condition': 'Sunny', 'temp_c': 24.0, 'humidity': 45}

πŸ€– Phase 4: Using It

Now, when you run your agent, it "sees" this tool in its system prompt definition automatically.

poetry run agentic orchestrate "Should I wear a raincoat in Paris right now?"

Reasoning Trace: 1. Thought: User is asking about weather-dependent clothing. I need current weather for Paris. 2. Action: get_weather(city="Paris", country_code="FR") 3. Observation: {'condition': 'Light rain', ...} 4. Answer: "Yes, it is currently raining lightly in Paris, so a raincoat would be a good idea."


πŸ’‘ Pro Tip: Error Handling

External APIs fail. Your tool should be robust so the agent doesn't crash.

try:
    resp.raise_for_status()
except httpx.HTTPStatusError as e:
    # Return the error as a string so the agent knows what happened
    return f"Error fetching weather: target API returned {e.response.status_code}"

If the agent sees this error string, it might say: "I'm sorry, I couldn't check the weather right now due to a connection issue."β€”smart!