Agent SkillsAgent Skills
Okeysir198

livekit-agent-tools

@Okeysir198/livekit-agent-tools
Okeysir198
1
3 forks
Updated 4/12/2026
View on GitHub

Comprehensive guide for building functional tools for LiveKit voice agents using the @function_tool decorator. Use when creating tools for LiveKit agents to enable capabilities like API calls, database queries, multi-agent coordination, or any external integrations. Covers tool design, RunContext handling, interruption patterns, parameter documentation, testing, and production best practices.

Installation

$npx agent-skills-cli install @Okeysir198/livekit-agent-tools
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Pathskills-reference/livekit-agent-tools/SKILL.md
Branchmain
Scoped Name@Okeysir198/livekit-agent-tools

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

npx agent-skills-cli list

Skill Instructions


name: livekit-agent-tools description: Comprehensive guide for building functional tools for LiveKit voice agents using the @function_tool decorator. Use when creating tools for LiveKit agents to enable capabilities like API calls, database queries, multi-agent coordination, or any external integrations. Covers tool design, RunContext handling, interruption patterns, parameter documentation, testing, and production best practices.

LiveKit Agent Tools Development

Build robust, production-ready tools for LiveKit voice agents that enable LLMs to interact with external services, manage state, coordinate multi-agent workflows, and handle real-time voice interactions.

Quick Start

Basic Tool Pattern

from livekit.agents import Agent
from livekit.agents.llm import function_tool
from livekit.agents.voice import RunContext

class MyAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are a helpful assistant...",
            llm="openai/gpt-4o-mini",
        )

    @function_tool
    async def get_weather(self, location: str) -> str:
        """Get current weather for a location.

        Args:
            location: City name or address to get weather for
        """
        # Your implementation here
        return f"Weather in {location}: Sunny, 72°F"

The @function_tool decorator automatically registers methods as callable tools for the LLM. The docstring is critical—it tells the LLM when and how to use the tool.

Tool Definition Best Practices

Critical for reliability: A good tool definition is key to reliable tool use from your LLM. Be specific about:

  • What the tool does
  • When it should or should not be used
  • What the arguments are for
  • What type of return value to expect

Core Concepts

1. Tool Naming and Descriptions

Use clear, action-oriented names that help the LLM discover the right tool:

@function_tool
async def search_flights(self, origin: str, destination: str, date: str) -> str:
    """Search for available flights between two cities on a specific date.

    Use this when the user asks about flight availability, prices, or schedules.
    Do NOT use this for booking—only for searching.

    Args:
        origin: Departure city or airport code
        destination: Arrival city or airport code
        date: Travel date in YYYY-MM-DD format
    """

2. RunContext for State and Control

The RunContext parameter provides access to session state, speech control, and user data:

@function_tool
async def save_preference(
    self,
    preference_name: str,
    value: str,
    context: RunContext
) -> str:
    """Save a user preference for later use.

    Args:
        preference_name: Name of the preference (e.g., "favorite_color")
        value: The preference value
        context: Runtime context (automatically provided)
    """
    # Access shared state across tools
    context.userdata[preference_name] = value
    return f"Saved {preference_name} as {value}"

See Context & State Management for complete RunContext patterns.

3. Parameter Documentation

Use type hints and annotations for rich parameter documentation:

from typing import Annotated, Literal
from pydantic import Field
from enum import Enum

