=================== Structured Outputs =================== Agentle allows you to define the structure of agent responses using Pydantic models, enabling strongly-typed outputs that can be easily integrated into your application logic. Basic Structured Output --------------------- Here's a simple example of using structured outputs: .. code-block:: python from pydantic import BaseModel from typing import List, Optional from agentle.agents.agent import Agent from agentle.generations.providers.google.google_genai_generation_provider import GoogleGenaiGenerationProvider # Define your output schema class WeatherForecast(BaseModel): location: str current_temperature: float conditions: str forecast: List[str] humidity: Optional[int] = None # Create an agent with structured output structured_agent = Agent( name="Weather Agent", generation_provider=GoogleGenaiGenerationProvider(), model="gemini-2.0-flash", instructions="You are a weather forecasting assistant. Provide accurate forecasts.", response_schema=WeatherForecast # Define the expected response structure ) # Run the agent response = structured_agent.run("What's the weather like in San Francisco?") # Access structured data with type hints weather = response.parsed print(f"Weather for: {weather.location}") print(f"Temperature: {weather.current_temperature}°C") print(f"Conditions: {weather.conditions}") for day in weather.forecast: print(f"- {day}") Working with Complex Models ------------------------- You can use nested models and complex structures: .. code-block:: python from pydantic import BaseModel, Field from typing import List, Optional, Dict from enum import Enum from datetime import datetime # Define an enum for weather conditions class WeatherCondition(str, Enum): SUNNY = "sunny" CLOUDY = "cloudy" RAINY = "rainy" SNOWY = "snowy" STORMY = "stormy" # Define a nested model for daily forecast class DailyForecast(BaseModel): date: datetime high_temp: float low_temp: float condition: WeatherCondition precipitation_chance: float = Field(ge=0, le=1) # Between 0 and 1 wind_speed: float # Define the main response model class DetailedWeatherForecast(BaseModel): location: str country: str current: Dict[str, float] conditions: WeatherCondition forecast: List[DailyForecast] alerts: Optional[List[str]] = None last_updated: datetime # Create an agent with the complex schema detailed_weather_agent = Agent( name="Detailed Weather Agent", generation_provider=GoogleGenaiGenerationProvider(), model="gemini-2.0-flash", instructions="You are a weather forecasting assistant that provides detailed, structured forecasts.", response_schema=DetailedWeatherForecast ) # Get structured response response = detailed_weather_agent.run("Give me a detailed 5-day forecast for Tokyo, Japan") # Access the structured data forecast = response.parsed print(f"Weather for {forecast.location}, {forecast.country}") print(f"Current temperature: {forecast.current['temperature']}°C") print(f"Current conditions: {forecast.conditions.value}") print("\n5-day forecast:") for day in forecast.forecast: date_str = day.date.strftime("%A, %B %d") print(f"{date_str}: {day.condition.value}, {day.low_temp}°C to {day.high_temp}°C") Combining with Tools ------------------ For even more powerful agents, combine structured outputs with tool calling: .. code-block:: python from pydantic import BaseModel from typing import List, Optional # Define a tool def get_city_data(city: str) -> dict: """Get basic information about a city.""" city_database = { "Paris": { "country": "France", "population": 2161000, "timezone": "CET", "famous_for": ["Eiffel Tower", "Louvre", "Notre Dame"], }, # More cities... } return city_database.get(city, {"error": f"No data found for {city}"}) # Define the structured response schema class TravelRecommendation(BaseModel): city: str country: str population: int local_time: str attractions: List[str] best_time_to_visit: str estimated_daily_budget: float safety_rating: Optional[int] = None # Create an agent with both tools and a structured output schema travel_agent = Agent( name="Travel Advisor", generation_provider=GoogleGenaiGenerationProvider(), model="gemini-2.0-flash", instructions="""You are a travel advisor that provides structured recommendations for city visits.""", tools=[get_city_data], response_schema=TravelRecommendation, ) # Run the agent response = travel_agent.run("Create a travel recommendation for Tokyo.") # Access structured data rec = response.parsed print(f"TRAVEL RECOMMENDATION FOR {rec.city}, {rec.country}") print(f"Population: {rec.population:,}") print(f"Best time to visit: {rec.best_time_to_visit}") Best Practices ------------ 1. **Clear Instructions**: Make sure your agent instructions align with your schema requirements 2. **Schema Complexity**: Balance schema complexity with model capabilities - too complex schemas may lead to validation errors 3. **Field Documentation**: Add field descriptions to help the model generate appropriate values 4. **Optional Fields**: Use Optional for fields that might not always be present 6. **Default Values**: Provide sensible defaults for fields where appropriate