N8N and VAPI sync issue

I have major issues with getting my Vapi voice agent to read through my calendar availability when I ask for it on the phone.

I use this JSON response format in my “respond to webhook” node:

{
“results”: [
{
“toolCallId”: “{{ $(‘Event = tool-call’).item.json.body.message.toolWithToolCallList[0].toolCall.id }}”,
“output”: {
“available”: true,
“suggestedSlots”: {{ JSON.stringify($json.availSlots) }},
“message”: “We’ve got available slots at {{ $json.availSlots.toString() }}. Do any of those work for you?”
}
}
]
}

The N8N workflow works as intended and actually books the call without errors, but my voice agent doesn’t express this on the phone. It keeps repeating that there’s no availability at that specific time and is unable to check for calendar availability, despite having sent an HTTP GET request to my cal.com calendar with the correct credentials, and the workflow successfully booking a call based on the availability and my requested time.

I’ve also created a function/tool inside Vapi to check for my calendar availability, and clearly instructed the agent to do so in the assistant prompt.

I don’t know why this isn’t working. Maybe I’m using the wrong JSON response format, or maybe my function isn’t set up properly. Hope you guys are able to help.

Added this to my assistant prompt as well:

When receiving a function response:

  • If output.available is true, extract each time in suggestedSlots and read them aloud to the user, formatted in human-friendly language. Example: “We’ve got times at 7:15 PM, 7:30 PM, and 8:15 PM. Do any of those work?”
  • If output.message exists, read it naturally.
  • If output.available is false and suggestedSlots exists, offer those as fallback options.
  • If suggestedSlots is empty or missing and output.message exists, only read the message and let the user know no times are currently available.




Ensure the Respond to Webhook node fires after all booking logic has completed.

Include clear inputs in the output JSON, for example:

{
"bookingStatus": "success",
"slotTime": "2025-06-14T10:00:00Z",
"available": true,
"suggestedSlots": ["2025-06-14T10:00:00Z"]
}

Use decision nodes (IF) to distinguish between available and unavailable flows, and send an appropriate response for each case.