Assistant hooks

Automate actions on call events and interruptions

Overview

Assistant hooks let you automate actions when specific events occur during a call. Use hooks to transfer calls, run functions, or send messages in response to events like call ending or speech interruptions.

Supported events include:

  • call.ending: When a call is ending
  • assistant.speech.interrupted: When the assistant’s speech is interrupted
  • customer.speech.interrupted: When the customer’s speech is interrupted

You can combine actions and add filters to control when hooks trigger.

How hooks work

Hooks are defined in the hooks array of your assistant configuration. Each hook includes:

  • on: The event that triggers the hook
  • do: The actions to perform (supports transfer, function, and say)
  • filters: (Optional) Conditions that must be met for the hook to trigger

The call.endedReason filter can be set to any of the call ended reasons.
The transfer destination type follows the transfer call tool destinations schema.

Example: Transfer on pipeline error

Transfer a call to a fallback number if a pipeline error occurs:

1{
2 "hooks": [{
3 "on": "call.ending",
4 "filters": [{
5 "type": "oneOf",
6 "key": "call.endedReason",
7 "oneOf": ["pipeline-error"]
8 }],
9 "do": [{
10 "type": "transfer",
11 "destination": {
12 "type": "number",
13 "number": "+1234567890",
14 "callerId": "+1987654321"
15 }
16 }]
17 }]
18}

You can also transfer to a SIP destination:

1{
2 "hooks": [{
3 "on": "call.ending",
4 "filters": [{
5 "type": "oneOf",
6 "key": "call.endedReason",
7 "oneOf": ["pipeline-error"]
8 }],
9 "do": [{
10 "type": "transfer",
11 "destination": {
12 "type": "sip",
13 "sipUri": "sip:user@domain.com"
14 }
15 }]
16 }]
17}

Example: Combine actions on pipeline error

Perform multiple actions—say a message, call a function, and transfer the call—when a pipeline error occurs:

1{
2 "hooks": [{
3 "on": "call.ending",
4 "filters": [{
5 "type": "oneOf",
6 "key": "call.endedReason",
7 "oneOf": ["pipeline-error"]
8 }],
9 "do": [
10 {
11 "type": "say",
12 "exact": "I apologize for the technical difficulty. Let me transfer you to our support team."
13 },
14 {
15 "type": "function",
16 "function": {
17 "name": "log_error",
18 "parameters": {
19 "type": "object",
20 "properties": {
21 "error_type": {
22 "type": "string",
23 "value": "pipeline_error"
24 }
25 }
26 },
27 "description": "Logs the error details for monitoring"
28 },
29 "async": true,
30 "server": {
31 "url": "https://your-server.com/api"
32 }
33 },
34 {
35 "type": "transfer",
36 "destination": {
37 "type": "number",
38 "number": "+1234567890",
39 "callerId": "+1987654321"
40 }
41 }
42 ]
43 }]
44}

Example: Handle speech interruptions

Respond when the assistant’s speech is interrupted by the customer:

1{
2 "hooks": [{
3 "on": "assistant.speech.interrupted",
4 "do": [{
5 "type": "say",
6 "exact": ["Sorry about that", "Go ahead", "Please continue"]
7 }]
8 }]
9}

Handle customer speech interruptions in a similar way:

1{
2 "hooks": [{
3 "on": "customer.speech.interrupted",
4 "do": [{
5 "type": "say",
6 "exact": "I apologize for interrupting. Please continue."
7 }]
8 }]
9}

Use "oneOf": ["pipeline-error"] as a catch-all filter for any pipeline-related error reason.

Common use cases

  • Transfer to a human agent on errors
  • Route to a fallback system if the assistant fails
  • Handle customer or assistant interruptions gracefully
  • Log errors or events for monitoring

Slack Webhook on Call Failure

You can set up automatic Slack notifications when calls fail by combining assistant hooks with Slack webhooks. This is useful for monitoring call quality and getting immediate alerts when issues occur.

Step 1: Generate a Slack webhook

Follow the Slack webhook documentation to create an incoming webhook:

  1. Create a Slack app (if you don’t have one already)
  2. Enable incoming webhooks in your app settings
  3. Create an incoming webhook for your desired channel
  4. Copy the webhook URL (it will look like https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX)

Step 2: Create a serverless function

Set up a serverless function (using a service like val.town) to convert Vapi tool call requests into Slack messages:

1export default async function(req: Request): Promise<Response> {
2 try {
3 const json = await req.json();
4 console.log(json);
5
6 const callId = json.message.call.id;
7 const reason = json.message.toolCalls[0].function.arguments.properties.callEndedReason.value;
8
9 fetch("<your-slack-webhook-url>", {
10 "method": "POST",
11 "headers": {
12 "Content-Type": "application/json",
13 },
14 body: JSON.stringify({
15 text: `🚨 Call Failed\nCall ID: ${callId}\nReason: ${reason}`
16 }),
17 });
18
19 return Response.json({
20 results: [{
21 "result": "success",
22 "toolCallId": "hook-function-call"
23 }],
24 });
25 } catch (err) {
26 console.error("JSON parsing error:", err);
27 return new Response("Invalid JSON", { status: 400 });
28 }
29}

Step 3: Configure the assistant hook

Add this hook configuration to your assistant to trigger Slack notifications on call failures:

1{
2 "hooks": [{
3 "on": "call.ending",
4 "filters": [{
5 "type": "oneOf",
6 "key": "call.endedReason",
7 "oneOf": ["pipeline-error"]
8 }],
9 "do": [{
10 "type": "function",
11 "function": {
12 "name": "report_error",
13 "parameters": {
14 "type": "object",
15 "properties": {
16 "text": {
17 "type": "string",
18 "value": "A call error occurred."
19 }
20 }
21 },
22 "description": "Reports a call error to Slack."
23 },
24 "async": false,
25 "server": {
26 "url": "<your-serverless-function-url>"
27 }
28 }]
29 }]
30}

Replace <your-slack-webhook-url> with your actual Slack webhook URL and <your-serverless-function-url> with your serverless function endpoint.