Hindsight × elizaOS 集成指南:为 Agent 接入长期记忆的官方插件 @vectorize-io/hindsight-eliza
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
Hindsight 在 v0.1.0 版本中正式发布了面向 elizaOS 的长期记忆集成插件@vectorize-io/hindsight-eliza(对应仓库目录 hindsight-integrations/eliza),让 elizaOS 智能体能够通过 Hindsight 存储与检索持久化记忆。本文以该集成的变更日志为脉络,结合插件源码与测试用例,完整讲解插件的安装、接入方式、全部配置项、底层实现原理与故障安全行为,帮助你在一小时内为自己的 eliza 角色接入可长期演进的记忆能力。
一、从变更日志看这个集成的定位
eliza 集成变更日志 记录了该集成的首个版本 v0.1.0 的核心变更:
Added a Hindsight long-term memory integration for elizaOS, enabling eliza to store and retrieve persistent memories via Hindsight.
这是该插件唯一也是最重要的一个特性:为 elizaOS 增加基于 Hindsight 的长期记忆能力——eliza 既能将对话"记住"(store),又能在后续对话中"想起"(retrieve)。该特性由 @benfrank241 贡献,提交号为 f36a462d1。
集成以独立 npm 包@vectorize-io/hindsight-eliza形式发布,源码完整托管在仓库的 hindsight-integrations/eliza 目录下,包含源码(src/)、测试(tests/)与打包配置(package.json、tsup.config.ts)。
二、插件架构:一个 Provider + 一个 Evaluator
从 plugin.ts 的源码可以看到,这个插件只做两件事,分别对应 elizaOS 的两个扩展点:
HINDSIGHT_MEMORYProvider(读取):在每次模型调用前,用当前用户消息查询 Hindsight,把相关记忆注入提示词上下文;HINDSIGHT_RETAINEvaluator(写入):在每轮对话结束后,把消息持久化到 Hindsight。
// hindsight-integrations/eliza/src/plugin.ts(核心逻辑) export function createHindsightPlugin(options: HindsightPluginOptions): Plugin { const { client, bank, recall = {}, retain = {} } = options; const providers = recall.enabled === false ? [] : [createHindsightProvider(client, bank, recall)]; const evaluators = retain.enabled === false ? [] : [createHindsightEvaluator(client, bank, retain)]; return { name: "@vectorize-io/hindsight-eliza", description: "Hindsight long-term memory: recall relevant memories and retain conversations.", providers, evaluators, }; }两个组件默认同时开启,并且是"叠加"在 elizaOS 自身既有记忆机制之上运行的,而不是替换它。recall.enabled与retain.enabled可分别关闭任意一侧——例如只做召回、只做留存,或干脆只保留 Provider/Evaluator 之一。这一行为在 tests/plugin.test.ts 中有对应用例覆盖("can disable both recall and retain"、"can disable only recall…"、"can disable only retain…")。
createHindsightProvider与createHindsightEvaluator也从 index.ts 单独导出,如果你想绕过插件、自己组装 Provider/Evaluator,可以直接使用它们。
三、安装与快速接入
3.1 安装依赖
需要同时安装插件本体和 Hindsight 官方客户端:
npm install @vectorize-io/hindsight-eliza @vectorize-io/hindsight-client环境要求(来自 package.json):
- peerDependency:
@elizaos/core^1.7.2(必须由宿主 eliza 项目提供); - Node.js:
>= 22; - 包以ESM形式发布(
"type": "module"),主入口为dist/index.js,类型声明为dist/index.d.ts。
3.2 最小接入示例
在角色定义(character)中挂载插件即可:
import { createHindsightPlugin } from "@vectorize-io/hindsight-eliza"; import { Hindsight } from "@vectorize-io/hindsight-client"; const hindsightPlugin = createHindsightPlugin({ client: new Hindsight({ apiKey: process.env.HINDSIGHT_API_KEY }), recall: { budget: "high", includeEntities: true }, retain: { tags: ["source:eliza"] }, }); export const character = { name: "Ada", plugins: [hindsightPlugin], };接入后,Ada的每一轮对话都会自动经历"先召回相关记忆 → 模型基于记忆作答 → 结束后把本次对话留存到 Hindsight"的完整闭环。
3.3 关于 memory bank(记忆库隔离)
插件默认按消息的entityId作为 bank 键——也就是"每个用户/每个 agent 一套独立记忆"。这是 options.ts 中resolveBank的默认行为:
export function resolveBank(bank: BankResolver | undefined, message: Memory): string { if (typeof bank === "function") return bank(message); if (typeof bank === "string" && bank.length > 0) return bank; return message.entityId; }bank参数支持两种形态:
- 固定字符串:所有消息读写同一个 bank(例如团队共享记忆
bank: "team-bank"); - 函数
(message) => string:按消息动态推导 bank,典型用法是按房间隔离(room:${message.roomId})或按用户隔离。
resolveBank的解析优先级在 tests/options.test.ts 中有完整用例验证:函数优先 → 非空字符串 → 回退entityId;空字符串也会回退到entityId。
四、完整配置项详解
以下配置表完整继承自集成文档,并补充了源码层面的默认值与语义(源码见 options.ts):
| Option | 说明 | 默认值 |
|---|---|---|
client | Hindsight 客户端实例(来自@vectorize-io/hindsight-client) | 必填 |
bank | 固定 bank 字符串,或(message) => string函数 | message.entityId |
recall.enabled | 是否启用召回 Provider | true |
recall.budget | 处理预算,"low" \| "mid" \| "high",权衡召回延迟与深度 | "mid" |
recall.types | 限定召回的事实类型("world" \| "experience" \| "observation") | 全部 |
recall.maxTokens | 召回结果的最大 token 上限 | API 默认 |
recall.includeEntities | 是否在召回中附带实体观测(entity observations) | false |
recall.heading | 注入提示词时召回记忆上方的标题 | # Relevant long-term memories |
retain.enabled | 是否启用留存 Evaluator | true |
retain.async | 是否异步留存(fire-and-forget,不增加对话延迟) | true |
retain.tags | 为每条留存记忆附加的标签数组 | — |
retain.metadata | 为每条留存记忆附加的元数据对象 | — |
retain.includeAgentMessages | 是否同时留存 agent 自己的回复 | false |
4.1 客户端最小接口(structural subset)
插件并不直接依赖@vectorize-io/hindsight-client,而是在 client.ts 中定义了一个结构子集接口HindsightClient,只要求实现两个方法:
export interface HindsightClient { retain(bankId: string, content: string, options?: { timestamp?: Date | string; context?: string; metadata?: Record<string, string>; documentId?: string; tags?: string[]; async?: boolean; }): Promise<RetainResponse>; recall(bankId: string, query: string, options?: { types?: FactType[]; maxTokens?: number; budget?: Budget; includeEntities?: boolean; includeChunks?: boolean; }): Promise<RecallResponse>; }这种设计意味着:只要对象实现了recall/retain两个方法,就能作为client传入——既方便在测试中注入 mock,也便于接入自建网关或代理实现。
五、底层实现原理
5.1 Provider 的召回与提示词注入
provider.ts 中,Provider 名为HINDSIGHT_MEMORY、dynamic: false。每次get()被调用时:
- 取出
message.content.text并trim();如果消息为空,直接短路返回,不会发起网络请求(对应测试 "returns empty text for an empty message without calling recall"); - 调用
client.recall(bankId, query, {...}),把types/maxTokens/budget/includeEntities原样透传; - 将召回结果格式化为 Markdown 无序列表,渲染在
heading之下:
function formatMemories(results: RecallResult[], heading: string): string { const lines = results .map((r) => r.text?.trim()) .filter((text): text is string => Boolean(text)) .map((text) => `- ${text}`); if (lines.length === 0) return ""; return `${heading}\n${lines.join("\n")}`; }- 返回结构包含三部分:
text(注入提示词的渲染文本)、values.hindsightMemoryCount(命中记忆条数,可被 eliza 的模板/状态系统读取)、data.hindsight(原始响应,供调试追踪)。
RecallResult的字段(client.ts)包括id、text、type、entities、context、occurred_start/end、mentioned_at、document_id、metadata、chunk_id,可见 Hindsight 回传的记忆带有完整的时间与溯源信息,可在上层做进一步加工。
5.2 Evaluator 的留存时机与去重逻辑
evaluator.ts 中,Evaluator 名为HINDSIGHT_RETAIN、alwaysRun: true。它选择在"每轮对话处理完之后"运行,这正是持久化新记忆的天然时机。处理逻辑:
validate()只放行含非空文本的消息;- 默认留存触发消息本身,但如果该消息是 agent 自己的且未开启
includeAgentMessages,则跳过(避免把 agent 的回复当成用户记忆存入,对应测试 "skips the agent's own message by default"); - 开启
includeAgentMessages后,还会遍历responses把 agent 本轮的每条回复也依次留存(对应测试 "retains agent replies when includeAgentMessages is set"); async: true(默认)时对外直接返回 resolved promise,真正的留存请求在后台 fire-and-forget,不增加对话时延;async: false时才等待完成,适合需要确认写入成功的场景。
5.3 故障安全(fail-safe)设计
集成文档明确承诺:"a Hindsight outage never blocks the agent from responding."(Hindsight 宕机绝不会阻塞 agent 响应)。这一点在源码与测试中都有硬保证:
- Provider:
recall抛错时被try/catch捕获,返回空文本与hindsightError错误信息,绝不向上抛出(provider.ts,对应测试 "never throws when recall fails"); - Evaluator:
retain的 promise 被.catch(() => undefined)吞掉,即使写入失败也不会让回合失败(evaluator.ts,对应测试 "does not reject the turn when retain fails (async mode)")。
也就是说,记忆服务不可用时,eliza 依然可以正常对话,只是"召回为空、留存失败",记忆能力优雅降级。
六、从配置项到客户端的完整调用链
综合 options.ts、provider.ts、evaluator.ts 与 client.ts,插件的调用链可以归纳为:
elizaOS 角色 (character.plugins) └─ createHindsightPlugin({ client, bank, recall, retain }) ├─ HINDSIGHT_MEMORY Provider(每轮模型调用前) │ └─ resolveBank() → client.recall(bankId, query, {types, maxTokens, budget, includeEntities}) │ └─ 格式化 → 注入提示词(heading + 记忆列表)→ values.hindsightMemoryCount └─ HINDSIGHT_RETAIN Evaluator(每轮结束后) └─ resolveBank() → client.retain(bankId, text, {async, tags, metadata}) └─ (可选)遍历 responses 留存 agent 回复测试 tests/plugin.test.ts 通过 mock client 验证了整条链路上的关键行为,包括:默认同时注册 Provider 与 Evaluator、bank覆盖、recall选项透传(budget: "high"、types: ["world"]、includeEntities: true、maxTokens: 500均按原样传给客户端)、空消息短路、故障容错等。这些用例本身就是很好的"集成行为参考说明书"。
七、常见接入场景与建议
- 按用户隔离记忆:不传
bank,默认以entityId分库,每个用户一套独立长期记忆,适合 C 端助手; - 按房间/群组共享记忆:
bank: (message) => \room:${message.roomId}``,同房间成员共享上下文,适合协作场景; - 团队统一知识库:
bank: "team-bank"固定库,所有消息读写同一个 bank; - 降低召回噪音:
recall.types: ["world"]只召回世界性事实;maxTokens限制注入的 token 量; - 调试与追踪:关注 Provider 返回的
data.hindsight(含trace/entities/chunks原始响应)与values.hindsightMemoryCount; - 本地开发验证:在 hindsight-integrations/eliza 目录下执行
npm install、npm test、npm run build即可跑通测试与打包(项目使用 vitest + tsup)。
八、小结
@vectorize-io/hindsight-eliza是 Hindsight 官方为 elizaOS 提供的长期记忆插件,v0.1.0 以"一个 Provider + 一个 Evaluator"的极简架构实现了记忆的召回与留存闭环:默认按entityId分库隔离、支持bank自定义、全部召回/留存参数可调,并以源码级的 try/catch 与 promise 吞错保证了记忆服务故障时的优雅降级。若想深入源码,建议从 plugin.ts(装配入口)、provider.ts(召回)、evaluator.ts(留存)三个文件读起,配合 tests/plugin.test.ts 验证你对各行为的理解。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考