多仓库下 Codex 如何不再串台:Hindsight 记忆银行隔离完整指南
多仓库下 Codex 如何不再串台:Hindsight 记忆银行隔离完整指南【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight你在 API 仓库修查询超时,Codex 给出的方案却引用了前端仓库的 lint 约定。两个仓库共享不到十行代码,串台的根源在 Codex 记忆银行布局:所有仓库写进同一个codex银行,Hindsight 的 recall 只能在混杂的多仓库上下文里筛当前仓库的内容。本文讲 Hindsight 与 Codex 多仓库记忆隔离的布局策略——按仓库分库让每个项目的记忆独立、跨会话可召回,跨仓库规范放进一个共享库。这是一篇布局策略指南,不是安装教程;钩子安装与服务接入以官方 Codex 集成指南为准。布局总览每个仓库一个记忆银行,加一个跨仓库共享库,是多仓库场景下 Codex 记忆银行策略的最优解。层银行 ID 形态承载内容关键配置按仓库私有库codex::api(动态派生)仓库约定、脆弱区、排障史、工程决策dynamicBankId: true跨仓库共享库team-standards(固定)团队级 commit 约定、共享 CI、内部库bankId: team-standards生命周期触发点SessionStart/UserPromptSubmit/Stop预热 / 召回 / 保留hooks/hooks.json召回预算每轮注入的记忆量recallBudget: midrecallMaxTokens: 1024先看懂召回竞争,再明白为什么分库比调参根本召回精准度是一个竞争问题:预算有限时,候选记忆都来自当前仓库,答案自然干净。每次提问前,UserPromptSubmit钩子触发 recall,注入的记忆受recallMaxTokens(默认1024)约束,这就是你的召回预算。单银行下,无关仓库的记忆和当前仓库的记忆竞争同一份预算——前端仓库的 lint 约定因为最近写入且语义相近挤掉了 API 仓库的根因。按仓库分库把竞争在候选源头消灭:api仓库的 recall 只查codex::api,其他仓库的记忆物理上不在候选集里。调recallMinScores、recallBudget能过滤噪声,但分库决定噪声存不存在。Step 1:开启按仓库分库的最小配置多仓库的干净默认值是一个工作目录一个银行,两个配置键就能开启。{ dynamicBankId: true, dynamicBankGranularity: [agent, project] }写入~/.hindsight/codex.json。在~/projects/api和~/projects/frontend下运行 Codex,记忆分别落进codex::api与codex::frontend,存与召回都按仓库走,跨仓库零泄漏,也不需要手工给银行命名。Step 2:看清 retain/recall 在 Codex 钩子上的三个落点Codex 暴露的三个生命周期钩子,恰好覆盖记忆系统需要的预热、召回、保留。hooks/hooks.json 定义了全部三个钩子:钩子触发时机脚本动作超时SessionStart会话开始session_start.py校验服务可达性,后台预热 daemon5sUserPromptSubmit每次提问前recall.py召回记忆,以hindsight_memories包裹后经hookSpecificOutput.additionalContext注入45sStop每轮结束retain.py读 transcript,按retainMode写入银行30srecall.py 的链路是:读 stdin 钩子输入 → 派生银行 ID(L118) →recallContextTurns 1时拼多轮查询(L122-L132) → 按recallMaxQueryChars(默认800)截断 → 调 recall API → 格式化注入(L169-L175)。它始终以退出码 0 优雅降级,任何错误不打断对话。retain.py 读transcript_path下的会话记录,银行 ID 同样经derive_bank_id派生(L122)。Step 3:用固定 bankId 建立跨仓库团队共享库真正跨越仓库边界的知识放固定命名的银行,而不是动态银行。{ dynamicBankId: false, bankId: team-standards }指向同一bankId的银行,在所有指向它的 Hindsight 集成之间共享:一位队友的集成保留过的团队规范,其他指向同一共享库的集成也能召回。实用布局就是:日常开发走按仓库动态库,commit 约定、共享流水线、安全评审这类跨切标准放team-standards。银行 ID 的派生规则动态银行 ID 就是粒度字段值用::拼接,服务端原样存储,不做 URL 编码。派生逻辑在 scripts/lib/bank.py#L24-L65:模式银行 ID实例静态(dynamicBankId: false)bankId(缺省codex),配了bankIdPrefix则拼成前缀-bankIddev-codex动态(dynamicBankId: true)dynamicBankGranularity字段值用::连接,前缀拼在最前codex::api粒度字段的取值与兜底(bank.py#L54-L59):字段来源缺省值agent配置agentNamecodexproject工作目录基名unknownsession钩子输入session_idunknownuser环境变量HINDSIGHT_USER_IDanonymous边界行为都有测试背书(tests/test_bank.py):agentNamemybot、cwd 为/home/user/hindsight时派生出mybot::hindsight(L41-L45);含空格或 UTF-8 的目录名原样保留、不出现%编码(L47-L57);cwd 为空落unknown(L81-L84)。channel维度被刻意省略——Codex 是纯 CLI 工具,没有 Telegram/Discord 式多通道路由(bank.py#L9-L10)。配置加载顺序与环境变量切换四层配置后写覆盖前写,环境变量可以在不改文件的情况下切换分库。scripts/lib/config.py#L110-L140 定义的加载顺序:顺序来源说明1内置DEFAULTSconfig.py#L11-L582插件安装时写入的settings.json升级时会被覆盖,别在这里改3~/.hindsight/codex.json推荐修改点,升级不丢4环境变量ENV_OVERRIDES环境变量映射表在 config.py#L61-L83,常用的有HINDSIGHT_BANK_ID、HINDSIGHT_DYNAMIC_BANK_ID、HINDSIGHT_AGENT_NAME、HINDSIGHT_RECALL_TIMEOUT、HINDSIGHT_DEBUG。所以临时做分库实验可以直接HINDSIGHT_DYNAMIC_BANK_IDtrue codex,布尔值只认true/1/yes(config.py#L86-L95)。保留模式与文档 ID默认full-session模式整份 transcript 反复 upsert 同一文档,最终库里就是这个会话的完整形态。retainMode行为文档 IDfull-session(默认)整份会话 transcript 保留session_id(retain.py#L125-L130)chunked按用户轮边界切最近retainEveryNTurns retainOverlapTurns的窗口(retain.py#L81-L84)session_id 毫秒时间戳两种模式都受retainEveryNTurns门控(默认10,见 settings.json#L30):每 N 轮才真正触发一次 retain(retain.py#L73-L79)。所以会话中途查不到不是 bug,是节奏没到——验证时把retainEveryNTurns临时调成1。用什么标准判断该沉淀什么别问要保留什么,问这条信息是否命中下面的判断句——默认整会话 retain,这些判断决定的是什么是好会话。四个可复用的判断问句:这条信息每个新会话都要重新解释一遍吗?——是,就是仓库约定(本项目 FastAPI asyncpg,不用 SQLAlchemy;lint 走ruff check)。这个模块会以出人意料的方式坏掉吗?——是,就是内有恶龙的备注(部署前必须先跑的迁移、带超时毛病的端点)。这个 bug 的根因,下一个人不查半天猜得出来吗?——猜不出来,就值得留下(auth服务 401 是时钟偏移导致的,已用 X 修复)。这个选型从 diff 里反推代价高吗?——高,就是该沉淀的工程决策(为什么换重试策略、为什么选这个库)。反例:我刚才跑了npm run dev,端口被占用,临时改到 3001——一次性操作,下次会话再问就是过期信息,让它占召回预算是纯亏。验收 checklist隔离是否生效,看记忆有没有留在它来源的仓库里,五条即可:✅ 仓库 A 会话结束(或每 N 轮)后,同仓库新会话能召回刚沉淀的决策✅ 仓库 B 里问同样的问题,不出现仓库 A 的答案✅ 同一仓库两次运行派生出相同银行 ID(如codex::api)✅debug: true时 stderr 出现Recalling from bank codex::api(recall.py#L144)✅ 指向team-standards的各集成都能召回共享库里的约定排错:症状、根因、修复对照多数排障归结为一件事:两次运行没有落在同一个银行 ID 上。症状根因修复recall 冒出别的仓库的内容dynamicBankId未开启,全写进默认codex银行~/.hindsight/codex.json设dynamicBankId: true同仓库第二次会话召回落空两次运行派生出不同银行 ID(cwd 不同或agentName被改)核对两次 cwd 基名一致;agentName保持稳定会话中途测召回,结果为空full-session整会话保留,且retainEveryNTurns默认10跳过多数轮次临时retainEveryNTurns: 1,或结束会话再验证环境变量开关不生效布尔值不合法(_cast_env只认true/1/yes)用HINDSIGHT_DYNAMIC_BANK_IDtrue,或直接写配置文件两次运行落在不同银行HINDSIGHT_AGENT_NAME在一次运行中被设置、另一次没有统一从配置文件提供agentName三个反模式以下三种布局,出现任何一条就该调整:全部塞进单个codex银行——写入的仓库越多,召回要过滤的噪声越多。团队约定只存在按仓库银行里——跨切标准只在一个仓库有效,等于没沉淀。期望仓库 A 召回仓库 B 的上下文——银行隔离是严格的,隔离本身就是特性。FAQ三个高频问题,直接给结论。我怎么确认某次钩子运行实际命中的是哪个银行?开debug: true(或HINDSIGHT_DEBUGtrue),stderr 会打印Recalling from bank bank_id;每次 recall 还会把bank_id与结果数写进last_recall.json(recall.py#L177-L185)。动态分库会不会让银行数量失控?agent::project的银行数只随工作目录数量增长,不随会话数增长。只有把session加进dynamicBankGranularity才会一会话一库——那是场景隔离手段,不是日常布局。能用 bankIdPrefix 区分测试与生产环境吗能。静态模式下拼成dev-codex(test_bank.py#L32-L38),动态模式下拼在拼接结果前,如v2-codex::api(test_bank.py#L64-L67),派生逻辑见 bank.py#L30-L34 与 bank.py#L65。资源索引按阅读顺序,从安装到机制到 API:安装指南(钩子包、服务接入):hindsight-docs/guides/2026-05-04-guide-codex-memory-with-hindsight.md完整配置表与默认值:hindsight-integrations/codex/README.md银行 ID 派生源码与测试:scripts/lib/bank.py、tests/test_bank.py配置加载与默认值:scripts/lib/config.py、settings.json钩子入口与生命周期定义:recall.py、retain.py、hooks.jsonrecall / retain / memory-banks API 文档:recall.mdx、retain.mdx、memory-banks.mdx自托管快速开始(pip install hindsight-api或 Docker):quickstart.mdx【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考