Hindsight Chat SDK 多平台机器人:用一套 Handler 让 Slack 与 Discord 共享同一份 Agent 记忆
2026/9/14 11:52:29 网站建设 项目流程

Hindsight Chat SDK 多平台机器人:用一套 Handler 让 Slack 与 Discord 共享同一份 Agent 记忆

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

本文是 Hindsight 官方 Cookbook 中 "Chat SDK Multi-Platform Bot" 应用案例的深度技术解读。它展示如何基于 Vercel Chat SDK、Hindsight 与 Vercel AI SDK 构建一个同时在 Slack 和 Discord 上运行、共享同一个 Hindsight 记忆库的聊天机器人:在 Slack 中告诉它任何事,再到 Discord 里问它,它能完整回忆起来。读完本文,你将掌握withHindsightChat()包装器的完整工作原理、全部可配置项、bankId 隔离策略,以及端到端部署的每一步细节。

核心能力一览

能力说明
跨平台记忆Slack 与 Discord 共享同一个 Hindsight 记忆库(memory bank)
LLM 驱动的回答通过 Vercel AI SDK 调用 OpenAI 生成回复
自动召回(auto-recall)每次响应前自动检索相关记忆
自动留存(auto-retain)对话内容自动写入记忆库
一个 Handler 覆盖所有平台withHindsightChat()包装任意 Chat SDK handler

架构:一次封装,多端复用

Slack message ─────┐ ├─→ withHindsightChat() ─→ auto-recall ─→ LLM handler ─→ auto-retain Discord message ───┘ │ ▼ Hindsight API (shared bank)

从源码结构看,这一模式的核心并不复杂:所有平台的消息在进入你编写的 LLM handler 之前,先统一经过withHindsightChat()这个高阶函数;它负责把"当前消息属于哪个记忆库"解析出来、召回相关记忆、构建携带记忆上下文的ctx对象,再交给你自己的 handler。而 Slack 与 Discord 的差异(HTTP 推送 vs WebSocket Gateway)只体现在适配器层,记忆逻辑完全共用。

深入源码:withHindsightChat()的执行管线

官方示例的关键文件是lib/bot.ts。Slack 与 Discord 两个适配器注册到同一个 Chat 实例,且都使用withHindsightChat()并共享同一个 bank ID:

