The menu tool

A voice agent without tools is just a talking chatbot. Tools are where the agent actually does things. In the LiveKit agents SDK you declare a tool by decorating a Python function, and the LLM decides when to call it based on the conversation.

How tool calling fits into the voice loop

The LLM decides when to invoke a tool, the tool returns a string, and the agent speaks a response.

restaurant_agent.py
python
from livekit.agents import function_tool

MENU = {
    "appetizers": [{"name": "Caesar Salad", "price": 8.99}],
    "mains": [{"name": "Grilled Salmon", "price": 22.99}],
    "desserts": [{"name": "Tiramisu", "price": 6.99}],
}

@function_tool()
async def get_menu_items(category: str = "all") -> str:
    """Gets menu items by category or all items."""
    if category.lower() == "all":
        parts = []
        for cat, items in MENU.items():
            items_list = [f"{i['name']} for ${i['price']:.2f}" for i in items]
            parts.append(f"For {cat}, we have {', '.join(items_list)}.")
        return " ".join(parts)
    return f"I do not have {category} on the menu today."

Notice how the tool returns a natural sentence, not a JSON blob or a markdown list. Every word the tool returns can end up being spoken. Write for the ear.

You can, but it adds latency and risk. Every extra formatting step gives the LLM a chance to slip in markdown or a bulleted list that TTS will read out word by word. Returning a clean spoken sentence from the tool is the safest way to keep the voice natural.

Quiz: Quiz

Loading practice…