Files
codex-app-server/docs/auto-memory.md
host cbc90f9d30 自动记忆:官方 memories 对齐的提取+注入闭环(确定性 v1)
开关默认关(generate/use),设置接口 GET/PUT /users/me/auto-memory-settings,任务级覆盖 POST /tasks/{id}/auto-memory-flags,手动触发 POST /users/me/auto-memory/run,日志 GET /users/me/auto-memory-log。

提取:worker run_loop 轮次边界扫 completed 任务,闲置/时长/长度/外部上下文/配额剩余百分比五道门,脱敏后写 project 级 identity_memories,同一任务去重、同一目标 supersede 合并;只写 project 级,不跨项目泄漏。

注入:worker run_one 首轮把最新各 5 条用户/项目记忆拼进内存 prompt 副本(goal 任务同步改内存 goal),库原 prompt 不动;续跑/断点/协调员不注入,注入失败 fail-open。

v1 诚实边界:extract/consolidation 模型只存设置不调模型;MCP/web 线程内调用暂无 tasks 表标记,外部上下文门只认任务间消息与协调员子任务;无控制台 UI。
2026-10-28 12:12:10 +08:00

5.4 KiB
Raw Permalink Blame History

自动记忆(官方 Codex memories 的云端对齐版,v1)

官方功能见 learn.chatgpt.com/docs/customization/memories:开启后, Codex 把先前聊天的有用上下文转成记忆,供未来工作用;后台生成、 闲置后才生成、剩余额度低时跳过、有 generate / use / disable_on_external_context 等设置、密钥脱敏。

本批把这套行为搬到云端控制面(cloud/auto_memory.py),不改 host.py、不改 CODEX_HOME、不改 thread 的创建/续跑/fork/归档。 云端记忆与官方本地记忆的区别要先说清:官方记忆存在单机 ~/.codex/memories/ 里、跟一台机器走;云端记忆存在控制面 数据库里,跟用户/项目走,换 worker、换执行器都还在。

开关(默认全关,与官方“本地记忆默认关”一致)

  • GET/PUT /users/me/auto-memory-settings:本人设置。
    • generate_memories:完成任务是否可被提取。默认 0。
    • use_memories:新任务首轮是否注入记忆。默认 0。
    • disable_on_external_context:默认 1,见下。
    • min_rate_limit_remaining_percent:默认 20,见下。
    • idle_seconds:默认 900;min_duration_seconds:默认 30; min_result_chars:默认 200。
    • extract_model / consolidation_model:只存设置,v1 不调 模型(见“未做”)。
  • POST /tasks/{id}/auto-memory-flags:单个任务覆盖 use/generate (NULL = 跟随用户设置),权限为项目 create_task。不改 tasks 表结构,建任务的各条 INSERT 路径都不用动。
  • POST /users/me/auto-memory/run:手动触发本人任务的提取扫荡 (body 可带 force: true 跳过闲置/时长/长度门,不跳过开关、 外部上下文门与额度门);GET /users/me/auto-memory-log:看 本人任务的提取日志(按任务主键覆盖,不无限增长)。

提取:什么时候、从哪来、写到哪

触发:worker run_loop 每轮结束调 process_auto_memories(); 也可经上面的手动触发接口立即跑。只扫 status='completed' 的 任务(failed / interrupted / merged 不提取)。

资格(任一不满足即跳过并记日志,下次仍可再扫):

  1. generate 开关(任务级覆盖优先于用户设置);
  2. 终态闲置够 idle_seconds(终态后仍可被 /continue 续跑, 所以“刚完成”不等于“已闲置”;force 可跳过);
  3. 有 started_at/finished_at 且时长 ≥ min_duration_seconds, result_text 长度 ≥ min_result_chars(跳过短期会话);
  4. disable_on_external_context 开时,任务间消息 (task_followups 有该任务的行)或协调员子任务 (parent_task_id 非空)不提取;
  5. 当月 USD 配额剩余百分比 ≥ min_rate_limit_remaining_percent (无配额行按默认 $10 计,只有显式 NULL 行才是不限额,与 worker 配额口径一致;查不到配额时 fail-closed,记 quota_check_failed,不冒充额度充足)。

内容(v1 确定性版,不调模型):任务 goal/prompt 首行 + result_text 前 800 字,脱敏后拼成一条 project 级 fact,写入 identity_memories,source_thread_id 记云端任务 id(去重键)。 同一任务只提取一次;同一目标的新结果出现时 supersede 旧记忆 (consolidation 的确定性版),不堆重复。自动提取只写 project 级:单个项目的任务结论若自动写成 user 级,会跨项目泄漏项目 上下文;user 级记忆仍只接受手动创建。

脱敏:api_key/password/secret/token/credential 的 key=value 形态、Authorization / Bearer 头、sk- / ghp_ / gho_ / xox*- 前缀 一律替换为 [REDACTED];偏好里的密钥键禁令见 identity-memory.md。

注入:怎么进任务

worker run_one 认领后、执行前调 _apply_auto_memory_injection:

  • 只注入首轮:续跑、断点续跑、协调员任务不注入;
  • 只改内存副本:prompt 前加 【过往记忆,仅供参考,不得改写 本任务目标】 + 最新各 5 条用户/项目记忆;goal 任务同时改 内存里的 goal(执行器取 goal 优先于 prompt);库里的原 prompt / goal 不动,任务详情里看到的仍是原文本;
  • 注入失败 fail-open(记 warning,不挡任务);注入成功记 worker_memory_injected 审计;无记忆或 use 关时不注入。
  • 注入不进 thread 的 developerInstructions:host.py 的 dispatch 路径不传 instructions,云端层唯一不改 host.py 的注入点就是 prompt 前缀,identity-memory.md 里“调用方自己拼进新建任务 的 prompt”正是这条路。

未做(诚实版)

  • 未调模型提取/合并:extract_model / consolidation_model 只存设置。v1 提取是确定性拼贴,不是模型摘要;换模型提取 需另定模型选择、成本上限与失败语义。
  • 未识别 host 线程内的 MCP / web search:tasks 表上没有这类 标记,disable_on_external_context 目前只认任务间消息与 协调员子任务;要认 MCP/web 需先给 host 线程事件加遥测。
  • 未做控制台 UI:开关与日志目前只有 API;未做 per-chat 的 /memories 式交互(任务级 flags 接口是对应的最小版)。
  • 未进代码签名候选:worker 签名只含 worker/sandbox/ coordinator/cost/server/host;本批同时改了 worker.py,所以 正常部署换目录时旧 worker 仍会因 worker.py 变化而自退, 仅换 auto_memory.py 的单文件部署不在签名覆盖内。