diff --git a/fern/docs.yml b/fern/docs.yml index 09577e1d1..3ac5d83c4 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -310,6 +310,9 @@ navigation: path: tools/static-variables-and-aliases/extract-and-chain.mdx - page: Troubleshoot tool variables path: tools/static-variables-and-aliases/troubleshooting.mdx + - page: Dynamic tool messages + path: tools/dynamic-tool-messages.mdx + icon: fa-light fa-comment - page: Tool rejection plan path: tools/tool-rejection-plan.mdx icon: fa-light fa-shield-xmark diff --git a/fern/tools/dynamic-tool-messages.mdx b/fern/tools/dynamic-tool-messages.mdx new file mode 100644 index 000000000..ba03a81e8 --- /dev/null +++ b/fern/tools/dynamic-tool-messages.mdx @@ -0,0 +1,120 @@ +--- +title: Dynamic tool messages +subtitle: Generate a context-aware message before a tool runs with bot_say +slug: tools/dynamic-tool-messages +description: Configure bot_say for Function and Handoff tools so an assistant speaks a context-aware message before execution and handles multiple tool calls correctly. +--- + +`bot_say` is a reserved tool-call argument that lets the model generate a context-aware message in the same response that calls a tool. Vapi speaks the message before the tool runs, without making an additional model request. + +When `bot_say` is a non-empty string, Vapi trims and speaks it before the tool runs. Vapi waits for the message to finish, the caller cannot interrupt it, and Vapi removes the property from the tool-call arguments before execution. + + + Define `bot_say` inside `function.parameters`. It is not a top-level tool + field, so it does not appear as a named field in the [Create Tool API + reference](/api-reference/tools/create). + + +## Supported tools + +| Tool | Add `bot_say` to | Configuration note | +| --- | --- | --- | +| Function | `function.parameters.properties` | Add it to the tool's existing JSON Schema. | +| Handoff | `function.parameters.properties` | Preserve the generated `destination` property and its required entry. | + +## Configure `bot_say` + + + + Add a `bot_say` property with `type` set to `string` inside + `function.parameters.properties`. Include `bot_say` in + `function.parameters.required` so the schema requires the model to provide + it. + + Add the property to the existing schema without removing other properties + or required entries. + + + + Use the property's `description` to specify the message's purpose, tone, + length, language, and script rules. Ask for a non-empty value without + trailing punctuation. + + + + For a tool that normally plays a static or default `request-start` message, + add one `request-start` entry with an empty `content` value. Replace any + existing `request-start` entries, but keep entries for other message types. + + The empty entry prevents a second acknowledgment. Without it, Vapi can + select a default filler message. If you configure a non-empty static start + message, the caller can hear both the dynamic and static messages. + + + + Tell the model to populate `bot_say` whenever it calls the tool and not to + speak a separate acknowledgment. + + ```text + Whenever you call lookup_order, set bot_say to one brief acknowledgment in + the caller's current language. Do not speak a separate acknowledgment. + ``` + + + +## Function tool example + +```json +{ + "type": "function", + "function": { + "name": "lookup_order", + "description": "Look up an order by its ID", + "parameters": { + "type": "object", + "properties": { + "order_id": { + "type": "string", + "description": "The order ID to look up" + }, + "bot_say": { + "type": "string", + "description": "One brief acknowledgment before the lookup, in the caller's current language. No trailing punctuation." + } + }, + "required": ["order_id", "bot_say"] + } + }, + "server": { + "url": "https://example.com/vapi/tools" + }, + "messages": [ + { + "type": "request-start", + "content": "" + } + ] +} +``` + +## Behavior and limits + +- Vapi trims leading and trailing whitespace from a non-empty `bot_say` value before speaking it. +- An empty or whitespace-only value is neither spoken nor removed, so it remains in the tool-call arguments. +- If several tools are called in the same turn, Vapi joins their non-empty values with `. ` and speaks one combined message. +- If `bot_say` is missing, Vapi does not speak a dynamic tool message. + +## Verify the behavior + +Make a test call that triggers the Function tool, then inspect the request received by your server. Confirm that: + +- The assistant finishes the dynamic message before the request arrives. +- The caller cannot interrupt the message. +- The caller hears no second start message. +- The received tool-call arguments contain `order_id` but not `bot_say`. + +## Related + +- [Function tools](/tools/custom-tools) +- [Handoff arguments](/squads/passing-data-between-assistants#approach-1-handoff-arguments) +- [Static variables and aliases](/tools/static-variables-and-aliases) for server-controlled values the model does not generate.