Hindsight × OMO 集成实战:为 oh-my-openagent 智能体接入长期记忆与自动召回
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
本指南围绕 hindsight-integrations/omo/README.md 展开,系统讲解如何将 Hindsight 长期记忆能力接入 OMO(oh-my-openagent)智能体编排器:在每次用户提问前自动召回历史相关记忆注入上下文,在会话结束后自动提取并留存新的经验。读完本文,你将掌握完整的安装配置步骤、五大 Hook 的生命周期机制、全部配置项与优先级规则,以及 recall / retain 底层实现原理,可直接照搬到自己的 OMO 工作流中。
OMO 集成是什么
OMO(oh-my-openagent)是一个智能体编排器,而 Hindsight 是提供长期记忆能力的记忆服务。二者结合后,智能体不再"每次会话都从零开始":Hindsight 会自动在每次提示词(prompt)之前召回过往会话中的相关知识,并在会话结束后把本次学到的内容沉淀下来,供未来使用。
该集成的完整代码位于仓库的 hindsight-integrations/omo/ 目录,包含五个 Hook 脚本、项目规则文件、默认配置与测试用例,属于本仓库hindsight-integrations生态中面向 OMO 用户的官方接入方案。
快速上手:四步完成接入
第一步:获取 API Key
注册 Hindsight 云服务并创建 API Key(形如hsk_...)。自托管部署时则无需 API Key,只需指向本地服务地址。
第二步:安装集成文件
从仓库的hindsight-integrations/omo/目录执行以下复制命令,将 hooks、脚本、设置与规则分发到对应位置:
# Hooks(全局) mkdir -p ~/.omo/hooks cp hooks/hooks.json ~/.omo/hooks/hindsight-hooks.json # 脚本 + 设置(全局) mkdir -p ~/.omo/plugins/hindsight/scripts cp -r scripts/ ~/.omo/plugins/hindsight/scripts/ cp settings.json ~/.omo/plugins/hindsight/settings.json # 规则(按项目——在项目根目录执行) mkdir -p /path/to/your/project/.omo/rules cp rules/hindsight-memory.md /path/to/your/project/.omo/rules/hindsight-memory.md对应文件在仓库中的位置分别是 hooks/hooks.json、scripts/、settings.json 与 rules/hindsight-memory.md。
第三步:设置 API Key
通过环境变量设置:
export HINDSIGHT_API_TOKEN=hsk_your_key_here或持久化写入用户配置文件~/.hindsight/omo.json:
{ "hindsightApiToken": "hsk_your_key_here" }第四步:允许 OMO 透传环境变量
在 OMO 的配置文件~/.config/opencode/oh-my-openagent.jsonc中,将集成需要的三个环境变量加入mcp_env_allowlist:
{ "mcp_env_allowlist": [ "HINDSIGHT_API_URL", "HINDSIGHT_API_TOKEN", "HINDSIGHT_BANK_ID" ] }完成以上四步后启动 OMO,记忆功能即自动生效,无需任何额外手动操作。
Hook 生命周期:记忆如何自动流动
OMO 通过生命周期钩子(Hook)与 Hindsight 交互,核心事件与动作对应关系如下表:
| Hook 事件 | 触发时机 | 执行动作 |
|---|---|---|
SessionStart | 会话开始 | 健康检查;若缺少 API Key 则发出警告 |
UserPromptSubmit | 每次用户提示词提交前 | 向 Hindsight 查询相关记忆;以additionalContext注入上下文 |
Stop | 智能体完成回复 | 提取会话转录文本;发送给 Hindsight 做事实提取 |
SubagentStop | 子智能体完成 | 与Stop相同——捕获子智能体的学习成果 |
SessionEnd | 会话终止 | 对短会话强制执行最后一次 retain |
整体的架构流程如下:
OMO (orchestrator) ├── SessionStart hook → health check ├── UserPromptSubmit hook → recall memories → inject as additionalContext ├── Stop hook → retain session transcript (async) ├── SubagentStop hook → retain sub-agent findings (async) └── SessionEnd hook → force final retain在 hooks/hooks.json 中可以确认每个 Hook 的完整声明:SessionStart与UserPromptSubmit是同步命令(超时分别为 5 秒与 45 秒),Stop与SubagentStop声明为"async": true异步执行(超时 15 秒),避免 retain 阻塞主流程;SessionEnd超时 10 秒。所有命令都采用python3 ... || python ...的双解释器回退写法,兼容不同系统环境。
关键设计:优雅降级。所有 Hook 在任何出错场景下都"静默失败"——从源码看,recall.py 与 retain.py 的退出码恒为 0(仅在debug模式下对异常返回 2)。因此即使 Hindsight 服务不可达,OMO 也会照常工作,只是暂时失去记忆能力。
配置体系详解
配置加载优先级
设置按以下顺序加载,后者覆盖前者("later wins"):
settings.json(插件默认值——内置云端 URL)~/.hindsight/omo.json(用户覆盖)HINDSIGHT_*环境变量
这一逻辑在 scripts/lib/config.py 的load_config()中有完整实现:先以DEFAULTS字典为底,依次合并插件目录下的settings.json与~/.hindsight/omo.json(合并时跳过值为null的键),最后遍历ENV_OVERRIDES映射表覆盖环境变量;布尔值与整数环境变量还会经过类型转换(布尔接受true/1/yes)。
关键设置一览
| 设置项 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
hindsightApiUrl | HINDSIGHT_API_URL | https://api.hindsight.vectorize.io | API 端点 |
hindsightApiToken | HINDSIGHT_API_TOKEN | — | API Key(hsk_...),云端必需 |
bankId | HINDSIGHT_BANK_ID | omo | 记忆库(bank)名称 |
autoRecall | HINDSIGHT_AUTO_RECALL | true | 提示词前自动召回 |
autoRetain | HINDSIGHT_AUTO_RETAIN | true | 回复后自动留存 |
retainEveryNTurns | — | 10 | 留存频率(按轮次) |
recallBudget | HINDSIGHT_RECALL_BUDGET | mid | 召回深度(low/mid/high) |
dynamicBankId | HINDSIGHT_DYNAMIC_BANK_ID | false | 按项目隔离记忆库 |
debug | HINDSIGHT_DEBUG | false | 向 stderr 输出调试日志 |
完整默认配置(settings.json)
插件自带的 settings.json 是理解全部能力的最佳入口,除上述核心项外还包含以下精细控制:
{ "version": "0.1.0", "hindsightApiUrl": "https://api.hindsight.vectorize.io", "hindsightApiToken": null, "bankId": "omo", "bankMission": "You are an OMO (oh-my-openagent) orchestrator. Focus on technical discussions, decisions, architectural context, and coding patterns relevant to the user's projects.", "retainMission": "Extract technical decisions, architectural choices, user preferences, project context, debugging insights, and tool/library relationships. Ignore routine greetings and transient operational details.", "autoRecall": true, "autoRetain": true, "retainMode": "full-session", "recallBudget": "mid", "recallMaxTokens": 1024, "recallTypes": ["world", "experience"], "recallContextTurns": 1, "recallMaxQueryChars": 800, "recallRoles": ["user", "assistant"], "recallPromptPreamble": "Relevant memories from past conversations (prioritize recent when conflicting). Only use memories that are directly useful to continue this conversation; ignore the rest:", "retainRoles": ["user", "assistant"], "retainEveryNTurns": 10, "retainOverlapTurns": 2, "retainToolCalls": false, "retainTags": ["{session_id}"], "retainMetadata": {}, "retainContext": "omo", "recallAdditionalBanks": [], "bankIdPrefix": "", "dynamicBankId": false, "dynamicBankGranularity": ["agent", "project"], "resolveWorktrees": true, "directoryBankMap": {}, "requestTimeoutSeconds": null, "debug": false }各参数含义说明:
bankMission/retainMission:描述智能体的身份使命与留存提取准则,首次使用某个 bank 时会通过 API 写入服务端(见下文ensure_bank_mission)。retainMode:full-session(整段会话全部留存)或chunked(按retainEveryNTurns + retainOverlapTurns轮窗口分块留存,避免超长会话一次提交过大)。recallMaxTokens:单次召回返回的最大 token 数;recallTypes:限定召回的记忆类型(world世界知识 /experience经验);recallContextTurns:大于 1 时结合转录文本构造多轮召回查询;recallMaxQueryChars:查询文本最大字符数;recallRoles:参与构造查询的角色。recallPromptPreamble:注入到additionalContext中的提示前缀,指导智能体"只使用对当前对话直接有用的记忆"。retainRoles/retainToolCalls:控制转录中纳入哪些角色消息、是否包含工具调用记录。retainTags:支持{session_id}、{bank_id}、{timestamp}、{user_id}模板变量,代码中会先做模板解析再写入。retainContext:随记忆一起存储的上下文标签,默认omo。requestTimeoutSeconds:全局请求超时覆盖值,null时使用客户端各自的默认超时(recall 10s、retain 15s、健康检查 5s)。resolveWorktrees:为true时在 git worktree 环境下解析到主仓库名,使同一仓库的多个 worktree 共享同一记忆库(实现见 scripts/lib/bank.py 的_resolve_project_name)。directoryBankMap:显式的"目录 → bank"映射,优先级最高的静态路由。
环境变量完整映射
除 README 列出的项外,scripts/lib/config.py 中的ENV_OVERRIDES还支持更多变量,完整清单如下:
| 环境变量 | 对应配置项 | 类型 |
|---|---|---|
HINDSIGHT_API_URL | hindsightApiUrl | string |
HINDSIGHT_API_TOKEN | hindsightApiToken | string |
HINDSIGHT_BANK_ID | bankId | string |
HINDSIGHT_AGENT_NAME | agentName | string |
HINDSIGHT_AUTO_RECALL | autoRecall | bool |
HINDSIGHT_AUTO_RETAIN | autoRetain | bool |
HINDSIGHT_RETAIN_MODE | retainMode | string |
HINDSIGHT_RECALL_BUDGET | recallBudget | string |
HINDSIGHT_RECALL_MAX_TOKENS | recallMaxTokens | int |
HINDSIGHT_RECALL_MAX_QUERY_CHARS | recallMaxQueryChars | int |
HINDSIGHT_RECALL_CONTEXT_TURNS | recallContextTurns | int |
HINDSIGHT_REQUEST_TIMEOUT_SECONDS | requestTimeoutSeconds | int |
HINDSIGHT_DYNAMIC_BANK_ID | dynamicBankId | bool |
HINDSIGHT_BANK_MISSION | bankMission | string |
HINDSIGHT_DEBUG | debug | bool |
进阶配置:记忆隔离与多库召回
Dynamic Bank IDs:按项目隔离记忆
默认所有会话共享一个omo记忆库。开启动态 bank 后可按项目隔离:
{ "dynamicBankId": true, "dynamicBankGranularity": ["agent", "project"] }此时会生成形如omo::myproject、omo::other-repo的独立记忆库。granularity 支持的可选字段在 scripts/lib/bank.py 中定义为agent、project、session、channel、user,对应取值分别来自配置的agentName(默认omo)、工作目录解析出的项目名、会话 ID 及HINDSIGHT_CHANNEL_ID/HINDSIGHT_USER_ID环境变量,多个字段以::拼接。还可以用bankIdPrefix为所有 bank 名统一加前缀。
Multi-Bank Recall:跨库召回
除了主 bank,还可以同时查询附加 bank,实现团队级共享知识:
{ "recallAdditionalBanks": ["shared-team-knowledge"] }从 recall.py 的实现可以看到,插件会先查询主 bank,再依次查询每个附加 bank,将全部结果合并后统一注入上下文;单个附加库失败不会影响主库召回。
项目规则:让智能体知道如何用记忆
安装时复制到项目.omo/rules/hindsight-memory.md的规则文件(仓库位置 rules/hindsight-memory.md)为智能体定义了三条使用准则:
- 何时 recall:处理非平凡任务前,从用户请求提取 3~5 个关键术语,搜索历史解决方案、调试洞见或架构决策;琐碎任务(错别字、简单问答)不召回。
- 何时 retain:完成可能复现的问题解决方案、关键架构决策及理由、用户工作流/编码风格/工具偏好、来之不易的调试洞见;不存储琐碎改动、已被 git 跟踪的应用代码、以及 API Key 等敏感数据。
- 何时 reflect:当用户要求跨主题综合、或需要跨多条记忆推理模式时使用
reflect工具。
该文件通过 front-matter 的alwaysApply: true随会话自动注入。
自托管部署(可选)
不使用云端时,通过环境变量覆盖 API 地址即可指向本地实例:
export HINDSIGHT_API_URL=http://localhost:8888或在~/.hindsight/omo.json中指定:
{ "hindsightApiUrl": "http://localhost:8888", "hindsightApiToken": null }本地实例无需 API Token。从 recall.py 与 retain.py 的源码可见一个细节:当 API URL 包含云端域名api.hindsight.vectorize.io且未配置 token 时,插件会静默跳过请求;而指向本地地址时无 token 也可正常调用。
底层原理:一次 recall 与 retain 的完整旅程
纯标准库的 REST 客户端
scripts/lib/client.py 中的HindsightClient仅依赖 Python 标准库(urllib),零外部依赖。它负责三个核心 REST 调用:
health_check:GET /health,用于SessionStart时探测服务可用性;recall:POST /v1/default/banks/{bank_id}/memories/recall,携带query、max_tokens、budget、types参数;retain:POST /v1/default/banks/{bank_id}/memories,以{"items": [...]}形式提交内容,并带"async": true让服务端异步执行事实提取,document_id默认conversation;set_bank_mission:PATCH /v1/default/banks/{bank_id}/config,写入reflect_mission与retain_mission。
客户端还会校验 API URL 必须为http/https协议且包含主机名,Token 通过Authorization: Bearer ...头传递。
Recall 流程(UserPromptSubmit)
load_config()读取合并后的配置;若autoRecall为 false 则直接退出。- 从 stdin 读取 Hook 输入(
prompt、session_id、cwd、可选的transcript_path);提示词过短(<5 字符)则跳过。 derive_bank_id()推导目标 bank,ensure_bank_mission()在首次使用时写入 bank 使命(已设置过的 bank 记录在本地状态文件,避免重复写入,且状态文件超过 10000 条时自动清理一半)。- 当
recallContextTurns > 1时,读取 JSONL 转录文本并组合成多轮查询;查询超长时按recallMaxQueryChars截断。 - 调用
client.recall()获取结果,并合并所有recallAdditionalBanks的召回结果。 - 若无结果则静默返回;否则将记忆格式化为
<hindsight_memories>...</hindsight_memories>块(含前缀、当前时间戳),写入last_recall.json状态,最后向 stdout 输出hookSpecificOutput.additionalContext,OMO 会把它作为额外上下文注入给模型。
Retain 流程(Stop / SubagentStop / SessionEnd)
- 若
autoRetain关闭则退出;SessionEnd场景通过force=True强制执行一次。 - 读取会话转录(JSONL,兼容 OMO 的
{"type": "user|assistant", "message": {...}}与扁平{"role": ..., "content": ...}两种格式)。 - 频率控制:
retainEveryNTurns > 1时通过increment_turn_count()计数(基于文件锁fcntl.flock保证并发安全),未到指定轮次则跳过。 - 按
retainMode选取留存窗口:chunked模式截取最近retainEveryNTurns + retainOverlapTurns轮;随后按retainRoles过滤角色、可选包含工具调用,组装成转录文本。 - 生成
document_id:全量模式为session_id(发生"压缩"即转录变短时自动推进到session_id-cN分块编号,保护既有文档不被覆盖);chunked模式为session_id-毫秒时间戳。 - 解析
retainTags模板变量、组装retained_at/message_count/session_id元数据,调用client.retain()异步提交给服务端做事实提取与存储。
文件式状态持久化
scripts/lib/state.py 说明了一个重要的实现约束:OMO 的 Hook 是一次性临时进程,状态必须落到磁盘。所有状态(轮次计数、留存追踪、已设置 mission 的 bank 列表、最近一次召回)都存放在PLUGIN_DATA/state/(或~/.hindsight/omo/state/)目录下,采用临时文件 +os.replace的原子写入,并对文件名做了路径穿越防护。
测试与演示
仓库为该集成提供了完整的验证手段:
运行单元测试:
cd hindsight-integrations/omo pip install pytest python -m pytest tests/ -v测试用例位于 hindsight-integrations/omo/tests/(test_bank.py、test_config.py、test_hooks.py),覆盖 bank ID 推导、配置合并、Hook 行为等核心逻辑。
运行交互式演示:demo.py 可以针对本地 Hindsight 开发服务器完整模拟 Hook 生命周期(SessionStart → UserPromptSubmit(recall) → Stop(retain) → SessionEnd),包括健康检查、首次召回(应为空)、留存两段对话、等待异步事实提取后再次召回(应能命中刚学到的记忆):
# 先启动 Hindsight 开发服务器: ./scripts/dev/start-api.sh HINDSIGHT_API_URL=http://localhost:8888 python demo.py演示默认使用omo-demobank,同一 bank 的记忆跨多次运行持久保留——再次运行即可看到历史召回结果。
小结
Hindsight × OMO 集成通过五个生命周期 Hook 把"记忆"无缝织入智能体的日常会话:UserPromptSubmit前自动召回、Stop/SubagentStop后自动留存、SessionEnd兜底收尾,全部失败静默降级,不干扰原有工作流。配合动态 bank 隔离、多库召回、轮次频率控制与按项目注入的规则文件,开发者可以用极低的心智成本,为 OMO 智能体构建一套可持续积累、跨会话复用的长期记忆系统。需要深入自定义时,可直接阅读 scripts/ 下的各模块源码与 tests/ 测试用例。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考