Files
2025-11-29 18:16:40 +08:00

290 lines
9.1 KiB
Python

"""
Travel Booking Agent Example
Multi-tool agent using strict tool use mode for guaranteed parameter validation.
Demonstrates validated tool inputs in agentic workflows.
"""
from anthropic import Anthropic
from typing import Dict, Any, List
import json
import os
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
# Define tools with strict mode
TOOLS = [
{
"name": "search_flights",
"description": "Search for available flights between two cities",
"strict": True, # Enable strict parameter validation
"input_schema": {
"type": "object",
"properties": {
"origin": {
"type": "string",
"description": "Departure city (e.g., 'San Francisco, CA')"
},
"destination": {
"type": "string",
"description": "Arrival city (e.g., 'Paris, France')"
},
"departure_date": {
"type": "string",
"format": "date",
"description": "Departure date in YYYY-MM-DD format"
},
"return_date": {
"type": "string",
"format": "date",
"description": "Return date in YYYY-MM-DD format (optional for one-way)"
},
"travelers": {
"type": "integer",
"enum": [1, 2, 3, 4, 5, 6],
"description": "Number of travelers"
}
},
"required": ["origin", "destination", "departure_date", "travelers"],
"additionalProperties": False # Required for strict mode
}
},
{
"name": "book_flight",
"description": "Book a selected flight",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"flight_id": {
"type": "string",
"description": "Flight identifier from search results"
},
"passenger_names": {
"type": "array",
"items": {"type": "string"},
"description": "Full names of all passengers"
},
"contact_email": {
"type": "string",
"format": "email",
"description": "Contact email for booking confirmation"
}
},
"required": ["flight_id", "passenger_names", "contact_email"],
"additionalProperties": False
}
},
{
"name": "search_hotels",
"description": "Search for hotels in a city",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
},
"check_in": {
"type": "string",
"format": "date",
"description": "Check-in date in YYYY-MM-DD format"
},
"check_out": {
"type": "string",
"format": "date",
"description": "Check-out date in YYYY-MM-DD format"
},
"guests": {
"type": "integer",
"enum": [1, 2, 3, 4],
"description": "Number of guests"
}
},
"required": ["city", "check_in", "check_out", "guests"],
"additionalProperties": False
}
}
]
# Mock tool implementations
def search_flights(origin: str, destination: str, departure_date: str,
travelers: int, return_date: str = None) -> Dict:
"""Mock flight search - would call real API."""
print(f"🔍 Searching flights: {origin}{destination}")
print(f" Departure: {departure_date}, Travelers: {travelers}")
return {
"flights": [
{
"id": "FL123",
"airline": "Air France",
"departure": f"{departure_date} 10:00",
"arrival": f"{departure_date} 23:00",
"price": 850.00,
"class": "Economy"
},
{
"id": "FL456",
"airline": "United",
"departure": f"{departure_date} 14:30",
"arrival": f"{departure_date} 03:30+1",
"price": 920.00,
"class": "Economy"
}
]
}
def book_flight(flight_id: str, passenger_names: List[str],
contact_email: str) -> Dict:
"""Mock flight booking - would call real API."""
print(f"✈️ Booking flight {flight_id}")
print(f" Passengers: {', '.join(passenger_names)}")
print(f" Email: {contact_email}")
return {
"confirmation": "ABC123XYZ",
"status": "confirmed",
"total_price": 850.00 * len(passenger_names)
}
def search_hotels(city: str, check_in: str, check_out: str, guests: int) -> Dict:
"""Mock hotel search - would call real API."""
print(f"🏨 Searching hotels in {city}")
print(f" Check-in: {check_in}, Check-out: {check_out}, Guests: {guests}")
return {
"hotels": [
{
"id": "HTL789",
"name": "Grand Hotel Paris",
"rating": 4.5,
"price_per_night": 200.00,
"amenities": ["WiFi", "Breakfast", "Gym"]
},
{
"id": "HTL101",
"name": "Budget Inn",
"rating": 3.5,
"price_per_night": 80.00,
"amenities": ["WiFi"]
}
]
}
# Tool registry
TOOL_FUNCTIONS = {
"search_flights": search_flights,
"book_flight": book_flight,
"search_hotels": search_hotels,
}
def run_travel_agent(user_request: str, max_turns: int = 10):
"""
Run travel booking agent with strict tool validation.
With strict mode enabled, all tool inputs are GUARANTEED to match
the schema - no validation needed in tool functions!
"""
messages = [{"role": "user", "content": user_request}]
print("=" * 70)
print(f"User Request: {user_request}")
print("=" * 70)
for turn in range(max_turns):
print(f"\n🤖 Agent Turn {turn + 1}")
response = client.beta.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
betas=["structured-outputs-2025-11-13"],
messages=messages,
tools=TOOLS,
)
# Check stop reason
if response.stop_reason == "end_turn":
# Agent finished
final_text = ""
for block in response.content:
if hasattr(block, "text"):
final_text += block.text
print(f"\n✅ Agent Complete:")
print(f"{final_text}")
return final_text
if response.stop_reason == "tool_use":
# Execute tools
tool_results = []
for block in response.content:
if block.type == "text":
print(f"\n💭 Agent: {block.text}")
elif block.type == "tool_use":
tool_name = block.name
tool_input = block.input # GUARANTEED to match schema!
print(f"\n🔧 Tool Call: {tool_name}")
print(f" Input: {json.dumps(tool_input, indent=2)}")
# Execute tool with validated inputs
tool_function = TOOL_FUNCTIONS[tool_name]
result = tool_function(**tool_input) # Type-safe!
print(f" Result: {json.dumps(result, indent=2)}")
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result)
})
# Add to conversation
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
else:
print(f"⚠️ Unexpected stop reason: {response.stop_reason}")
break
print("\n⚠️ Max turns reached without completion")
return None
def main():
"""Run travel agent examples."""
examples = [
"Book a round trip from San Francisco to Paris for 2 people, "
"departing May 15, 2024 and returning May 22, 2024. "
"Passengers are John Smith and Jane Doe. "
"Email confirmation to john.smith@example.com. "
"Also find a hotel in Paris for those dates.",
"Find flights from New York to London for 1 traveler on June 1, 2024.",
"Search for hotels in Tokyo for 2 guests, checking in July 10 "
"and checking out July 15.",
]
for i, request in enumerate(examples, 1):
print(f"\n\n{'='*70}")
print(f"EXAMPLE {i}")
print(f"{'='*70}")
run_travel_agent(request)
if __name__ == "__main__":
main()