Initial commit
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
"""
|
||||
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()
|
||||
Reference in New Issue
Block a user