2026-10-01 · 原文发布日
n8n模板:用Vapi语音前台自动查档期、预约并记录来电
这套n8n工作流把Vapi语音助手变成电话前台:Vapi发来工具调用后,流程按工具名分流——查档期时读取Google日历近期事件并按营业时段规则算出可约空位,以可朗读的JSON回给语音助手;预约时直接写入日历、把记录追加到Google Sheets并邮件通知店主;留言则记入表格并转发邮件。需在Vapi配置三个服务器工具,并接入日历、Sheets和SMTP凭证,时段、时区、提前量都可在代码节点里改。
原文要点
该n8n工作流接收Vapi语音助手的工具调用webhook:解析出工具名、工具调用ID和参数后按工具名分流。checkAvailability读取Google日历近期事件,按可配置的营业时段规则算出可约空位,以含ISO时间戳的可朗读JSON回给语音助手;bookAppointment在指定开始时间创建日历事件、向Google Sheets追加预约记录并邮件通知店主;takeMessage把留言记入表格并转发邮件;非工具事件返回空确认。需在Vapi建三个server tools,名称与参数为checkAvailability(无参)、bookAppointment(customerName、phoneNumber、service、startTime)、takeMessage(callerName、phoneNumber、message);时区、营业时间、工作日、时段长度、提前量在代码节点的CONFIGURE块里改。模板基于作者为英国居家护理服务商做过的生产系统。
这次做成什么
把Vapi语音助手变成电话前台:来电人问档期能实时报出空位,确认后直接写入日历并通知店主,无人预约的留言也自动记录。练习方案:先在n8n里用合成的工具调用payload逐条测通三个分支,确认日历事件、表格行、邮件各就各位,再去Vapi后台配置正式助手。
准备什么
- Vapi账号和一个语音助手,能添加server tools并指向webhook URL
- Google Calendar凭证,模板默认使用primary日历
- Google Sheets一份,含Timestamp、Type、Caller Name、Phone、Details、When六列表头
- SMTP凭证用于给店主发预约与留言通知邮件
- n8n实例已发布该工作流,拿到生产webhook地址
具体怎么做
建来电登记表
新建Google Sheet,第一行写入六个表头:Timestamp、Type、Caller Name、Phone、Details、When。两个Sheets节点都指向这份文档的同一工作表,Type列区分booking与message两类记录。
配置营业时段规则
打开Compute Open Slots代码节点的CONFIGURE块,设置时区(如Asia/Shanghai)、每天开门与打烊时间、工作日、时段长度SLOT_MINS、最短提前量和一次报出的空位个数。预约时长必须和Create Event节点的事件时长保持一致,否则日历事件和口头承诺对不上。下方给出本站编写的独立示例代码供理解逻辑,原模板代码以其画布为准。
配置三个工具分支
流程收到POST后先标准化Vapi负载,取出工具名与参数进Switch节点:checkAvailability分支读日历近期事件、算空位、返回可朗读JSON;bookAppointment分支按startTime创建日历事件、追加表格、发邮件;takeMessage分支追加表格、发邮件、回确认;其余事件回空确认。填好日历、Sheets、SMTP三处凭证和两个邮件节点的收发地址。
用合成payload逐分支测试
在n8n测试执行里向webhook POST下方的bookAppointment合成payload,应看到日历新增事件、表格新增一行、店主收到邮件;再测checkAvailability应返回含ISO时间戳的空位列表。
在Vapi配置三个server tools
在Vapi助手后台新建三个server tools,URL都填生产webhook地址:checkAvailability无参数;bookAppointment带customerName、phoneNumber、service、startTime四个参数;takeMessage带callerName、phoneNumber、message三个参数。用Vapi的测试通话功能各触发一次。
可直接复制的材料
Vapi三个server tools定义(本站整理)
名称与参数来自原模板说明;在Vapi后台录入时,三个工具的server URL都填同一生产webhook地址。
[
{"name": "checkAvailability", "description": "查询最近可预约的空位", "parameters": {"type": "object", "properties": {}}},
{"name": "bookAppointment", "description": "在指定时间创建预约", "parameters": {"type": "object", "properties": {
"customerName": {"type": "string"},
"phoneNumber": {"type": "string"},
"service": {"type": "string"},
"startTime": {"type": "string", "description": "ISO 8601时间,来自checkAvailability返回的选项"}},
"required": ["customerName", "phoneNumber", "service", "startTime"]}},
{"name": "takeMessage", "description": "记录来电留言", "parameters": {"type": "object", "properties": {
"callerName": {"type": "string"},
"phoneNumber": {"type": "string"},
"message": {"type": "string"}},
"required": ["callerName", "phoneNumber", "message"]}}
]空位计算逻辑示例(本站独立编写)
本站按模板描述编写的逻辑示意,非原模板代码;正式使用请以画布上Compute Open Slots节点实际代码为准并核对字段名。
// CONFIGURE 块:按业务修改
const CONFIGURE = {
TIMEZONE: "Asia/Shanghai",
OPEN_HOUR: 9,
CLOSE_HOUR: 18,
WORK_DAYS: [1, 2, 3, 4, 5], // 周一至周五
SLOT_MINS: 60,
MIN_NOTICE_HOURS: 2,
OFFER_COUNT: 3
};
// 逻辑:从『现在+最短提前量』起,逐SLOT_MINS扫描未来7天,
// 跳过非工作日与非营业时段,与已拉取的日历事件比对冲突,
// 收集满OFFER_COUNT个空位后返回,每项含ISO startTime与可读文本。bookAppointment合成测试payload
本站虚构测试数据,电话号码为占位号段;Vapi实际负载结构以Vapi文档和你收到的真实请求为准。
{
"message": {
"type": "tool-calls",
"toolCallList": [{
"id": "call_test_001",
"name": "bookAppointment",
"arguments": {
"customerName": "测试客户王芳",
"phoneNumber": "+8613800000000",
"service": "首次到店咨询",
"startTime": "2026-10-08T14:00:00+08:00"
}
}]
}
}输入与输出示例
本站虚构演示,空位为按示例规则手工推演的结果,未实际运行工作流。
输入
上午10点有来电问『最近哪天下午有空?』,语音助手调用checkAvailability;配置为营业9点到18点、工作日、时段60分钟、最短提前2小时、报3个空位,日历中10月8日14点到15点已有事件。对应输出
返回给Vapi的可朗读JSON:{"spoken": "最近的可约时间是:10月8日周四中午12点、下午1点,和10月8日下午3点。您想约哪一个?", "options": [{"startTime": "2026-10-08T12:00:00+08:00", "label": "10月8日中午12点"}, {"startTime": "2026-10-08T13:00:00+08:00", "label": "10月8日下午1点"}, {"startTime": "2026-10-08T15:00:00+08:00", "label": "10月8日下午3点"}]}。上午10点来电加2小时最短提前量,空位从12点开始计算;14点选项因已有日历事件被排除。做完检查这些
- POST合成的bookAppointment payload后,primary日历在指定startTime出现新事件且时长与SLOT_MINS一致
- 同一请求在Sheet新增一行,Type为booking,六个列均有值,店主邮箱收到预约通知
- checkAvailability返回的每个option都含ISO格式startTime,且全部晚于『当前时间+最短提前量』、不与现有日历事件冲突
- takeMessage分支新增Type为message的表格行并触发邮件,且回给Vapi确认文本
- 发送非工具调用类事件(如状态通知)时流程返回空确认,不产生任何日历、表格或邮件副作用
容易卡住的地方
- Create Event节点的事件时长若忘记与SLOT_MINS同步,口头承诺的时段长度和日历占位会不一致
- 模板默认用primary日历,多人共用门店日历时需改为指定日历ID,否则约到私人日历上
- 时区配置错误会让语音助手报出的时间和实际营业时间整体偏移,跨国团队尤其要查CONFIGURE里的TIMEZONE
- Vapi里工具名或参数名与Switch分支不一致时调用会落入默认分支,看似成功实则什么都没发生
- webhook必须用生产地址,测试地址在Vapi侧不会持续生效
- 作者说明模板源自真实生产系统,但不同业务的预约规则需自行改造,未核实的界面与参数以原模板画布为准
本站借助AI整理来源事实,独立编写中文操作指南与示例。示例不代表实际运行结果;来源效果尚未由本站独立复现。付费模板与模型、服务费用分别计算。
- 原文标题
- Handle voice receptionist bookings with Vapi, Google Calendar and Sheets
- 原作者
- Ali Amin
- 原始发布日期
- 2026-10-01T14:33:43.774Z
- 来源
- https://n8n.io/workflows/20302