记忆与预算

Codex 仓库里有两类容易被忽略的后台机制:memories 和 rollout budget。前者把历史工作提炼成可复用记忆,后者给同一个 root-thread session tree 施加共享 token 预算。它们共同体现了一个设计方向:agent 不只要会执行当前 turn,还要能管理长期上下文和成本边界。

Memory And Budget

Memories 总览

memory 写路径在 codex-rs/memories/write,读路径在 codex-rs/memories/read。两者刻意拆成不同 crate:读路径负责注入、引用解析和 telemetry 分类;写路径负责 startup pipeline、文件 artifact、两阶段 prompt 和 workspace diff。

memory 根目录是:

${CODEX_HOME}/memories

主要 artifact:

文件/目录 作用
raw_memories.md Phase 1 raw memory 的合并视图
rollout_summaries/ 每个 rollout 的摘要文件
extensions/ memory extension 的 source-specific instructions
phase2_workspace_diff.md Phase 2 consolidation agent 的只读 diff 输入

Startup pipeline

start_memories_startup_task 只在符合条件的 root session 启动:

跳过条件 原因
config.ephemeral 临时会话不应产生长期记忆
MemoryTool feature disabled 功能开关关闭
source.is_non_root_agent() sub-agent 不递归生成记忆
state DB 不可用 无法 claim job 或记录状态

启动后顺序是:

  1. 创建 memory root。
  2. seed extension instructions。
  3. prune 过期且未使用的 Phase 1 输出。
  4. 检查 Codex backend rate limit,剩余额度不足则跳过。
  5. 运行 Phase 1 抽取。
  6. 运行 Phase 2 合并。

rate limit guard 使用 backend 返回的 primary/secondary window,只有使用量低于配置阈值时才允许启动后台记忆任务。这避免了“用户正在交互时后台任务抢额度”。

Phase 1:按 rollout 抽取 raw memory

Phase 1 的输入是历史 rollout。它会从 state DB claim eligible jobs:

参数 来源
scan limit THREAD_SCAN_LIMIT = 5_000
startup 最大 claim 数 config.memories.max_rollouts_per_startup
rollout 最大年龄 config.memories.max_rollout_age_days
最小 idle 小时 config.memories.min_rollout_idle_hours
allowed sources interactive session sources
lease JOB_LEASE_SECONDS = 3_600

抽取任务用 buffer_unordered(CONCURRENCY_LIMIT) 并发执行,当前并发上限是 8。每个 job 会:

  1. 读取 rollout JSONL。
  2. 过滤可持久化的 response item。
  3. 构造 stage-one prompt。
  4. 要求模型返回严格 JSON:
字段 含义
raw_memory 详细 markdown 记忆
rollout_summary 用于路由和索引的摘要
rollout_slug 可选,用于摘要文件名

输出会经过 redact_secrets,再写入 state DB。

Phase 2:受限 agent 合并 memory workspace

Phase 2 是全局锁保护的 consolidation。它先 claim global phase-2 job,再准备 memory workspace。workspace 是一个 git baseline repository,Codex 用 git diff 判断本次同步是否真的改变了输入。

Phase 2 的关键步骤:

  1. claim global lock。
  2. prepare_memory_workspace 初始化或复用 .git baseline,并删除旧 diff artifact。
  3. 构造 consolidation agent config。
  4. 从 DB 选择 Phase 2 输入。
  5. 同步 raw_memories.mdrollout_summaries/
  6. 用 git diff 判断 workspace 是否变化。
  7. 写入有界 phase2_workspace_diff.md,上限 4 MiB
  8. spawn internal consolidation agent。
  9. heartbeat global lock,等待 agent final status。
  10. 成功后 reset git baseline,并把 job 标记为 succeeded。

consolidation agent 的 config 被刻意锁死:

配置 值/策略
cwd memory root
ephemeral true
generate_memories/use_memories false
MCP servers 空集合
approval policy Never
disabled features spawn/collab/memory/apps/plugins/skill dependency install
sandbox workspace-write,仅 memory root 可写,network disabled
reasoning effort medium

这说明 Codex 把后台智能任务当成“内部 worker”,仍然套完整的权限、sandbox、feature 和 heartbeat 管理,而不是直接给它文件系统自由写入。

Memory citation 与使用统计

读路径提供两类能力:

  1. parse_memory_citation 解析 <citation_entries><rollout_ids> 或兼容的 <thread_ids>
  2. memories_usage_kinds_from_command 通过 shell parser 判断命令是否安全读了 memory 文件,并分类 telemetry。

可分类的 memory 使用:

kind 识别路径
MemoryMd memories/MEMORY.md
MemorySummary memories/memory_summary.md
RawMemories memories/raw_memories.md
RolloutSummaries memories/rollout_summaries/
Skills memories/skills/

注意它只统计 known safe command 中的 read/search/list 行为,避免把任意 shell 字符串当成可靠信号。

Rollout Budget

rollout budget 在 codex-rs/core/src/rollout_budget.rs。它是 root-thread session tree 共享的账本,不是单 turn 计数器。

每次模型返回 token usage,Codex 会调用:

weighted_tokens_used += output_tokens * sampling_token_weight
    + non_cached_input_tokens * prefill_token_weight

如果超过 limit_tokensSession::record_rollout_budget_usage 返回 TurnAborted,当前 turn 被中止。

预算提醒

预算提醒不是 UI toast,而是写入会话历史的 developer contextual fragment:

<rollout_budget>
You have N weighted tokens left in the shared session token budget.
</rollout_budget>

pending_reminder(thread_id, window_id) 会根据 reminder_interval_tokens 计算当前 reminder index,并用 (thread_id, window_id) 去重。只有在 history insertion 成功后才调用 mark_reminder_delivered,如果取消发生在插入前,下次还会重试。

rearm_reminder(thread_id) 可以强制某个 thread 下次采样时重新声明剩余额度。

可学习的设计点

  1. memories 用 DB job lease + git baseline workspace + sandboxed internal agent,把长期记忆生成拆成可恢复流水线。
  2. Phase 1 和 Phase 2 使用不同模型、reasoning effort 和并发策略,避免“一次性大 prompt”。
  3. memory consolidation 禁用递归 memory、插件、MCP、网络和 delegation,防止后台任务失控。
  4. rollout budget 把成本约束转成 developer context,让模型在接近预算时主动收敛。
  5. 预算按 non-cached input 和 output 加权,比简单 total token 更贴近真实成本。

关键源码

主题 文件
memory write root codex-rs/memories/write/src/lib.rs
startup pipeline codex-rs/memories/write/src/start.rs
Phase 1 codex-rs/memories/write/src/phase1.rs
Phase 2 codex-rs/memories/write/src/phase2.rs
memory workspace codex-rs/memories/write/src/workspace.rs
memory storage artifacts codex-rs/memories/write/src/storage.rs
memory read usage/citation codex-rs/memories/read/src/usage.rscitations.rs
rollout budget codex-rs/core/src/rollout_budget.rs
budget context codex-rs/core/src/context/rollout_budget.rs