3-3 Ralph 模式与 Context Reset
核心洞察:长 Session 会系统性降级
先把问题说清楚,再说解法。
一个 agent session 跑得越长,context window 里积累的东西就越多:
- 早期尝试过但放弃的方向
- 被推翻的中间结论
- 重复的错误信息
- 已经不再相关的文件内容
模型没有能力主动忘掉这些内容。它会平等地"读"进去,结果是旧的死路干扰新的判断,模型开始兜圈子、重复犯同样的错、或者给出越来越保守的操作。
这不是模型能力的问题,是 context 结构的问题。一个填满了旧推理的 window,比一个干净的 window 更难用。
1-1 讲 context rot 时提到了这个现象,Ralph 模式是对它的直接工程回应。
Ralph 的解法
Ralph 模式的核心思路只有一句话:
每次迭代都是全新 agent,状态活在磁盘,不活在对话。
具体来说,每个 tick 的流程是:
启动全新 agent session
↓
从磁盘读当前仓库状态(代码、错误日志、任务描述)
↓
做一个工作单元(修一个 bug、完成一个子任务)
↓
commit
↓
session 退出,context 销毁
↓
下一个 tick 重新开始
每次 session 启动时,context window 是空的。模型拿到的是当前磁盘状态——而不是上一轮的推理过程。上一轮的中间思考、死路、错误尝试,全部不存在于这个 session 里。
信息的传递载体是 git,不是对话历史。
上一轮做了什么?看 git log。当前代码是什么状态?看文件系统。任务完成到哪一步了?看 task 文件或者 issue tracker。这些都是持久化的、可靠的状态,不依赖 session 是否存活。
为什么这个思路有效
对比一下两种方式:
传统长 session 方式:
session 开始
tick 1: 推理 A → 操作 → 失败 → 推理 B(A 还在 context 里)
tick 2: 推理 C → 操作 → 失败 → 推理 D(A、B 还在 context 里)
tick N: context 里有前 N-1 轮所有推理,window 快满,质量下降
Ralph 方式:
session 1: 干净 context → 读磁盘状态 → 推理 → 操作 → commit → 退出
session 2: 干净 context → 读磁盘状态(已含上次 commit)→ 推理 → 操作 → commit → 退出
session N: 干净 context → 读最新磁盘状态 → 推理 → 操作 → commit → 退出
每次 session 拿到的是最新的、干净的状态,不带历史包袱。模型在每个 tick 都以最佳状态工作,而不是在一个越来越嘈杂的 context 里挣扎。
实操:用 Claude Code 跑一个 Ralph 式 Loop
Claude Code 提供了两个直接支持 Ralph 模式的机制:
-p 模式(非交互式单次执行)
claude -p "读取 TASK.md,完成其中第一个未完成的任务,完成后在文件里标记为 done,然后 commit"
-p 让 Claude Code 执行完就退出,不保持 session。这正是 Ralph 模式需要的——每次调用是一个独立的、生命周期确定的 session。
把它包进外层 loop:
#!/bin/bash
# ralph_loop.sh
MAX_ITER=10
ITER=0
while [ $ITER -lt $MAX_ITER ]; do
echo "=== Iteration $ITER ==="
# 检查是否还有未完成任务
if ! grep -q "\[ \]" TASK.md; then
echo "所有任务完成,退出"
exit 0
fi
# 跑一个 tick
claude -p "读取 TASK.md,完成其中第一个未完成的任务(标记为 [ ]),
完成后把 [ ] 改为 [x],然后执行 git add -A && git commit -m 'task: complete next item'"
# 验证 commit 有没有发生(确定性信号)
if ! git log --oneline -1 | grep -q "task:"; then
echo "本轮没有产生 commit,可能卡住了,退出"
exit 1
fi
ITER=$((ITER + 1))
done
echo "达到最大迭代次数,停止"
这个脚本的结构体现了 Ralph 模式的全部要点:
- 外层 loop 是 bash,不是 agent——驱动逻辑是确定性的
- 每次
claude -p是一个独立 session,完成就退出 - 状态(TASK.md、代码)活在磁盘,通过 git 传递
- 有明确的终止条件(任务全完成 or 达到迭代上限 or 没有 commit 产生)
/goal 命令
Claude Code 内置的 /goal 是 Ralph 模式的产品化封装。它在内部管理迭代循环,自动处理 context reset,你只需要描述目标:
/goal 修复所有 TypeScript 编译错误,直到 tsc --noEmit 零报错为止
/goal 会自动跑多轮,每轮 context 重置,终止条件是 tsc 通过——这是一个标准的确定性 loop,完全交给工具管理。
一个需要注意的边界
Ralph 模式假设每个工作单元是独立的,可以 commit 的。如果任务本身是强耦合的——比如一个大重构,中间状态是不可 commit 的破坏性状态——Ralph 模式直接套用会有问题。
处理方式:
- 在独立分支上跑,允许每个 tick commit 中间状态
- 或者把大任务拆成更小的、各自可以独立完成的子任务,再交给 loop
任务的可拆分性,是 Ralph 模式能不能用的前提。
本节核心一句话
状态活在磁盘,session 随时可以销毁——Ralph 模式用 git 代替对话历史,每个 tick 都以最佳状态开始。