基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-10-23 09:51

用无状态回调搭建 AI 电话接待

dev.to · AI#语音交互#无服务器#智能体
Editor brief · 编辑速览

作者拆解电话接待系统的完整链路:呼叫转接、语音转写、LLM 生成回复,再通过 Webhook 循环推进对话。实现采用无服务器后端和无状态轮次设计,通话结束后向商家发送需求及预约摘要。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

电话没人接,小商家可能就丢掉一笔生意。作者为加拿大小企业做了 AI 电话接待产品 Aethely,思路很直接:用 Twilio 接听和转写,用 LLM 决定下一句,再把来电需求整理成短信发给店主。

这套方案值得看的地方,是它把语音接待拆成了普通 HTTP 请求,并用结构化输出衔接业务流程。不过,无数据库状态和模型驱动转接都有适用前提,原文展示的是实现经验,没有提供效果对照或性能数据。

一通电话,怎么变成一组 HTTP 请求

客户拨打商家原来的号码,无人接听或已经下班时,运营商把电话转到系统控制的号码。Twilio 随后请求来电 webhook,后端返回 XML,告诉它先说什么、再听什么。

下面这段代码解决开场和收集语音的问题,也明确告知来电者正在与 AI 交流:

<Response>
  <Gather input="speech" action="/api/voice/turn?s=STATE"
          speechTimeout="auto" language="en-CA" actionOnEmptyResult="true">
    <Say>Hi, thanks for calling Northside Heating. I'm the virtual assistant,
    an AI. How can I help?</Say>
  </Gather>
</Response>

要看的是 actionOnEmptyResult="true":即使对方没说话,后端也能收到回调,自行处理沉默。speechTimeout="auto" 用于语音收集的超时判断,language="en-CA" 对应加拿大英语。

之后,Twilio 把转写文本交给 /api/voice/turn。后端带上商家资料和对话历史询问 LLM,再返回下一句和继续监听的指令,循环直到通话结束。

每一步都是独立的 HTTP 请求,适合放进 serverless functions。这里的「无状态」指函数实例不必记住上一次调用,对话历史仍然需要有地方存放。

把历史塞进 URL,省掉数据库要付出什么

常见做法是按 call ID,把历史存进数据库或缓存。作者选择压缩历史,再放进回调 URL 的 s 参数,让下一次函数调用直接拿到完整上下文。

下面两个函数完成状态的压缩编码与还原:

import { deflateRawSync, inflateRawSync } from 'node:zlib';

export const packState = (obj) =>
  deflateRawSync(Buffer.from(JSON.stringify(obj))).toString('base64url');

export const unpackState = (s) =>
  JSON.parse(inflateRawSync(Buffer.from(s, 'base64url')).toString());

要看的是 unpackState 中的解压和 JSON.parse:输入来自 URL,不能直接当成可信对象。作者也明确要求限制轮数,并校验解包后的内容。

这个取舍依赖一个具体条件:作者称,典型通话少于十轮,压缩后的历史足够小,因此可以省掉数据库和清理任务。但原文没有给出实际字节数、URL 长度上限,或长通话超限后的处理。

另外,base64url 是编码,不是加密。若历史包含姓名、电话和地址,还得考虑 URL 在日志中的留存。Webhook 验签与状态内容校验也要分别做,前者不能代替后者。

模型负责表达,代码负责执行

作者没有让后端从一段自然语言里猜测「是不是要转人工」,而是要求模型返回符合 schema 的 JSON:

  • say 是下一句要说的话,end_call 表示是否结束。
  • urgent 表示是否符合店主定义的紧急规则,transfer 表示是否立即转接。
  • details 包含 name、callback、need、address、booking,用于整理短信。

这五个顶层字段都列入 required。后端读取 transfer: true 后执行 <Dial>,读取 end_call: true 后挂断并发送摘要,业务分支不必依赖文本解析。

结构化输出能固定数据形状,但不能保证模型判断正确。

原文的 schema 也没有把 details 内的字段设为必填。因此,不能假定每次都能拿到完整联系方式和预约信息。作者没有给出所用模型、结构化输出 API、校验失败和重试代码,这些部分仍需补齐。

提示词则主要规定边界:营业时间、服务、允许公开的价格、预约窗口和紧急规则。信息不足就承认不知道并留言,不编造价格、空档和承诺,不提供医疗、法律或财务建议,回复保持简短。

失败分支同样属于主流程。第一次沉默询问是否还在,第二次沉默礼貌结束,并发送已收集的信息;通话结束的 status callback 则处理只持续几秒或未接通的情况,给来电者补发商家短信。

安全方面,每个 webhook 在处理前验证服务商签名,作者描述为对 URL 和参数计算 HMAC。延迟方面,他建议缩短模型输出、缓存提示词,并把摘要短信放到通话结束后发送。原文没有给出缓存实现或延迟测量结果。

我的判断

我认同作者对交付物的判断:店主真正需要的是一条能据此行动的短信,里面写清谁来电、需要什么、多紧急、预约了什么。原文示例把 Jordan、(780) 555-0142、暖炉故障和当天 2–4 PM 的预约或请求集中在一起,比让店主重新听留言更直接。

但「请求」和「已预约」必须分清。原文没有展示日历写入或预约确认过程,不能据此认定系统已经完成真实预约。

无数据库方案适合短对话和轻量流程;如果需要查询历史、恢复通话或审计,按 call ID 存储通常更容易管理。结构化输出优于解析自由文本,但转接、挂断等动作仍值得由后端检查规则。

至于「边界让店主信任系统」,这是作者的产品观察。原文没有提供接通率、转化率、成本或错误率的对照数据,不能据此判断它优于人工接听或普通语音留言。

能拿来做什么

  • 用 Node 做电话接待原型时,先跑通来电 webhook、语音转写回调和下一轮响应,再接入 LLM,分别验证电话链路与模型输出。
  • 给日常 AI 编程中的业务助手定义明确 schema,把回复内容和动作字段分开,并为字段缺失、校验失败、超时准备处理路径。
  • 采用 URL 携带状态时,同时设置轮数、输入大小和解压后大小限制;需要长期查询与审计时,改用 call ID 关联数据库或缓存。
  • 验收时检查沉默、提前挂断、信息不足和紧急来电的结果,并确认短信能区分预约请求与已确认预约。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
评估编程 Agent,要走完一次交付流程
下一篇
用 tokenecon 拆解每次智能体任务成本

资讯速览

dev.to · AI · 2026-10-23 09:51

AI 评分 8.0 / 10

相关标签

#语音交互#无服务器#智能体

继续阅读

  • Claude Code 如何发现并连接 MCP 服务
  • 评估编程 Agent,要走完一次交付流程
  • 用 tokenecon 拆解每次智能体任务成本
  • Agent Skills 转向基金会治理
  • 让 AI 先读懂数据库结构再执行查询