Build a Tool-Calling Chat Agent That Searches and Books Flights via a REST API

Read the full interview experience this question came from →

Quick Overview

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.

Build a Tool-Calling Chat Agent That Searches and Books Flights via a REST API

Company: Cresta

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Onsite

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: ```python headers = {"X-API-Key": "your-api-key-here", "Content-Type": "application/json"} ``` **1. Save passenger information:** `POST /api/save_passenger_information` ```json {"first_name": "John", "last_name": "Doe", "email": "john@example.com", "phone": "15551234567", "date_of_birth": "1990-05-15"} ``` Response (save the `passenger_id`): ```json {"success": true, "passenger_id": "550e8400-e29b-41d4-a716-446655440001", "message": "Passenger information saved successfully"} ``` **2. Search flights:** `POST /api/search_flight` ```json {"origin": "JFK", "destination": "LAX", "departure_date": "2025-11-15", "passengers": 1} ``` Response (save the `flight_id` of the selected flight): ```json { "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) ```json {"passenger_id": "550e8400-e29b-41d4-a716-446655440001", "flight_id": "FLABCD1234", "seat_preference": "window"} ``` Response (save the `confirmation_code`): ```json {"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. ```python #!/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. ```hint 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 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. ``` ### 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-Key` header, 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_preference` values does the API accept, and is the field required? - What do error responses look like (status codes and body), and is `book_flight` safe 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_results` is large, or only the best few? ### What a Strong Answer Covers - Tool schemas that match the API exactly, with clear descriptions for the model - An `execute_function` with authentication, timeouts, and error results the model can explain - A conversation loop that supports several tool calls within one user turn, with a bound on steps - Correct handling of IDs across calls, including rejecting IDs the model did not get from the API - A safeguard before the booking call, and protection against duplicate bookings - A working end-to-end demo, and a way to test the agent without the real services ### 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?

Overview: 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.

Read the full Cresta Software Engineer interview experience this question came from

|Home/Software Engineering Fundamentals/Cresta
Cresta logo
Cresta
Sep 23, 2026
mediumSoftware EngineerOnsiteSoftware Engineering Fundamentals
0
0

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": "john@example.com", "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-Key header, 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 Guidance

  • 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_preference values does the API accept, and is the field required?
  • What do error responses look like (status codes and body), and is book_flight safe 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_results is large, or only the best few?

What a Strong Answer Covers Guidance

  • Tool schemas that match the API exactly, with clear descriptions for the model
  • An execute_function with authentication, timeouts, and error results the model can explain
  • A conversation loop that supports several tool calls within one user turn, with a bound on steps
  • Correct handling of IDs across calls, including rejecting IDs the model did not get from the API
  • A safeguard before the booking call, and protection against duplicate bookings
  • A working end-to-end demo, and a way to test the agent without the real services

Follow-up Questions Guidance

  • 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?
Loading comments...