The transfer signal
Handoffs are not a hidden side effect. They are an explicit action. The triage agent exposes function tools like transfer_to_support and transfer_to_billing. When the LLM decides a caller needs a specialist, it calls the tool, and LiveKit swaps the active agent in the session.
async def _transfer_to_agent(self, name: str, context: RunContext_T) -> Agent:
"""Hand control to another agent registered in personas."""
userdata = context.userdata
current_agent = context.session.current_agent
next_agent = userdata.personas[name]
# Remember who was just active so the next agent can copy context
userdata.prev_agent = current_agent
# Returning an Agent from a function tool tells LiveKit to swap
return next_agentThe method on BaseAgent records the previous agent for context copying, then returns the next agent. LiveKit sees the returned Agent and swaps the session.
from livekit.agents.llm import function_tool
from livekit.agents.voice import Agent
from base_agent import BaseAgent
from user_data import RunContext_T
class TriageAgent(BaseAgent):
"""First contact. Greets the caller and routes to a specialist."""
@function_tool
async def transfer_to_support(self, context: RunContext_T) -> Agent:
"""Transfer to Support for appointments, refills, medical records."""
await self.session.say(
"Let me connect you with our Patient Support team."
)
return await self._transfer_to_agent("support", context)
@function_tool
async def transfer_to_billing(self, context: RunContext_T) -> Agent:
"""Transfer to Billing for insurance and payment questions."""
await self.session.say(
"I will transfer you to our Billing department."
)
return await self._transfer_to_agent("billing", context)Each tool has a descriptive docstring. The LLM reads those docstrings to decide when to call each tool. The session.say line gives the caller a verbal acknowledgement before the handoff lands.
A lot. The LLM sees the function name, arguments, and docstring when it decides which tool to call. A vague docstring leads to wrong routes. Write the docstring as if you are coaching a new employee on when to use the tool, with specific triggers like insurance, copay, prescription, or appointment.