You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Twilio WhatsApp API为聊天机器人保留会话状态

解决Twilio机器人的会话状态保留问题

你遇到的问题非常典型——因为HTTP是无状态协议,Twilio每次推送用户消息都是一个全新的POST请求,默认情况下机器人根本没法记住之前的对话上下文。要搞定这个问题,核心思路就是把每个用户的会话状态单独存储起来,下面给你几个适配当前技术栈的落地方案:

方案1:内存存储(快速开发测试用)

如果只是处于开发调试阶段,可以用一个简单的JS对象临时存储用户状态,用用户的From号码作为唯一标识(每个用户的WhatsApp号码都是独一无二的,刚好能对应会话)。

修改你的whatsapp/main.js:

const accountSid = "accountSid";
const authToken = "authToken";
const client = require("twilio")(accountSid, authToken);
const MessagingResponse = require("twilio").twiml.MessagingResponse;

// 内存存储会话状态,仅用于开发测试!生产环境绝对不能用
const userSessions = {};

function sendResponse(req, res, next) {
  const userNumber = req.body.From;
  const userMessage = req.body.Body.trim().toLowerCase();
  const twiml = new MessagingResponse();

  // 获取用户当前会话状态,默认是"空闲"
  const currentState = userSessions[userNumber] || "idle";

  if (currentState === "idle") {
    if (userMessage === "show me movies") {
      twiml.message("in what language?");
      // 更新状态:等待用户输入电影语言
      userSessions[userNumber] = "awaiting_movie_language";
    } else {
      twiml.message("Hi there! Type 'show me movies' to get started.");
    }
  } else if (currentState === "awaiting_movie_language") {
    // 这里可以扩展逻辑,比如调用电影API获取对应语言的影片列表
    twiml.message(`Got it! Showing you *${userMessage}* movies right away.`);
    // 重置会话状态为空闲
    userSessions[userNumber] = "idle";
  }

  res.writeHead(200, { "Content-Type": "text/xml" });
  res.end(twiml.toString());
}

module.exports = { sendResponse };

⚠️ 注意:内存存储的致命缺点是服务器重启后所有状态都会丢失,而且没法支持多服务器部署(状态不共享),所以只适合开发调试用。

方案2:Redis存储(生产环境推荐)

生产环境下,首推用Redis这种内存数据库存储会话状态——它速度快,支持设置过期时间(自动清理闲置会话),还能在多服务器之间共享状态,完美适配生产场景。

步骤1:安装Redis依赖

npm install redis

步骤2:修改whatsapp/main.js集成Redis

const accountSid = "accountSid";
const authToken = "authToken";
const client = require("twilio")(accountSid, authToken);
const MessagingResponse = require("twilio").twiml.MessagingResponse;
const redis = require("redis");

// 创建Redis客户端,替换成你的Redis实际地址
const redisClient = redis.createClient({
  url: "redis://localhost:6379"
});
redisClient.connect().catch(console.error);

async function sendResponse(req, res, next) {
  const userNumber = req.body.From;
  const userMessage = req.body.Body.trim().toLowerCase();
  const twiml = new MessagingResponse();

  // 从Redis获取用户当前状态,默认是"idle"
  const currentState = await redisClient.get(`session:${userNumber}`) || "idle";

  if (currentState === "idle") {
    if (userMessage === "show me movies") {
      twiml.message("in what language?");
      // 存储状态并设置2小时过期,避免闲置会话占用资源
      await redisClient.setEx(`session:${userNumber}`, 7200, "awaiting_movie_language");
    } else {
      twiml.message("Hi there! Type 'show me movies' to get started.");
    }
  } else if (currentState === "awaiting_movie_language") {
    twiml.message(`Got it! Showing you *${userMessage}* movies right away.`);
    // 清理当前会话状态
    await redisClient.del(`session:${userNumber}`);
  }

  res.writeHead(200, { "Content-Type": "text/xml" });
  res.end(twiml.toString());
}

module.exports = { sendResponse };

关键注意点

  • 始终用From号码作为会话的唯一标识,确保不同用户的上下文不会混淆
  • 生产环境绝对不能用内存存储,必须用Redis、MongoDB这类持久化/分布式存储方案
  • 给会话状态设置合理的过期时间,自动清理长期闲置的会话,节省服务器资源

这样改造后,你的机器人就能完美记住用户的上下文了——比如用户回复"english"时,机器人会立刻明白这是针对「电影语言」的回复,而不是一个全新的独立请求。

内容的提问来源于stack exchange,提问作者obiwankenoobi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:37:34