Build a Tool-Calling Chat Agent That Searches and Books Flights via a REST API
CrestaSoftware Engineer · OnsiteLast updated
An AI-assisted coding round: turn a Python starter script into a terminal chat agent that uses LLM tool calling to search flights, save passenger details and book a flight through a three-endpoint REST API. It tests tool schemas, a multi-step tool loop, ID handling, booking safeguards and error handling.
In an AI-assisted coding round, you are given an API document (api.md) and a starter script (agent_starter.py). Using AI assistance, implement an AI agent that helps a user search for flights and book them through a chat-style conversation in the terminal.
The code must be in Python, and you set up the whole project in your own IDE, so make sure Python runs locally before the round. You are given three environment variables: OPENAI_API_KEY, OPENAI_BASE_URL and FLIGHT_API_KEY.
Provided api.md
All endpoints are POST requests with JSON bodies. Every request authenticates with these headers:
headers = {"X-API-Key": "your-api-key-here", "Content-Type": "application/json"}
1. Save passenger information: POST /api/save_passenger_information
{"first_name": "John", "last_name": "Doe", "email": "[email protected]", "phone": "15551234567", "date_of_birth": "1990-05-15"}
Response (save the passenger_id):
{"success": true, "passenger_id": "550e8400-e29b-41d4-a716-446655440001", "message": "Passenger information saved successfully"}
2. Search flights: POST /api/search_flight
{"origin": "JFK", "destination": "LAX", "departure_date": "2025-11-15", "passengers": 1}
Response (save the flight_id of the selected flight):
{
"success": true,
"flights": [
{"flight_id": "FLABCD1234", "flight_number": "AA123", "airline": "American Airlines",
"departure_time": "2025-11-15T08:00:00", "arrival_time": "2025-11-15T11:30:00",
"price": 299.99, "available": true}
],
"total_results": 20
}
3. Book flight: POST /api/book_flight (uses the IDs from steps 1 and 2)
{"passenger_id": "550e8400-e29b-41d4-a716-446655440001", "flight_id": "FLABCD1234", "seat_preference": "window"}
Response (save the confirmation_code):
{"success": true, "booking_id": "660e8400-e29b-41d4-a716-446655440001", "confirmation_code": "A7B3C9", "booking_details": {"pricing": {"total_price": 344.99}}}
Provided agent_starter.py
The flight API's base URL is supplied in the round and is replaced by a placeholder here.
#!/usr/bin/env python3
"""Flight Booking Agent Starter Template"""
import os
import json
import requests
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
# Configuration
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
FLIGHT_API_KEY = os.getenv("FLIGHT_API_KEY", "")
API_BASE_URL = "<flight API base URL provided in the round>"
client = OpenAI(api_key=OPENAI_API_KEY)
# System prompt - modify as needed
SYSTEM_PROMPT = "You are a helpful flight booking assistant."
# Welcome message
WELCOME_MESSAGE = """Welcome to the Flight Booking Agent!
I can help you book flights. Just tell me where you'd like to go.
Type 'quit' to exit."""
# Define your tools here
TOOLS = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name or zip code"},
"units": {"type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit"},
},
"required": ["location"],
"additionalProperties": False,
},
},
}
]
def execute_function(function_name: str, arguments: dict) -> dict:
"""Execute API calls based on function name"""
# Call your functions here
return {"error": "Not implemented"}
def run_agent():
"""Main conversation loop"""
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
print(f"\n{WELCOME_MESSAGE}\n")
while True:
user_input = input("You: ").strip()
if user_input.lower() in ["quit", "exit"]:
break
if not user_input:
continue
messages.append({"role": "user", "content": user_input})
# Call LLM
response = client.chat.completions.create(
model="gpt-4.1",
messages=messages,
tools=TOOLS if TOOLS else None,
)
assistant_message = response.choices[0].message
# Handle function calls
if assistant_message.tool_calls:
messages.append(assistant_message)
for tool_call in assistant_message.tool_calls:
result = execute_function(
tool_call.function.name,
json.loads(tool_call.function.arguments),
)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_call.function.name,
"content": json.dumps(result),
})
# Get response after function execution
response = client.chat.completions.create(
model="gpt-4.1",
messages=messages,
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
print(f"\nAgent: {assistant_message.content}\n")
if __name__ == "__main__":
run_agent()
Turn the starter into a working agent: a user should be able to describe a trip in plain language, see matching flights, choose one, provide passenger details, and end up with a confirmed booking and its confirmation code.
Constraints and Clarifications
- Python only, run locally from your own environment. Read keys from environment variables and never hard-code them.
- The flight API uses the
X-API-Keyheader, and all three endpoints take and return JSON. - The chat model is reached through the provided OpenAI-compatible endpoint, using tool (function) calling.
Clarifying Questions
- Must the agent get explicit confirmation from the user before it calls
book_flight? - Search accepts a passenger count, but booking takes a single
passenger_id. How should a booking for several travelers work? - Which
seat_preferencevalues does the API accept, and is the field required? - What do error responses look like (status codes and body), and is
book_flightsafe to retry? - Will users type city names or relative dates ("next Friday"), or airport codes and exact dates?
- Should the agent show all results when
total_resultsis large, or only the best few?
Hints
Hint 1
Tools mirror endpoints: Replace the placeholder tool with one tool per endpoint, and decide which values the model must carry from one tool result into the next call.
Hint 2
Two calls in one turn: Trace what the starter loop does when a single user message requires two tool calls in a row, such as saving the passenger and then booking.
Follow-up questions
- The booking call times out. How do you avoid double-booking when the user or the agent retries?
- How would you test the agent without calling the real model or the flight API?
- How would you support booking one itinerary for two passengers?
- How would you keep a long conversation's history from growing without limit?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.