Skip to main content
A tool is a function in your code that the LLM can call during a live meeting. You define it once on your account, attach it to one or more scenarios, and the runtime invokes it (over webhook or in the browser) when the LLM emits a tool call. The wire format is identical to OpenAI / Tavus function-calling — port your existing tools with a name change.

When to use a tool

  • Look up a CRM record, calendar slot, or knowledge-base entry mid-call
  • Place an order, book a meeting, or write back to your system
  • Branch the dialogue on real-world state (account tier, inventory, eligibility)
  • Surface UI in the participant’s browser (open a doc, prefill a form)

The Tool object

Example tool object


Execution modes


Conversational modes

A tool call can take 1–8 seconds. Two extra fields control what the persona does during and after the call so the conversation doesn’t go dead.

on_call — what the persona does while the tool runs

static_filler is required when on_call = "static_filler" and forbidden otherwise.

on_resolve — what happens with the result

On Gemini Live, response_in_result falls back to add_to_context — the native-audio API can’t be forced to speak an exact string. The result is still in context for the next turn. Use cloud-TTS providers (OpenAI, ElevenLabs, Cartesia) for true verbatim playback.

How it works at runtime


1. Create a tool

Response — 201 Created:
webhook_secret is never returned — only has_webhook_secret: true. Rotate it any time by PATCHing the tool with a new value; every attached scenario picks up the change instantly.

2. Attach to a scenario

Response — 201 Created (or 200 OK if already attached):

Per-scenario fields


3. Handle the webhook

When the LLM calls the tool, CoreBackend POSTs this payload to your webhook_url:

Request headers

Respond with the result

Return any JSON within timeout_ms. Your response body IS the tool result the LLM sees on its next turn.
  • Non-JSON body → wrapped as { "result": "<your-text>" }
  • Responses larger than 256 KB are truncated
  • Non-2xx response → LLM sees { status: "error", error_code: "http_error", http_status: 500 } and recovers gracefully

Verify the signature

Use the raw request body for HMAC verification. express.json() and similar parsers mutate whitespace and break the signature.

Client-mode tools

For actions that should happen in the participant’s browser (open a doc, prefill a form), set execution_mode: "client" and omit webhook_url. The backend short-circuits the tool call with:
Your frontend SDK listens for the tool-call event on the Daily data channel and responds to the LLM directly. (Web SDK integration is rolling out — until then, prefer webhook mode for production.)

Errors


Limits


API surface

Tools (account-scoped): Scenario attachments:

Worked example — booking a meeting

Two tools (list_slots, book_slot) defined once, attached to both a sales and a support scenario.
During a meeting:
  1. User: “Can we set up a follow-up sometime this week?”
  2. LLM calls list_slots(timezone="Asia/Kolkata").
  3. Your webhook returns [{slot:"2026-06-20T10:00:00+05:30"}, …].
  4. LLM proposes the slots verbally.
  5. User: “Friday at 10 works.”
  6. LLM calls book_slot(slot_iso="2026-06-20T10:00:00+05:30", title="Follow-up").
  7. Your webhook books it and returns { "ok": true, "booking_id": "bk_…" }.
  8. LLM confirms: “Booked — you’ll get a calendar invite shortly.”
No frontend changes, no SDK. The conversation just works.