Hindsight × elizaOS 集成指南:为 Agent 接入长期记忆的官方插件 @vectorize-io/hindsight-eliza
2026/9/15 5:52:30 网站建设 项目流程

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.jsontsup.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.enabledretain.enabled可分别关闭任意一侧——例如只做召回、只做留存,或干脆只保留 Provider/Evaluator 之一。这一行为在 tests/plugin.test.ts 中有对应用例覆盖("can disable both recall and retain"、"can disable only recall…"、"can disable only retain…")。

createHindsightProvidercreateHindsightEvaluator也从 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说明默认值
clientHindsight 客户端实例(来自@vectorize-io/hindsight-client必填
bank固定 bank 字符串,或(message) => string函数message.entityId
recall.enabled是否启用召回 Providertrue
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是否启用留存 Evaluatortrue
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_MEMORYdynamic: false。每次get()被调用时:

  1. 取出message.content.texttrim();如果消息为空,直接短路返回,不会发起网络请求(对应测试 "returns empty text for an empty message without calling recall");
  2. 调用client.recall(bankId, query, {...}),把types/maxTokens/budget/includeEntities原样透传;
  3. 将召回结果格式化为 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")}`; }
  1. 返回结构包含三部分:text(注入提示词的渲染文本)、values.hindsightMemoryCount(命中记忆条数,可被 eliza 的模板/状态系统读取)、data.hindsight(原始响应,供调试追踪)。

RecallResult的字段(client.ts)包括idtexttypeentitiescontextoccurred_start/endmentioned_atdocument_idmetadatachunk_id,可见 Hindsight 回传的记忆带有完整的时间与溯源信息,可在上层做进一步加工。

5.2 Evaluator 的留存时机与去重逻辑

evaluator.ts 中,Evaluator 名为HINDSIGHT_RETAINalwaysRun: 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 响应)。这一点在源码与测试中都有硬保证:

  • Providerrecall抛错时被try/catch捕获,返回空文本与hindsightError错误信息,绝不向上抛出(provider.ts,对应测试 "never throws when recall fails");
  • Evaluatorretain的 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: truemaxTokens: 500均按原样传给客户端)、空消息短路、故障容错等。这些用例本身就是很好的"集成行为参考说明书"。

七、常见接入场景与建议

  1. 按用户隔离记忆:不传bank,默认以entityId分库,每个用户一套独立长期记忆,适合 C 端助手;
  2. 按房间/群组共享记忆bank: (message) => \room:${message.roomId}``,同房间成员共享上下文,适合协作场景;
  3. 团队统一知识库bank: "team-bank"固定库,所有消息读写同一个 bank;
  4. 降低召回噪音recall.types: ["world"]只召回世界性事实;maxTokens限制注入的 token 量;
  5. 调试与追踪:关注 Provider 返回的data.hindsight(含trace/entities/chunks原始响应)与values.hindsightMemoryCount
  6. 本地开发验证:在 hindsight-integrations/eliza 目录下执行npm installnpm testnpm 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),仅供参考

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

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

立即咨询