Agent-to-Agent Handoff
Explore the Implementation
git clone https://github.com/vobiz-ai/Vobiz-Livekit-Agent-to-Agent-Handoff-Example.git
cd Vobiz-Livekit-Agent-to-Agent-Handoff-ExampleThis example reveals LiveKit's native tool-handoff abstraction pattern. Instead of overloading a solitary massive system prompt, you deploy numerous distinct specialist sub-agents, orchestrating their activation when the LLM deems it appropriate to surrender the thread control. The codebase specifically models a TriageAgent fielding inbound calls before distributing the live session to dedicated SalesAgent, BillingAgent, or SupportAgent entities using isolated prompt boundaries.
How It Works
In advanced enterprise flows, compiling a multi-megabyte prompt governing every scenario leads to rampant hallucinations and sluggish latency. A tiered specialist array resolves this elegantly via state-maintained context propagation.
- The Triage Router: The system initiates with a lightweight
TriageAgentthat simply answers the line. It collects the caller's identity array (stored actively in aCallerInfodataclass bound tosession.userdata), extracts user intent, and maps that intent to a function tool liketransfer_to_billing(). - Returning Instantiated Agents: Crucially, these function tools do not return string primitives in JSON. In LiveKit, the tool literally constructs and yields a brand-new Python
Agentinstance equipped with strict billing context configurations natively out of the tool executor. - Preserving Conversational Flow: The framework automatically detaches the Triage agent and mounts the specialized Billing agent inside the exact same RTC Room instance natively. Context memory arrays are duplicated precisely across the handoff boundary via
chat_ctx.copy(exclude_instructions=True)so the new agent explicitly inherits the historical transcript without merging the previous agent's system prompt instructions. - Bi-Directional Flexibility: The
handoff_countattribute guarantees the system recognizes cyclic state regressions, ensuring specialist agents can successfully route callers back into the upstreamTriageAgentif the user requests an entirely disparate operational department.
Implementation Code
In LiveKit's Python architecture, Agent Hot-Swapping works natively by returning entirely new Agent instances directly out of the active function tool array explicitly passing the previous Context pointer:
from livekit.agents import llm, Agent
from backend.specialists import BillingAgent
class RoutingTools(llm.ToolContext):
def __init__(self, caller_identity: str):
super().__init__()
self.caller_identity = caller_identity
@llm.function_tool(description="Pass control securely to the Billing department specialist")
async def route_to_billing(self):
"""Immediately returns an Agent instantiation. LiveKit gracefully hot-swaps active contexts."""
return BillingAgent(
chat_ctx=self.chat_ctx.copy(exclude_instructions=True),
fnc_ctx=BillingTools(caller=self.caller_identity)
)