bumpy-student-61140
02/14/2026, 10:44 AMtall-airline-16756
02/14/2026, 10:44 AMtall-airline-16756
02/14/2026, 10:44 AM@function_tool in a separate file, importing them, and passing them in the agent tools list) still works in modern LiveKit — and how you might improve it if desired.
Short answer
• Yes — your existing approach still works in modern LiveKit agents. Defining async tools with @function_tool in a separate module, importing them, and giving them to the agent via the tools parameter is supported and is a recommended, modular pattern.
What you showed that remains valid
• Decorating async functions with @function_tool and using context: RunContext is the correct pattern.
• Importing tools from another file (e.g., functions.py) and passing them into the agent:
from functions import save_phone_number, get_room_list, ...
agent = HermesAgent(instructions=instructions, tools=[save_phone_number, get_room_list, ...])
• The RunContext parameter still provides session/context information useful inside tools.
Small improvements and recommended best practices (optional)
• Add parameter annotations with descriptive text to help the LLM and produce better tool schemas. Example:
from typing import Annotated
@function_tool(name="save_phone_number", description="Save or update phone in session and Supabase.")
async def save_phone_number(
context: RunContext,
session_id: Annotated[str, "Unique session ID"],
phone_number: Annotated[str, "E.164 formatted phone number"]
) -> dict:
...
• Return values: your current return of a dict is fine. If you want to signal “no meaningful output” you can return None or a brief message. The LLM will receive the returned value.
• Error handling: raise a ToolError (or equivalent handled exception) for recoverable failures so the agent can surface a clean message instead of crashing.
• Dynamic tools (optional): if you ever need to enable/disable tools at runtime, modern agents support updating tools post-instantiation (e.g., agent.update_tools([...])), but static registration is usually simpler and preferred.
• Keep side-effects explicit and idempotent where possible (e.g., Redis + Supabase updates) and log actions — your existing logging and event logging are good.
What you do NOT need to change
• You do not need to rewrite tools into some new registry format or embed them inline unless you want to. Manually constructing tool schemas by hand is unnecessary if you use @function_tool.
If you want, I can:
• Review one of your actual tool files and suggest any minor modernizations (annotations, error handling, logging patterns).
• Show a short complete example of a tool file + agent initialization using the improvements above.
• Help convert any commented-out or deprecated helper tools (e.g., older plugin APIs) to the current pattern.
Which would help you most next? Review a file, show a minimal example, or walk through error-handling patterns?
Sources: Tool definition and use | LiveKit Documentation