class Priority(str, Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"

@function_tool
async def create_task(
    self,
    title: str,
    priority: Priority,
    due_date: Annotated[str | None, Field(description="Due date in YYYY-MM-DD format")] = None
) -> str:
    """Create a new task with specified priority.

    Args:
        title: Brief description of the task
        priority: Task priority level
        due_date: Optional deadline for the task
    """

See Parameter Patterns for all documentation approaches.

When to Use Different Patterns

Simple Action Tools

Use for straightforward operations that execute quickly:

  • Logging events
  • Simple calculations
  • Database queries that return quickly

See examples/basic-tool.py

API Integration Tools

Use for external service calls:

  • Weather APIs
  • Database queries
  • Third-party integrations

See examples/api-integration-tool.py

Long-Running Tools

Use for operations that might take time and should handle interruptions:

  • Web searches
  • Complex calculations
  • File processing

See Long-Running Functions and examples/long-running-tool.py

Stateful Tools

Use for maintaining context across interactions:

  • Shopping cart management
  • Multi-step workflows
  • User preferences

See Context & State Management and examples/stateful-tool.py

Multi-Agent Coordination Tools

Use for agent handoffs and specialized routing:

  • Transferring to specialized agents
  • Escalation workflows
  • Domain-specific routing

See Multi-Agent Patterns and examples/agent-handoff-tool.py

Dynamic Tool Creation

Tools can be created at runtime for maximum flexibility:

from livekit.agents.llm import function_tool

# Option 1: Pass tools at agent creation
agent = MyAgent(
    instructions="...",
    tools=[
        function_tool(
            get_user_data,
            name="get_user_data",
            description="Fetch user information from database"
        )
    ]
)

# Option 2: Update tools after creation
await agent.update_tools(
    agent.tools + [
        function_tool(
            new_capability,
            name="new_capability",
            description="Dynamically added tool"
        )
    ]
)

See Dynamic Tool Creation for complete patterns.

Testing Your Tools

Testing is essential for reliable agents. LiveKit provides helpers that work with pytest:

import pytest
from livekit.agents.testing import VoiceAgentTestSession

@pytest.mark.asyncio
async def test_weather_tool():
    async with VoiceAgentTestSession(agent=MyAgent()) as session:
        response = await session.send_text("What's the weather in Tokyo?")
        assert "Tokyo" in response.text
        assert session.tool_calls[-1].name == "get_weather"

See Testing Guide for comprehensive testing strategies.

Production Considerations

Error Handling

Always handle errors gracefully and return meaningful messages:

@function_tool
async def fetch_data(self, user_id: str) -> str:
    """Fetch user data from the database."""
    try:
        data = await database.get_user(user_id)
        return f"User data: {data}"
    except UserNotFoundError:
        return f"No user found with ID {user_id}. Please check the ID and try again."
    except DatabaseError as e:
        return "I'm having trouble accessing the database right now. Please try again in a moment."

Interruption Handling

Design tools that respect user interruptions for better UX:

@function_tool
async def search_database(self, query: str, context: RunContext) -> str | None:
    """Search the database for matching records."""
    # Allow user to interrupt long searches
    search_task = asyncio.ensure_future(perform_search(query))
    await context.speech_handle.wait_if_not_interrupted([search_task])

    if context.speech_handle.interrupted:
        search_task.cancel()
        return None  # Skip the tool reply

    return search_task.result()

Tool Organization

For complex agents with many tools:

  • Group related tools by domain
  • Share common tools across agents using functions defined outside classes
  • Use clear naming conventions (e.g., order_create, order_update, order_cancel)

See Best Practices for production patterns.

Reference Documentation

Load these as needed for specific patterns:

Examples

Complete, runnable examples demonstrating each pattern:

Environment Setup

Before running examples, create a .env file with required API keys:

# LiveKit Configuration
LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=your_api_key
LIVEKIT_API_SECRET=your_api_secret

# LLM Provider (choose one)
OPENAI_API_KEY=your_openai_key
ANTHROPIC_API_KEY=your_anthropic_key

Install dependencies:

pip install livekit-agents livekit-plugins-openai livekit-plugins-silero python-dotenv aiohttp

Quick Reference

PatternWhen to UseKey FeaturesExample
Basic ToolsSimple, fast operationsDirect return values, no statebasic-tool.py
API IntegrationExternal service callsAsync HTTP, error handlingapi-integration-tool.py
Long-RunningTime-consuming opsInterruption support, cancellationlong-running-tool.py
StatefulMulti-step workflowsRunContext.userdata, persistencestateful-tool.py
Multi-AgentSpecialized routingAgent handoffs, context transferagent-handoff-tool.py
DynamicRuntime tool creationPermission-based, conditionalSee dynamic-tools.md

Common Patterns Cheat Sheet

# Basic tool
@function_tool
async def tool_name(self, param: str) -> str:
    """Tool description with usage guidance."""
    return result

# With state
@function_tool
async def stateful_tool(self, param: str, context: RunContext) -> str:
    context.userdata["key"] = value
    return result

# With interruption handling
@function_tool
async def long_tool(self, param: str, context: RunContext) -> str | None:
    task = asyncio.ensure_future(operation())
    await context.speech_handle.wait_if_not_interrupted([task])
    if context.speech_handle.interrupted:
        task.cancel()
        return None
    return task.result()

# Agent handoff
@function_tool
async def transfer_agent(self, context: RunContext):
    new_agent = SpecialistAgent()
    return new_agent, "Transferring to specialist"

Quick Troubleshooting

Tool not being called: Improve the description to be more specific about when to use it.

Type errors: Ensure all parameters have proper type hints.

Interruption issues: Use RunContext.speech_handle.wait_if_not_interrupted() for long operations.

State not persisting: Use context.userdata to share state across tool calls.

Agent transitions fail: Return a tuple (new_agent, message) from the tool.

Import errors: Verify all required packages are installed (pip install livekit-agents livekit-plugins-openai).

For detailed guidance, consult the reference documentation above.

More by Okeysir198

View all
tts-livekit-plugin
1

Build and deploy self-hosted Text-to-Speech API using MeloTTS from Hugging Face and create a LiveKit plugin for voice agents. Use this skill when building TTS systems, LiveKit voice agents, or self-hosted speech synthesis solutions.

livekit-stt-selfhosted
1

Build self-hosted speech-to-text APIs using Hugging Face models (Whisper, Wav2Vec2) and create LiveKit voice agent plugins. Use when building STT infrastructure, creating custom LiveKit plugins, deploying self-hosted transcription services, or integrating Whisper/HF models with LiveKit agents. Includes FastAPI server templates, LiveKit plugin implementation, model selection guides, and production deployment patterns.

livekit-prompt-builder
1

Guide for creating effective prompts and instructions for LiveKit voice agents. Use when building conversational AI agents with the LiveKit Agents framework, including (1) Creating new voice agent prompts from scratch, (2) Improving existing agent instructions, (3) Optimizing prompts for text-to-speech output, (4) Integrating tool/function calling capabilities, (5) Building multi-agent systems with handoffs, (6) Ensuring voice-friendly formatting and brevity for natural conversations, (7) Iteratively improving prompts based on testing and feedback, (8) Building industry-specific agents (debt collection, healthcare, banking, customer service, front desk).

tts-livekit-plugin
1

Build self-hosted TTS APIs using HuggingFace models (Parler-TTS, F5-TTS, XTTS-v2) and create LiveKit voice agent plugins with streaming support. Use when creating production-ready text-to-speech systems that need: (1) Self-hosted TTS with full control, (2) LiveKit voice agent integration, (3) Streaming audio for low-latency conversations, (4) Custom voice characteristics, (5) Cost-effective alternatives to cloud TTS providers like ElevenLabs or Google TTS.