工作流
用 Twilio + LLM 把 AI 客服接进 WhatsApp(半小时跑通沙箱)
做海外业务,你迟早会发现:用户全在 WhatsApp 上,而不是你的 App 里。与其逼他们下载新应用,不如把 AI 客服直接「开」进 WhatsApp。Twilio 的 WhatsApp Sandbox + Flask + 大模型 能让你半小时内跑通一个会收消息、查知识库、自动回复的智能体。本教程手把手带你从沙箱到生产意识。
💬 本教程适合:做出海/海外客服、想用 WhatsApp 触达用户的团队。需要一点 Python 基础。
先搞懂:沙箱是什么?
WhatsApp 正式号码要审核,周期长。Twilio 提供沙箱(Sandbox):一个共享测试号,你用 join 码加入就能立刻收发消息,适合先把链路跑通。正式上线再申请 Business API 号码。两者代码几乎一致,只是号码与合规要求不同。
Step 1:开通 Twilio 与 WhatsApp 沙箱
1 注册并加入沙箱
1. 注册 Twilio 免费账号(twilio.com)
2. 控制台 → Messaging → Try it out → Send a WhatsApp message
3. 记下分配给你的沙箱号(形如 +14155238886)
4. 用你的个人 WhatsApp 给该号发 join 加一段英文词(控制台可见)
5. 收到确认 = 已加入你的沙箱
费用与合规:沙箱免费仅用于测试;正式对外必须走 WhatsApp Business 审核,且模板消息、营销内容受Meta 政策约束。本教程仅做技术演示,群发营销前务必读清平台规则。
Step 2:最小 Flask webhook
2 先让机器人回「收到」
Twilio 在你收到消息时会 POST 到你的 webhook。用 Flask 接住,返回 TwiML 即可回复。
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
app = Flask(__name__)
@app.route("/whatsapp", methods=["POST"])
def reply():
msg = request.form.get("Body", "")
resp = MessagingResponse()
resp.message("收到你的消息:" + msg)
return str(resp)
if __name__ == "__main__":
app.run(port=5000)
💡 把本地服务用 ngrok 暴露:
ngrok http 5000,把https://xxx.ngrok-free.app/whatsapp填到沙箱设置的 When a message comes in。发消息即可收到回执。注意 ngrok 免费版地址每次重启会变。Step 3:接大模型做智能回复
3 知识库优先,LLM 兜底
先查本地知识库( pricing/hours 等高频问),命中就直接答;没命中再交给大模型,省 token 又稳。
KNOWLEDGE = {
"pricing": "基础版每月 49 美元起。",
"hours": "周一至周五 9:00-18:00。",
}
@app.route("/whatsapp", methods=["POST"])
def reply():
msg = request.form.get("Body", "").lower()
resp = MessagingResponse()
for k, ans in KNOWLEDGE.items():
if k in msg:
resp.message(ans)
return str(resp)
# 没命中走 LLM(用任意 OpenAI 兼容 SDK)
ai = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role":"system","content":"你是客服助手,用中文简洁回答。"},
{"role":"user","content": msg}],
)
resp.message(ai.choices[0].message.content)
return str(resp)
外部输入不可信:用户发来的 Body 是外部输入,拼进提示词前要做长度与内容校验,避免被注入带偏;返回内容也建议先人审关键场景。
Step 4:加会话记忆与指令
4 让对话连续
用每个用户的 WhatsApp 号码当 key,存最近 N 条历史,拼进 messages,机器人就能记得上下文。
history = {} # 生产用数据库,勿用内存
def reply():
sender = request.form.get("From", "")
msg = request.form.get("Body", "")
hist = history.get(sender, [])
hist.append({"role":"user","content": msg})
hist = hist[-10:] # 只留最近 10 条
ai = client.chat.completions.create(model="gpt-4o-mini", messages=hist)
hist.append({"role":"assistant","content": ai.choices[0].message.content})
history[sender] = hist
...
🔑 记忆要设上限(条数/字数),既控成本也防上下文溢出;生产环境用 Redis/数据库替代内存字典,否则重启即丢。
Step 5:人审兜底与护栏
5 危险动作必须人确认
涉及退款、下单、转账等敏感操作,机器人只生成「待确认草稿」,必须人工点确认才执行;并对高频消息做限流。
# 伪代码:敏感意图识别
if "退款" in msg or "下单" in msg:
resp.message("该操作需人工确认,已转接客服,请稍候。")
# 触发人工工单,不自动执行
return str(resp)
绝不自动执行危险操作:WhatsApp 是强触达渠道,自动退款/扣款/发营销一旦出错影响面大。所有写操作走 human-in-the-loop,机器人只读取与建议。
Step 6:从沙箱到生产
6 上线前要做的
· 申请 WhatsApp Business 号码并完成 Meta 审核
· 把 Flask 部署到稳定公网(Render / Railway / 自有服务器),配 HTTPS
· 用固定域名/webhook,替代会变的 ngrok
· 模板消息(template)用于主动触达,受平台模板规则约束
· 配置费用告警,防止消息量失控
🎉 沙箱验证完逻辑,生产只换「号码 + 托管地址 + 合规模板」,业务代码基本不动。后续可把 LLM 换成你自己的 Agent,接订单/物流等后端系统。
常见问题速查
| 现象 | 原因与解决 |
|---|---|
| 收不到消息 | webhook 地址填错/未公网可达;ngrok 地址变了 |
| 回复 200 但用户没收到 | 返回的不是合法 TwiML 文本 |
| 沙箱加不进 | join 码拼错或发给了错误号码 |
| 生产发不出去 | Business 号码未审核/模板未过 |