Drive-Thru Example
A complete drive-thru ordering system demonstrating interactive voice agents for food ordering with database integration and order management.
For setup instructions and more details, see the main examples README.
Overview
This example simulates a fast food drive-thru. It is split across three files: database.py contains the menu and formats it as system prompt text, order.py holds Pydantic models for the three order types, and agent.py defines DriveThruAgent with dynamically built ordering tools.
The full menu is loaded once per session and injected directly into the agent's instructions, so the LLM has menu context without needing to call a tool.
Menu Loading
At the start of each session, new_userdata() queries FakeDB for all item categories (drinks, combos, Happy Meals, regulars, sauces) and stores them in the Userdata dataclass alongside a fresh OrderState.
https://github.com/livekit/agents/blob/8283a5a5c9863a07bcf030ee90e8ab780e1e569b/examples/drive-thru/agent.py#L382-L399
DriveThruAgent.__init__ then formats each category using menu_instructions() and concatenates the results with COMMON_INSTRUCTIONS to build the full system prompt. This means the LLM sees the entire menu from the first turn and can answer questions or suggest items without any tool calls.
https://github.com/livekit/agents/blob/8283a5a5c9863a07bcf030ee90e8ab780e1e569b/examples/drive-thru/agent.py#L55-L83
Dynamic Tool Building
The three ordering tools are constructed by build_combo_order_tool, build_happy_order_tool, and build_regular_order_tool. Each method closes over the relevant item lists and injects their IDs as the enum constraint in the tool's JSON schema.
This restricts the LLM to known IDs at the schema layer before any runtime logic runs. ToolError handles the cases that can't be caught statically — for example, when a drink has multiple available sizes and the customer hasn't specified one yet, the tool raises a ToolError prompting the agent to ask for clarification before retrying.
Order Types
order.py defines three Pydantic models: OrderedCombo, OrderedHappy, and OrderedRegular . A discriminated union OrderedItem is also defined. Each ordered item receives a random short order_id on creation via order_uid().
OrderState stores the current cart as a dict[str, OrderedItem] keyed by order_id, which the remove_order_item and list_order_items tools use to look up or modify existing items.
https://github.com/livekit/agents/blob/8283a5a5c9863a07bcf030ee90e8ab780e1e569b/examples/drive-thru/order.py#L45-L56
Managing the Order
Two tools handle cart management:
list_order_itemsreturns all current cart items with theirorder_ids. The agent is instructed to call this first when modifying or removing an item whoseorder_idis unknown.remove_order_itemremoves one or more items byorder_id. Modifications (e.g., upsizing fries) are done by removing the old item and re-adding it with the new parameters.
max_tool_steps=10 is set on the session to give the agent enough budget to call list_order_items followed by remove_order_item in a single turn when needed.
Background Audio
BackgroundAudioPlayer plays an ambient drive-thru noise track (bg_noise.mp3) throughout the session to set the scene.
https://github.com/livekit/agents/blob/8283a5a5c9863a07bcf030ee90e8ab780e1e569b/examples/drive-thru/agent.py#L438-L443
STT Tuning
The STT model is also initialized with keyterm hints for McDonald's brand names (e.g., "Big Mac", "McFlurry", "McCrispy") to improve transcription accuracy.
https://github.com/livekit/agents/blob/8283a5a5c9863a07bcf030ee90e8ab780e1e569b/examples/drive-thru/agent.py#L415-L430