I'm trying to implement tools in my livekit agent....
# ask-ai
b
I'm trying to implement tools in my livekit agent. I had imported tools from a different file and implemented them like this, back in a much older version of livekit. Can i do the same? if not, how should i implement those tools now? from functions import ( get_room_list, save_name, save_phone_number, get_phone_number, save_guest_email, save_guest_mobile, get_guest_email, get_guest_mobile, validate_guest_info_complete, specific_room_function, calculate_pricing_for_booking, _# send_whatsapp_message,_ send_advance_qr_code, retrieve_advance, save_booking, save_final_price, save_advance, send_whatsapp_image, save_discount, get_discount, apply_discount, apply_direct_booking_discount, apply_manager_discount, apply_pricing_with_discount, _# send_rates_template,_ try_send_whatsapp, transfer_call, end_call, create_complete_booking_with_qr, summarize_and_store_from_session, ) agent = HermesAgent( instructions=instructions, tools=[ # contact-capture save_name, save_phone_number, get_phone_number, save_guest_email, save_guest_mobile, get_guest_email, get_guest_mobile, validate_guest_info_complete, # availability & pricing get_room_list, specific_room_function, calculate_pricing_for_booking, # notification & payment _# send_whatsapp_message,_ try_send_whatsapp, _# send_rates_template,_ send_whatsapp_image, send_advance_qr_code, retrieve_advance, # final bookkeeping save_booking, save_final_price, save_advance, # discount save_discount, get_discount, apply_discount, apply_direct_booking_discount, apply_manager_discount, apply_pricing_with_discount, # call handling transfer_call, end_call, ], ) will this work the same in modern lk? or do i need to import tools differently now? also here is how i used to define tools back then. can i do the same now? @function_tool( name="save_phone_number", description="Save or update the customer's phone number in the session record in Redis and Supabase.", ) async def save_phone_number( context: RunContext, session_id: str, phone_number: str, ) -> dict: """ Save (or update) the customer's phone number for the session. This function uses Redis' HSET to update the 'phone' field of the session record and also creates/updates the customer record in Supabase. """ key = f"session:{session_id}" redis_client.hset(key, "phone", phone_number) redis_client.set(f"whatsappsession{phone_number}", session_id) logger.info(f"Saved phone number: {phone_number} for session: {session_id}") # Also save to Supabase unified table await supabase_manager.update_customer_info(session_id, {"phone": phone_number}) # Update booking session with guest mobile booking_update = {"guest_mobile": phone_number} await supabase_manager.update_booking_data(session_id, booking_update) # Log this as a communication event await supabase_manager.log_communication_event( session_id, {"event_type": "phone_collected", "phone": phone_number} ) return {"status": "success", "phone": phone_number}
t
Thanks for reaching out, Aryan. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — this is a clear question and the code sample you shared is helpful. I’m responding to whether your old approach (defining tools with
@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:
Copy code
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:
Copy code
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