
Hindsight × Paperclip 集成指南为 Paperclip Agent 接入持久化长期记忆【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight本篇文章围绕开源仓库 Hindsight 中的vectorize-io/hindsight-paperclip插件展开完整讲解如何让 Paperclip Agent 通过 Hindsight 获得跨运行、跨公司、跨重启持久化的长期记忆安装方式、全部配置项与记忆银行Bank隔离模型、两个内置 Agent 工具hindsight_recall/hindsight_retain的使用方法以及插件背后的运行原理与源码实现。读完本文你将能够在自己的 Paperclip 实例中一键接入 Hindsight并掌握按公司、按 Agent、按用户三种记忆隔离粒度的选型方法。一、插件是什么给 Paperclip 装上会学习的记忆Paperclip 是一个自动化 AI Agent 平台但默认情况下Agent 每轮运行都是失忆的——它看不到上一次任务中积累的结论、用户偏好和已做过的决策。Hindsight项目仓库根目录见 README.md项目定位为 Agent Memory That Learns正是为了解决这一问题而设计的长期记忆服务它把 Agent 产生的信息组织进记忆银行Bank并提供语义召回recall与持久化retain能力。vectorize-io/hindsight-paperclip源码位于 hindsight-integrations/paperclip把两者打通安装一次整个 Paperclip 实例里的每个 Agent 都能获得持久记忆。它做的事情可以概括为三句话每次运行前Before each run——获取本次运行对应的 issue以其标题 描述作为查询向 Hindsight 召回相关历史记忆并缓存在插件状态中供本轮 Agent 使用每条评论后After each comment——将完整评论正文用户输出与 Agent 输出都包含保留到 Hindsight形成持久的运行记录Agent 工具Agent tools——暴露hindsight_recall和hindsight_retain两个工具允许 Agent 在运行中途主动查询与写入记忆。插件的元数据定义在 src/manifest.tsid 为paperclip-plugin-hindsight当前版本0.2.0核心生命周期逻辑全部在 src/worker.ts 中实现。二、安装与前置条件2.1 安装命令在你的 Paperclip 环境中执行pnpm paperclipai plugin install vectorize-io/hindsight-paperclip安装完成后进入Settings → Plugins → Hindsight Memory完成配置即可生效。说明插件清单manifest声明了运行所需的能力包括issues.read、issue.comments.read、events.subscribe、agent.tools.register、plugin.state.read/write、http.outbound、secrets.read-ref、agents.read见 src/manifest.ts。首次安装或升级时Paperclip 可能会弹出权限确认请允许这些能力。2.2 前置条件选择 Hindsight 后端插件本身不包含记忆存储能力它通过 HTTP 调用 Hindsight 服务。两种接入方式方式一推荐Hindsight Cloud注册 Hindsight Cloud 账号获取 API Key完全跳过自托管部署。方式二自托管 Hindsight在本地运行 Hindsight 服务pip install hindsight-all export HINDSIGHT_API_LLM_API_KEYyour-openai-key hindsight-api自托管默认监听http://localhost:8888后续配置hindsightApiUrl时填入该地址即可。三、配置项详解下表汇总了插件全部可配置字段与 src/manifest.ts 中instanceConfigSchema的定义一一对应FieldDefaultDescriptionhindsightApiUrlhttps://api.hindsight.vectorize.ioHindsight 服务地址Cloud 默认值自托管填http://localhost:8888hindsightApiKeyRef—存放 Hindsight Cloud API Key 的 Paperclip secret 名称dynamicBankIdtrue为true时Bank ID 由bankGranularity推导设为false并提供bankId则可让多个 Agent 共享一个静态记忆银行bankId—当dynamicBankId为false时使用的静态 Bank ID。所有共享该值的 Agent 读写同一个记忆银行bankGranularity[company, agent]dynamicBankId为true时的记忆隔离粒度按公司Agent、仅按公司、仅按 Agent追加user可实现按用户隔离对 GDPR 合规场景有用recallBudgetmidlow 最快mid 均衡high 最彻底autoRetaintrue每次运行后自动将运行输出保留到 HindsightenabledAgentIds—仅对这些 Agent ID 启用 recall/retain留空则对所有 Agent 启用默认3.1 配置校验机制从源码看插件在保存配置时会执行一次连通性校验src/worker.tshindsightApiUrl为空时直接返回错误hindsightApiUrl is required否则通过HindsightClient.health()探测/health端点若无法连通则返回Cannot reach Hindsight at ...或Connection failed: ...只有校验通过配置才允许保存。测试用例 tests/plugin.spec.ts 覆盖了这三种情形缺 URL、服务不可达、服务可达可作为排查配置问题的参考。四、记忆银行Bank与隔离模型4.1 Bank ID 格式Hindsight 的记忆按 Bank银行组织插件通过 Bank ID 决定这份记忆属于谁。Bank ID 的推导逻辑集中在 src/bank.ts 的deriveBankId()函数中格式如下paperclip::{companyId}::{agentId} ← 默认公司 Agent 粒度 paperclip::{companyId} ← 仅公司粒度跨 Agent 共享 paperclip::{agentId} ← 仅 Agent 粒度记忆跨公司 paperclip::{companyId}::{agentId}::user::{userId} ← 用户粒度按用户隔离GDPR 友好 {bankId} ← 静态共享银行dynamicBankId false4.2 动态推导 vs 静态银行动态模式默认dynamicBankId为true或未设置时按bankGranularity数组中的字段顺序拼接 Bank ID固定以paperclip前缀开头。例如[company, agent]生成paperclip::{companyId}::{agentId}。静态模式设置bankId且dynamicBankId不为true时直接原样返回bankId绕过所有推导逻辑源码见 src/bank.ts。这是让所有 Agent 读写同一份共享记忆的方式。几个容易混淆的边界行为在 tests/bank-edge-cases.spec.ts 中有明确测试静态优先同时设置bankId和用户粒度时只要dynamicBankId不为true静态bankId胜出显式覆盖是刻意设计dynamicBankId: true恢复动态即使设置了bankId只要dynamicBankId显式为true仍走动态推导空白bankId回退bankId为空白字符串空格/制表符/换行时视为未设置回退到动态推导无配置兜底完全不传配置时默认按[company, agent]推导src/bank.tsdynamicBankId未设置但设置了bankId由于undefined ! true走静态路径——这是向后兼容的关键行为见 tests/bank-edge-cases.spec.ts。4.3 用户粒度的用户身份提取启用user粒度后插件需要从 issue 中识别用户身份这一逻辑在extractUserFromIssue()src/bank.ts优先使用 issue 的creatorEmail字段否则解析originId字段格式为channel-key::user-email例如slack::aliceacme.com从后往前扫描分段取第一个包含的分段作为用户邮箱两者都无法识别时返回undefined此时 Bank ID 会省略 user 段回退到公司Agent 粒度tests/plugin.spec.ts 验证了该回退行为。五、两个 Agent 工具运行中的主动记忆读写插件向 Agent 注册两个工具参数 Schema 定义见 src/manifest.tshindsight_recall(query)—— 搜索记忆并返回相关上下文。运行开始时会被自动调用一次Agent 也可在运行中途针对特定问题主动调用。参数querystring必填——要搜索的内容行为细节src/worker.ts若本轮agent.run.started已缓存过召回结果state key 为recalled-memories工具直接返回缓存、不再发起网络请求只有缓存不存在时才进行实时召回兜底。这保证了一次召回、整轮复用的性价比。召回请求通过 src/client.ts 的recall()发送到POST /v1/default/banks/{bankId}/memories/recall请求体携带query、budget默认mid和max_tokens: 1024。hindsight_retain(content)—— 立即存储一个事实或决策不必等运行结束。参数contentstring必填——要存入记忆的内容行为细节src/worker.ts通过retain()发送到POST /v1/default/banks/{bankId}/memories请求体包含content与context: paperclip并携带agentId、companyId、runId元数据采用async: true异步写入见 src/client.ts。两个工具在计算 Bank ID 时都会读取agent.run.started阶段缓存的user-id当配置了用户粒度时确保同一运行内工具调用与自动召回/保留写入的是同一个银行src/worker.ts。六、工作原理插件生命周期全流程插件核心是一个基于paperclipai/plugin-sdk的 workersrc/worker.ts其事件驱动流程如下agent.run.started └─ fetch issue via ctx.issues.get └─ recall(issueTitle description) → cached in plugin state for the run agent running… ├─ hindsight_recall(query) → returns cached context or live recall └─ hindsight_retain(content) → stores immediately issue.comment.created └─ retain(full comment body via ctx.issues.listComments) └─ bank attribution: agent comment author when present; otherwise issue assignee agent.run.finished └─ no-op (subscription kept for future use when payload carries output)6.1 运行开始基于 issue 内容的自动召回agent.run.started处理器src/worker.ts的执行路径通过enabledAgentIds白名单过滤不在名单内的 Agent 直接跳过校验issueId与companyId是否齐全随后调用ctx.issues.get(issueId, companyId)获取 issue将issue.title与issue.description拼接成查询串若为空则跳过若配置了用户粒度从 issue 提取userId并缓存在运行级 stateuser-id推导 Bank ID调用client.recall(bankId, query, recallBudget)将召回结果格式化为 Markdown 列表缓存到运行级 staterecalled-memories供本轮后续使用。值得注意的容错设计召回失败不阻断Agent 运行注释明确说明 Non-fatal: agent runs without memory context仅记录warn日志。对应测试does not throw when Hindsight is unreachabletests/plugin.spec.ts验证了服务不可达时事件处理仍正常 resolve。6.2 评论创建完整正文的持久化issue.comment.created处理器src/worker.ts是记忆写入的主通道autoRetain为false时直接返回由于事件 payload 只携带 120 字符的bodySnippet截断片段插件调用ctx.issues.listComments(issueId, companyId)获取完整评论正文用commentId匹配到目标评论若listComments不可用则回退到 snippet源码注释说明了这一回退路径银行归属bank attribution评论由 Agent 作者撰写时归入该 Agent 的银行评论无 Agent 作者用户/系统评论时回退到 issue 的assigneeAgentId归属见 src/worker.ts再次经过enabledAgentIds过滤与归属校验无归属 Agent 则跳过并记录 info 日志推导 Bank ID以commentId作为document_id调用client.retain()并附带agentId、companyId、issueId、commentId元数据。测试retains the full comment body with the commentId as document ID与falls back to the issue assignee for bank attributiontests/plugin.spec.ts分别验证了正文写入与归属回退逻辑。6.3 运行结束当前为 no-opagent.run.finished目前是空操作src/worker.tsPaperclip 的运行生命周期 payload 只包含状态/耗时字段、不携带 Agent 输出因此记忆写入已全部改由issue.comment.created承担。订阅保留是为了让插件在事件订阅列表中保持可见并在未来 payload 携带输出引用时直接在此处接管。6.4 记忆的持久性关键记忆始终以companyIdagentId可选userId为键绑定到 Bank从不绑定 Paperclip 会话 ID 或运行 ID——这正是记忆能跨任意多次运行存活的原因。七、HTTP 客户端与请求细节插件通过零依赖的轻量 HTTP 客户端src/client.ts基于 Node 20 原生fetch与 Hindsight 通信baseUrl 处理构造时校验非空并去除末尾斜杠src/client.ts鉴权配置了hindsightApiKeyRef时通过ctx.secrets.resolve()解析出密钥以Authorization: Bearer token头发送src/worker.ts超时保护所有写操作请求带 15 秒 AbortController 超时health()探测带 5 秒超时src/client.ts端点召回POST /v1/default/banks/{bankId}/memories/recall保留POST /v1/default/banks/{bankId}/memoriesitems数组 async: true健康检查GET /health从 tests/plugin.spec.ts 可以看到 Bank ID 在 URL 中是经过encodeURIComponent编码的如paperclip::co-1::ag-1编码为paperclip%3A%3Aco-1%3A%3Aag-1因此包含::的 Bank ID 不会破坏 URL 结构。八、本地开发与调试插件是一个标准的 TypeScript ESM 包见 package.json要求 Node 20唯一运行时依赖是paperclipai/plugin-sdk。开发循环npm install npm run build npm testnpm run build通过 esbuild.config.mjs 将src/manifest.ts与src/worker.ts分别打包为dist/manifest.js和dist/worker.jspaperclipai/plugin-sdk被 external 化npm run dev进入 watch 模式npm test运行 Vitest 测试套件测试借助 SDK 的createTestHarness模拟 Paperclip 宿主环境并用全局 fetch mock 拦截 Hindsight API 调用无需真实启动 Paperclip 或 Hindsight见 tests/plugin.spec.ts。8.1 本地安装到运行中的 Paperclip 实例curl -X POST http://127.0.0.1:3100/api/plugins/install \ -H Content-Type: application/json \ -d {packageName:/absolute/path/to/hindsight-integrations/paperclip,isLocalPath:true}注意packageName需要替换为当前仓库中 hindsight-integrations/paperclip 的绝对路径。九、最佳实践与注意事项综合 README 与源码实现给出以下实践建议默认配置即可用大多数场景下保持默认dynamicBankId: truebankGranularity: [company, agent]每个公司的每个 Agent 自动拥有独立记忆互不干扰跨 Agent 共享知识需要团队级共享上下文时改bankGranularity: [company]或直接设置dynamicBankId: falsebankId后者同时兼容历史配置——见 tests/bank-edge-cases.spec.tsGDPR / 按用户隔离在bankGranularity中追加userBank ID 将带上::user::{userId}段同一 Agent 对不同用户的记忆相互隔离注意用户身份依赖 issue 的creatorEmail或originId如slack::aliceacme.com能够被解析到控制召回开销recallBudget三档可选low/mid/high对延迟敏感的场景用low默认mid是速度与深度的平衡点灰度试点用enabledAgentIds白名单只对少数 Agent 开启验证效果后再放开留空即全员启用想关掉自动记忆将autoRetain设为false但此时 Agent 仍可通过hindsight_retain工具主动存储失败不致命插件对 Hindsight 不可达、issue 获取失败等异常均做了降级处理记录 warn、Agent 继续运行不影响 Paperclip 主流程可放心接入。十、小结vectorize-io/hindsight-paperclip是 Hindsight 集成生态中面向 Paperclip 平台的记忆桥接插件运行前自动召回、评论后自动保留、运行中两个工具可主动读写配合灵活的 Bank 隔离粒度公司/Agent/用户/静态共享让 Paperclip Agent 从每次从零开始进化为越用越懂你。其完整实现worker、bank 推导、HTTP 客户端、manifest 与测试均可在当前仓库的 hindsight-integrations/paperclip 目录下直接查阅。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考