important-garden-60239
09/23/2025, 6:40 AMtall-airline-16756
09/23/2025, 6:40 AMtall-airline-16756
09/23/2025, 6:41 AMstart_turn and end_turn to mark exactly when a user begins and ends their interaction. This gives you clear, manual control over the interaction boundaries.
• Detect Agent Playback Completion: The playback_finished event is handy for knowing when the agent has finished speaking, so you can trigger an RPC and keep external systems in the loop.
• Use `on_user_turn_completed`: This lifecycle method is perfect to hook into for triggering actions right after the user’s turn ends and just before the agent responds.
• Send Custom RPC Events: Feel free to define custom RPC methods, like show_checkout, to notify external systems or kick off specific client-side actions tailored to your needs.
If you'd like, I’d be more than happy to provide detailed examples or help you with the implementation. Just let me know—I'm here to support you!
Sources: Pipeline nodes and hooks | LiveKit Docs | complex-agents/turn-taking/agent.py | Pipeline nodes and hooks | LiveKit Docs | Turn detection and interruptions | LiveKit Docs | How to detect when an agent has finished speakingimportant-garden-60239
09/23/2025, 6:42 AMtall-airline-16756
09/23/2025, 6:42 AMimportant-garden-60239
09/23/2025, 6:44 AMtall-airline-16756
09/23/2025, 6:45 AMevaluation_completed function tool might not be triggering the RPC event properly. I’m here to help you get this sorted out!
1. Function Tool Definition: First, please double-check that the function is correctly defined with the @function_tool decorator and that it accepts RunContext as an argument. This setup is essential for the function to run smoothly.
2. Room and Participant Initialization: It’s important to make sure that both the room and local_participant are properly initialized. If either is missing, the RPC call won’t work as expected.
3. RPC Call Logic: Let’s confirm that the function’s logic actually reaches the RPC call without exiting early. Sometimes, certain conditions might prevent the RPC from triggering, so reviewing those could help.
4. Error Handling: Using try-except blocks to catch and log any exceptions during the RPC call can be really helpful. This way, we can spot any transient issues or invalid states that might be causing trouble.
5. Tool Execution: Check if the tool is being selected and executed by the LLM. You can verify this by looking at function_tools_executed events or running test assertions.
6. Custom Implementation: Just a heads-up that evaluation_completed isn’t a built-in function in LiveKit. You’ll want to make sure it’s explicitly defined and registered as a custom tool.
If you try these steps and still face issues, please don’t hesitate to reach out. I’m more than happy to help you dig deeper and find a solution together.
Sources: Tool definition and use | LiveKit Docs | complex-agents/drive-thru/tools/management_tools.py | Events and error handling | LiveKit Docs | Testing and evaluation | LiveKit Docs | tests/test_evals.pyimportant-garden-60239
09/23/2025, 6:46 AMtall-airline-16756
09/23/2025, 6:46 AMfunction_tools_executed event! You can listen for this event on the AgentSession object. It gets emitted right after all the function tools have run for a specific user input, which is pretty handy.
Here’s a simple example in Python to get you started:
from livekit.agents import FunctionToolsExecutedEvent
@session.on("function_tools_executed")
def on_function_tools_executed(event: FunctionToolsExecutedEvent):
# Access the function calls and their outputs
for function_call, function_output in event.zipped():
print(f"Function {function_call.name} was executed")
if function_output:
print(f"Output: {function_output.output}")
And if you’re working with JavaScript/Node.js, here’s how you can do it:
import { AgentSessionEventTypes } from '@livekit/agents';
session.on(AgentSessionEventTypes.FunctionToolsExecuted, (event) => {
console.log('Function tools executed:', event.functionCalls);
event.functionCalls.forEach((call, index) => {
console.log(`Function ${call.name} executed with arguments:`, call.arguments);
if (event.functionCallOutputs[index]) {
console.log('Output:', event.functionCallOutputs[index].output);
}
});
});
This event gives you all the details about the executed function calls and their outputs. If you have any questions or need a hand with anything else, just let me know—I’m here to help!
Sources: Events and error handling | LiveKit Docs | livekit-agents/livekit/agents/voice/agent_activity.pyimportant-garden-60239
09/23/2025, 7:05 AMtall-airline-16756
09/23/2025, 7:05 AMregisterRpcMethod along with a handler function.
2. Then, from the AI agent’s side, you can make the call using performRpc, where you specify the destination participant, method name, and any payload you need.
If you’d like, I’m more than happy to help you create a custom RPC method that fits your specific needs—just let me know!
Sources: Remote method calls (RPC) | LiveKit Docs | realtime/openai-realtime-tools.py | Function calling with Voice Agents | LiveKit Docsimportant-garden-60239
09/23/2025, 7:08 AMtall-airline-16756
09/23/2025, 7:09 AMevaluationCompleted and success: true when the user answers questions correctly, you can use LiveKit's RPC mechanism. Here’s a friendly way to approach this:
1. Agent-Side: You’ll want to use perform_rpc to send a structured JSON payload to the frontend right after evaluating the user’s answers. For example:
evaluation_payload = {
"action": "evaluationCompleted",
"success": True,
"message": "All answers correct!"
}
json_payload = json.dumps(evaluation_payload)
await room.local_participant.perform_rpc(
destination_identity=participant.identity,
method="client.evaluation",
payload=json_payload
)
1. Frontend-Side: On the frontend, you can register an RPC handler to handle the evaluation result like this: Sources: avatars/tavus/README.mdimportant-garden-60239
09/23/2025, 7:32 AMtall-airline-16756
09/23/2025, 7:33 AMperform_rpc to send the results to the frontend. Here’s a quick example:
await ctx.room.local_participant.perform_rpc(
destination_identity=participant.identity,
method="client.evaluation",
payload=json.dumps({
"action": "evaluationCompleted",
"success": True,
"message": "All answers correct!"
})
)
1. Control Timing with LLM Instructions: Guide the agent’s prompts so it waits until all user input is in before running the function tool. For instance, you can tell the agent to only evaluate after receiving every answer.
This way, the RPC call happens right after the evaluation finishes. If you’d like, I’m here to help with more details or examples—just let me know!
Sources: complex-agents/nova-sonic/form_agent.pyimportant-garden-60239
09/23/2025, 7:33 AMtall-airline-16756
09/23/2025, 7:34 AM@llm.ai_callable(description="Evaluate user answers and trigger RPC")
async def evaluate_answers(
answers: Annotated[list, llm.TypeInfo(description="List of user answers")]
) -> dict:
# Implementation
return {"success": True, "message": "All answers correct!"}
1. Use Model-Specific Templates: Make sure the LLM outputs tool calls in strict JSON format. Here’s an example:
{
"name": "evaluate_answers",
"parameters": {
"answers": [
"A",
"B",
"C"
]
}
}
1. Control Tool Invocation: You can use the tool_choice parameter in ModelSettings to specify when tools should be called. For instance:
session = AgentSession(
model_settings=ModelSettings(tool_choice="required")
)
1. Suppress Unwanted Replies: To avoid unnecessary responses, use ev.cancel_tool_reply() within the function_tools_executed event.
2. Forward Results via RPC: Once evaluation is complete, you can use perform_rpc to send the results to the frontend seamlessly.
If you’d like, I’m more than happy to provide further clarification or tailor examples to your specific needs—just let me know!
Sources: Tool definition and use | LiveKit Docs | models/templates/meetkai-functionary-medium-v3.1.jinja | Function calling with Voice Agents | LiveKit Docs | examples/voice_agents/silent_function_call.py | agents/src/voice/generation.tsimportant-garden-60239
09/23/2025, 7:36 AMtall-airline-16756
09/23/2025, 7:36 AMinstructions="""
You are a helpful assistant. When the user completes all questions successfully, you must call the `evaluation_completed` function with the following payload:
{
"success": true,
"message": "All questions answered correctly."
}
Please don’t call this function until all questions are answered.
"""
In this block:
• Be sure to clearly mention the function name (evaluation_completed).
• Specify the exact condition for calling the function (like “when all questions are answered”).
• Include the expected payload structure so it’s called correctly.
If you’d like, I’m here to help with any further clarification or tweaks to fit your needs perfectly!
Sources: livekit-plugins/livekit-plugins-openai/livekit/plugins/openai/realtime/real... | Tool definition and use | LiveKit Docsimportant-garden-60239
09/23/2025, 7:48 AMtall-airline-16756
09/23/2025, 7:49 AMimportant-garden-60239
09/23/2025, 7:55 AMtall-airline-16756
09/23/2025, 7:55 AMinstructions="""
You are an agent that evaluates user answers and signals the frontend when the evaluation is complete.
Available functions:
- evaluation_completed: Notify the frontend that the user has successfully completed all questions. This function must be called with the following payload:
{
"success": true,
"message": "All questions answered correctly."
}
Do not call this function until all questions are answered correctly.
"""
By clearly outlining the function and its purpose, your agent will have a solid understanding of how and when to use it. If you’d like, I’m here to help you fine-tune this further—just let me know!