bot.onNewMention( withHindsightChat( { client: hindsight, bankId: () => BANK_ID, // 所有平台共用同一 bank retain: { enabled: true }, }, async (thread, message, ctx) => { const system = ctx.memoriesAsSystemPrompt(); // ... 携带记忆上下文生成 LLM 响应 } ) );

在仓库的 hindsight-integrations/chat/src/wrapper.ts 中可以看到它的完整实现。每次消息到达时,包装器严格按 5 个步骤执行:

  1. 解析 bank IDbankId可以是字符串,也可以是接收message并返回字符串的函数(wrapper.ts);
  2. 可选地自动留存入站消息(默认关闭):仅当retain.enabled === true、消息有文本且author.isMe不为真时触发;async模式(默认true)下是 fire-and-forget,不阻塞响应(wrapper.ts);
  3. 自动召回记忆(默认开启):以消息文本作为查询调用client.recall(),默认budget: "mid"includeEntities: true(wrapper.ts);
  4. 构建HindsightChatContext:把bankIdmemoriesentities以及memoriesAsSystemPrompt()/retain()/recall()/reflect()方法打包成ctx(wrapper.ts);
  5. 调用你的 handlerawait handler(thread, message, ctx)(wrapper.ts)。

这套行为在 wrapper.test.ts 中都有对应测试佐证:静态与动态 bankId 解析、默认召回、recall: { enabled: false }跳过召回、空文本跳过召回与留存、机器人消息(isMe)不自动留存、错误被降级为 warning 且 handler 仍继续执行等。

memoriesAsSystemPrompt()的格式化细节

ctx.memoriesAsSystemPrompt()内部调用 format.ts 的formatMemoriesAsSystemPrompt()。默认 preamble 为:

You have access to the following memories about this user from previous interactions:

输出按<memories><entity_observations>两个 XML 风格区块组织,例如:

You have access to the following memories about this user from previous interactions: <memories> - User prefers dark mode [experience] - Likes coffee [world] </memories> <entity_observations> ## Alice - Works at Acme Corp - Prefers TypeScript </entity_observations>

当没有任何记忆或实体时返回空字符串,因此你可以安全地拼接或按需追加。格式化选项见 types.ts:preamblemaxMemoriesincludeTypesincludeEntities

配置参考:完整选项与上下文 API

以下配置表格来自 @vectorize-io/hindsight-chat 的 README,与源码类型定义 types.ts 完全一致。

withHindsightChat(options, handler)的 Options

选项类型默认值说明
clientHindsightClient必填Hindsight 客户端实例(指向你的 Hindsight API)
bankIdstring \| (msg) => string必填记忆库 ID,静态字符串或解析函数
recall.enabledbooleantrue在 handler 运行前自动召回记忆
recall.budget'low' \| 'mid' \| 'high''mid'召回处理预算
recall.maxTokensnumberAPI 默认召回结果的 token 上限
recall.typesFactType[]全部只召回指定事实类型(world/experience/observation
recall.includeEntitiesbooleantrue是否包含实体观测
retain.enabledbooleanfalse自动留存入站消息
retain.asyncbooleantrue是否 fire-and-forget 留存
retain.tagsstring[]为留存记忆附加标签
retain.metadataRecord<string, string>为留存记忆附加元数据

传给 handler 的ctx(第三个参数)

属性 / 方法说明
ctx.bankId已解析出的 bank ID
ctx.memories召回的记忆数组(RecallResult[]
ctx.entities实体观测(未启用时为null
ctx.memoriesAsSystemPrompt(options?)把记忆格式化为 LLM system prompt
ctx.retain(content, options?)将内容写入记忆库
ctx.recall(query, options?)检索记忆
ctx.reflect(query, options?)基于记忆进行推理归纳

值得一提的是,withHindsightChat兼容onNewMentiononSubscribedMessageonNewMessage三种事件,并且包把chat声明为 peer dependency(见 package.json),要求chat ^4.0.0、Node.js ≥ 22,因此它可适配 Slack、Discord、Teams、Google Chat、GitHub、Linear 等多种平台。

从零部署:完整步骤

第 1 步:启动 Hindsight API

export OPENAI_API_KEY=your-key docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \ -e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \ -e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \ -v $HOME/.hindsight-docker:/home/hindsight/.pg0 \ ghcr.io/vectorize-io/hindsight:latest
  • API 地址:http://localhost:8888
  • Web UI 地址:http://localhost:9999

第 2 步:配置 Slack

  1. 打开 api.slack.com/apps 创建新应用;
  2. OAuth & Permissions中添加权限范围:app_mentions:readchat:writechannels:history
  3. 将应用安装到你的工作区;
  4. 复制Bot User OAuth TokenSigning Secret

第 3 步:配置 Discord

  1. 打开 discord.com/developers/applications 创建新应用;
  2. Bot下点击Reset Token并复制;
  3. 在 Privileged Gateway Intents 中启用Message Content Intent
  4. General Information下复制Application IDPublic Key
  5. OAuth2 > URL Generator中选择bot+applications.commands权限,并勾选 Send Messages、Read Message History;
  6. 使用生成的 URL 将机器人邀请进服务器。

第 4 步:配置环境变量

cp .env.example .env.local # 编辑 .env.local 填入你的 token

或手动创建.env.local

# Slack SLACK_BOT_TOKEN=xoxb-... SLACK_SIGNING_SECRET=... # Discord DISCORD_BOT_TOKEN=... DISCORD_PUBLIC_KEY=... DISCORD_APPLICATION_ID=... DISCORD_MENTION_ROLE_IDS=... # 可选:逗号分隔的 role ID # Hindsight HINDSIGHT_API_URL=http://localhost:8888 # LLM OPENAI_API_KEY=sk-...

第 5 步:暴露本地服务

Slack 与 Discord 需要通过 webhook 端点访问你的服务:

ngrok http 3000
  • 将 Slack 的Event Subscriptions > Request URL设为https://your-ngrok-url/api/webhooks/slack
  • 将 Discord 的Interactions Endpoint URL设为https://your-ngrok-url/api/webhooks/discord

第 6 步:安装并运行

npm install npm run dev

第 7 步:启动 Discord Gateway

与 Slack 通过 HTTP 推送事件不同,Discord 需要 WebSocket 连接才能接收消息。dev server 启动后在浏览器中打开:

http://localhost:3000/api/discord/gateway

该 Gateway 连接会保持 10 分钟。生产环境建议用 cron 任务定期重启它。

Bank ID 策略:隔离 vs 共享

bank ID 的选择直接决定了记忆的边界,官方文档给出了三种典型策略:

策略示例适用场景
静态bankId: 'demo'团队共享记忆
按用户bankId: (msg) => msg.author.userId每个用户隔离的记忆
跨平台身份将各平台 ID 映射到规范用户同一用户、同一 bank、任意平台

从 wrapper.ts 的实现可以看到,动态bankId函数在每次消息到达时基于message求值,因此你可以根据message.author.userIdmessage.threadId甚至自定义映射函数自由决定记忆的归属。要做到"Slack 和 Discord 共享记忆",只需让两个平台的 bankId 解析结果一致(如本示例的() => BANK_ID)。

错误处理:记忆失败永不拖垮机器人

这是withHindsightChat的重要设计。自动召回与自动留存发生任何错误都只会打印[hindsight-chat] Auto-recall failed:[hindsight-chat] Auto-retain failed:警告日志,随后继续以空记忆执行你的 handler(见 wrapper.ts 与 wrapper.ts)。对应的测试用例见 wrapper.test.ts 与 wrapper.test.ts。

而你在 handler 内手动调用的ctx.retain()ctx.recall()ctx.reflect()则正常抛出异常,方便你按需处理。这意味着记忆系统是"尽力而为"的增强层,即使 Hindsight API 短暂不可用,聊天机器人的核心对话功能也不受影响。

动手体验

  1. Slack 中@memory-bot I'm building a Rust compiler that targets WebAssembly
  2. 等待几秒让 Hindsight 索引记忆
  3. Discord 中@memory-bot what am I working on?
  4. 机器人从 Slack 中召回 Rust/WebAssembly 相关记忆并作答

参考与延伸阅读

  • 集成包源码与类型定义:hindsight-integrations/chat/src/wrapper.ts、hindsight-integrations/chat/src/types.ts、hindsight-integrations/chat/src/format.ts
  • 集成包使用文档:hindsight-integrations/chat/README.md
  • 行为验证测试:hindsight-integrations/chat/src/wrapper.test.ts、hindsight-integrations/chat/src/format.test.ts
  • 官方 Cookbook 索引:cookbook/README.md

License:MIT

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询