How Tavus tool calls work
A tool dispatches over exactly one channel, set per tool via thedelivery field - see Tool Delivery:
- App message (default) - the call arrives in your frontend as a
conversation.tool_callevent; your app runs the logic and sends aconversation.tool_resultevent back. - API call (HTTP) - Tavus makes an HTTPS request to an endpoint you configure; your backend runs the logic and returns the result in the HTTP response.
on_resolve, independent of which channel delivered the call.
App-message flow:
With app-message delivery, Tavus does not run the tool for you - your frontend handles
conversation.tool_call events and runs your own logic. With API delivery, Tavus calls your endpoint directly, so no frontend handling is needed. Pick one per tool; see Tool Delivery.1. Keep Tool Schemas Clear and Explicit
Tool definitions should be as clear and specific as possible. Ambiguous parameters make it harder for the model to choose and populate tools correctly. Prefer narrow tools with explicit parameters. Bad:2. Separate Read Tools from Write Tools
Tools generally fall into two categories. Read tools retrieve information and are safe to call frequently. Examples:- retrieving account data
- searching knowledge bases
- checking order status
- creating support tickets
- sending emails
- updating records
3. Keep Tool Results Small
Whatever you return - theoutput of a conversation.tool_result (app message) or the body of your HTTP response (API) - is injected back into the model’s context. Large payloads increase token usage and can degrade conversational quality.
Return only the fields needed for the next response:
4. Avoid Triggering Tools Too Early
Tavus agents operate in real-time conversations where users may interrupt or revise their requests. If a tool executes too early, it may perform the wrong action. The LLM does not truly know intent is clear. You make “intent is clear” operational by defining concrete criteria such as:- required slots are present (for example,
email,issue_type, etc.) - no unresolved ambiguity (for example, “today or tomorrow?”)
- user gave explicit confirmation for write actions (for example, “yes, submit it”)
- wait until the user’s intent is clear
- avoid executing write actions mid-sentence
- allow the conversation to stabilize before triggering tools
Recommended system prompt addendum (copy-paste)
Add the following policy to your PAL’s system prompt to improve tool-call quality and safety:5. Log Tool Calls for Observability
Production systems should log tool activity so issues can be debugged easily. For app-message delivery, listen to Tavus app-events (Dailyapp-message events) for end-to-end observability. For API delivery, log on your backend. Either way, you can trace the full lifecycle:
- when the
conversation.tool_call(or HTTPS request) fired - what payload was received
- what your app executed
- what result you returned (the
conversation.tool_resultoutput or the HTTP response body)
- conversation_id
- tool_call_id
- tool_name
- parameters
- execution result
- status (
success/error) - timestamp
6. Return Results Back to the Conversation
After executing a tool call, return the result so the LLM can use it. How you return it depends on the delivery channel; what the PAL does with it is controlled by the tool’son_resolve.
App-message delivery
The call arrives as aconversation.tool_call event carrying a tool_call_id:
properties.arguments is a JSON string - parse it to read the parameters. Execute your logic, then send a conversation.tool_result back with the matching tool_call_id:
API (HTTP) delivery
Tavus calls your configured HTTPS endpoint with the tool arguments; you return the result in the response. A2xx is treated as success and the response body becomes the tool result; non-2xx is marked error. There’s nothing to send back over the data channel - see Tool Delivery for the request/response shapes, retries, and signature verification.
Controlling What the PAL does with the result
Set the tool’son_resolve (it applies to both channels):
| You want | Set on_resolve to |
|---|---|
| The PAL speaks a natural-language summary of the result | generate_response |
| The PAL speaks the result text verbatim | response_in_result |
| Add the result to context silently, with nothing spoken this turn | add_to_context |
| Don’t wait for or process a result (side-effect-only tools) | fire_and_forget |
on_resolve reference for full details.
Example Implementation
For a complete working example of how to implement tool calling with Tavus, see the official example repository: https://github.com/Tavus-Engineering/tavus-examples/tree/main/examples/cvi-tool-calling This example demonstrates how to:- Create tools and attach them to a PAL
- Listen for
conversation.tool_callevents - Execute backend logic when a tool is triggered
- Return results with
conversation.tool_result

