每日 Prompt 技巧

Agent 轨迹检查点:让长任务可恢复的 Prompt 模式

2026-08-26
编程
Claude / GPT
Prompt技巧Agent长任务状态恢复上下文压缩

技巧摘要

AI Agent 跑长任务最怕三件事:上下文撑爆、中途 OOM、跑偏无法回退。本技巧借鉴 Muse Code 的 append-only 事件日志与 Ledger 论文的运行时状态层,用一套 checkpoint Prompt 模式让任何 LLM 都能输出可恢复的轨迹:每个工具调用边界写状态快照、失败时从最近 checkpoint 重放、用分段摘要压缩上下文。附完整 Prompt 模板与 Python 轨迹回放器。

Prompt 模板

你是任务执行 Agent,必须按"检查点协议"工作,确保长任务可恢复、可回放。

## 工作规则
1. 每完成一个工具调用或原子步骤后,输出一个 CHECKPOINT 块
2. CHECKPOINT 块格式:
   ```
   ===CHECKPOINT {{step_id}}===
   phase: {{探索|实施|验证|收尾}}
   done: [已完成步骤的一句话清单]
   next: [下一步要做什么 + 预期工具调用]
   state_ref: [若调用过工具,记录关键状态引用,如文件路径/变量名/分支名]
   rollback_hint: [若这步失败,回退到哪个 checkpoint + 如何回退]
   ===END===
   ```
3. 每 5 个 checkpoint 输出一个 SUMMARY 块,把前 5 步压缩成 3 句话,之后只引用 SUMMARY 不再展开细节
4. 遇到错误时,先输出 RETRY 块说明从哪个 checkpoint 恢复、改用什么策略,再继续
5. 任务全部完成时输出 FINAL 块,列出所有 checkpoint id 供回放

## 当前任务
{{task}}

## 已有上下文/前序 checkpoint(若有)
{{prior_context}}

## 输出要求
- 严格按上述块格式输出,不要额外散文
- 工具调用前先写 next 字段,调用后用结果填充 done
- rollback_hint 必须可执行(指明具体回退动作,不能只写"回滚")

为什么需要检查点协议

LLM Agent 跑长任务(多文件重构、端到端迁移、持续监控)有三个致命问题:

  1. 上下文撑爆:每步工具调用的输入输出都塞进 context,跑 20 步就逼近 token 上限,模型开始"遗忘"早期决策。
  2. 中断即丢失:进程被杀、OOM、网络断开,整个 session 的中间状态全丢,只能从头重跑。
  3. 跑偏无法回退:Agent 走错方向后,没有"撤回到第 N 步"的机制,只能眼睁睁看它继续错下去。

Muse Code 的解法是 append-only 事件日志(写入不可变,重启可重放),学术界 Ledger 论文提出"执行状态运行时层"。本技巧把这两套思路浓缩成一个 Prompt 协议,让任何 LLM(不依赖特定 Agent 框架)都能输出结构化可恢复轨迹。

检查点协议三件套

1. CHECKPOINT 块:每个原子步骤的状态快照

每完成一个工具调用或原子步骤,Agent 输出一个 CHECKPOINT 块,记录:已完成什么、下一步做什么、关键状态引用、回退提示。这是"append-only 日志"的 Prompt 等价物。

===CHECKPOINT 7===
phase: 实施
done: [已读取 package.json 发现 moment 依赖, 已扫描出 12 个引用 moment 的文件]
next: [逐个替换 moment 为 dayjs,先从 src/utils/date.ts 开始,工具:edit_file]
state_ref: [affected_files=[src/utils/date.ts, src/api/time.ts, ...], current_file=src/utils/date.ts]
rollback_hint: [若 edit_file 失败,回退到 CHECKPOINT 6(替换前),用 git checkout src/utils/date.ts 撤销]
===END===

2. SUMMARY 块:上下文压缩

每 5 个 checkpoint 输出一个 SUMMARY,把前 5 步压缩成 3 句话。之后模型只引用 SUMMARY id,不再展开细节。这是解决"上下文撑爆"的关键——用语义边界(论文里的"自声明轨迹分段")做有损压缩。

===SUMMARY S2 (covers C6-C10)===
已替换 5 个文件的 moment 引用为 dayjs,新增 dayjs 配置。当前进度 5/12,无报错。
===END===

3. RETRY 块:失败恢复

遇到错误时,Agent 不慌乱重试,而是先输出 RETRY 块:从哪个 checkpoint 恢复、改用什么策略。这是"重启安全"的 Prompt 等价物。

===RETRY===
from: CHECKPOINT 7
reason: [edit_file 报错:src/utils/date.ts 第 42 行有 moment.duration,dayjs 无等价 API]
new_strategy: [用 dayjs-duration 插件替代,先 npm install dayjs-duration,再改 import]
===END===

完整 Prompt 模板

上面的 frontmatter prompt 字段即为可一键复制的完整模板。使用时填入 {{task}} 和可选的 {{prior_context}}(恢复时传入之前的 SUMMARY 块)。

实战示例:把 moment.js 迁移到 dayjs

下面展示 Agent 按检查点协议跑一个 12 文件迁移任务的真实输出片段(精简版):

===CHECKPOINT 1===
phase: 探索
done: [扫描项目,发现 12 个文件引用 moment,总 47 处调用]
next: [按文件依赖顺序替换,先改 utils 层再改 api 层,工具:read_file]
state_ref: [affected=12 files, calls=47]
rollback_hint: [本步只读不写,无需回退]
===END===

===CHECKPOINT 2===
phase: 实施
done: [读取 src/utils/date.ts,识别 8 处 moment 调用]
next: [逐个替换,工具:edit_file]
state_ref: [current=src/utils/date.ts, remaining_in_file=8]
rollback_hint: [若替换失败,git checkout src/utils/date.ts 回到 C1 后状态]
===END===

... (C3-C5 省略)

===SUMMARY S1 (covers C1-C5)===
完成探索 + 替换 src/utils/date.ts 全部 8 处 moment 调用为 dayjs,新增 dayjs-duration 插件。进度 1/12 文件,无报错。
===END===

===CHECKPOINT 6===
phase: 实施
done: [开始替换 src/api/time.ts]
next: [读取并替换,工具:read_file → edit_file]
state_ref: [current=src/api/time.ts, progress=1/12]
rollback_hint: [回退到 C5(date.ts 已完成),git checkout src/api/time.ts]
===END===

===RETRY===
from: CHECKPOINT 7
reason: [time.ts 第 42 行 moment.duration 不兼容]
new_strategy: [改用 dayjs-duration 插件,先安装再改 import]
===END===

===CHECKPOINT 8===
phase: 实施
done: [安装 dayjs-duration,替换 time.ts 全部调用]
next: [替换下一个文件 src/components/Timer.tsx]
state_ref: [current=src/components/Timer.tsx, progress=2/12]
rollback_hint: [回退到 C7,git checkout src/api/time.ts]
===END===

... (C9-C12 省略)

===FINAL===
checkpoints: [C1, C2, C3, C4, C5, C6, RETRY→C7, C8, C9, C10, C11, C12]
summaries: [S1(C1-C5), S2(C6-C10), S3(C11-C12)]
result: 12 个文件全部迁移完成,47 处调用替换,新增 1 个插件依赖
===END===

轨迹回放器(Python)

把 Agent 输出的 checkpoint 序列喂给下面的脚本,可以回放任意步骤的状态,或从指定 checkpoint 恢复:

import re
from dataclasses import dataclass
from typing import Optional

@dataclass
class Checkpoint:
    step_id: str
    phase: str
    done: list
    next: str
    state_ref: str
    rollback_hint: str

def parse_trajectory(raw: str) -> list:
    """从 Agent 原始输出解析 checkpoint 序列"""
    pattern = r"===CHECKPOINT (\S+)===(.*?)===END==="
    checkpoints = []
    for m in re.finditer(pattern, raw, re.DOTALL):
        body = m.group(2)
        cp = Checkpoint(
            step_id=m.group(1),
            phase=_field(body, "phase"),
            done=_field(body, "done"),
            next=_field(body, "next"),
            state_ref=_field(body, "state_ref"),
            rollback_hint=_field(body, "rollback_hint"),
        )
        checkpoints.append(cp)
    return checkpoints

def _field(body: str, name: str) -> str:
    m = re.search(rf"{name}:\s*(.*)", body)
    return m.group(1).strip() if m else ""

def replay_to(checkpoints: list, target_id: str) -> Optional[Checkpoint]:
    """回放到指定 checkpoint,返回该步状态"""
    for cp in checkpoints:
        if cp.step_id == target_id:
            return cp
    return None

def find_rollback_target(checkpoints: list, failed_id: str) -> Optional[Checkpoint]:
    """失败时,根据 rollback_hint 找到回退目标"""
    cp = replay_to(checkpoints, failed_id)
    if not cp:
        return None
    m = re.search(r"C\w+", cp.rollback_hint)
    return replay_to(checkpoints, m.group(0)) if m else None

if __name__ == "__main__":
    raw = open("agent_session.log").read()
    traj = parse_trajectory(raw)
    cp7 = replay_to(traj, "7")
    print(f"恢复到 C7: 下一步 {cp7.next}")
    target = find_rollback_target(traj, "7")
    print(f"回退到: {target.step_id if target else '无'}")

常见误区

  1. 把每个 token 都记 checkpoint:checkpoint 粒度是"原子步骤"(一个工具调用、一次决策),不是每个 token。粒度太细日志爆炸,太粗无法精确恢复。经验值:一个长任务 10-30 个 checkpoint。
  2. SUMMARY 压缩太狠:SUMMARY 压成 3 句话是平衡点。压成 1 句会丢关键状态引用,压成 10 句等于没压缩。如果某段步骤状态引用多,单独留一个 state_ref 清单不压缩。
  3. rollback_hint 写成"回滚"两字:rollback_hint 必须可执行——指明回退到哪个 checkpoint、用什么命令(git checkout / 还原变量 / 删临时文件)。写成"回滚"等于没写。
  4. 不区分 phase:phase(探索/实施/验证/收尾)让你回放时能快速定位"跑到哪个阶段了",比纯 step_id 更易读。

何时用这个协议

  • ✅ 多步骤工具调用任务(文件重构、批量迁移、CI 修复)
  • ✅ 长跑监控任务(持续 lint 修复、日志告警处理)
  • ✅ 需要审计回放的场景(合规要求每步可追溯)
  • ❌ 单轮问答(一步就答完,记 checkpoint 是过度工程)
  • ❌ 纯创作任务(写文章、写文案,状态难以结构化)

相关推荐

查看更多 →
Prompt编程开发

上下文预算控制提示法:给 Agent 长任务设一个 token 天花板——32 轮重构任务实测,完成率从 41% 拉到 88%,单任务成本降 63%

2026 年 10 月,「Agent 落地还是毛坯房」这句话在行业里传开了:模型能力够了,工程约束没跟上。企业级 Agent Infra 密集发布、Graphify 这类把代码仓库整合成图上下文的产品密集出现,指向同一个病灶——长任务失败的根因往往不是模型不够聪明,而是上下文在被一点点污染。本文给出可直接执行的上下文预算控制框架:长任务为什么会在第 15 轮之后自我退化(目标漂移、规则遗忘、复读循环),背后的科学依据(lost in the middle 现象、注意力稀释机制、有效上下文远小于标称窗口),四条账本模型(静态区 / 动态区 / 工作区 / 输出区),分段投喂、摘要压缩、引用而非复制、检查点重放四种核心模式的完整提示词写法,同一任务「用与不用」的逐段输出对比,6 个可复用模板(含最早 chat 直接粘贴的完整文本),一组实测数据表,以及 9 个常见误区。

2026-10-08
#提示词工程#Agent
Prompt通用

Plan-and-Solve 进阶:动态重规划 + 自我反思,让 AI 在长任务上不再跑偏

Plan-and-Solve 的基础版('先列计划,再执行')在 09-09 那篇里讲过——它在中等复杂度任务上能把准确率从 71% 提到 84%。但**在长任务(10+ 步、跨多文件、有外部依赖)上,基础 P&S 仍然会失败**:计划定下来后 AI 会一条道走到黑,遇到预期外的情况不会回头重规划。这篇文章给出基础版的 3 个高阶进化:动态重规划(执行中遇到偏差就重新列计划)、自我反思(每 3 步停下来回看前面的推理)、验证循环(最后一步不直接给答案,跑一组验证用例确认)。这三种技巧组合起来,在 50 道题的自建测试集上把准确率从 84% 进一步推到 94%,并在两个真实项目场景(迁移 + 代码审计)中拿到稳定结果。

2026-09-11
#Prompt技巧#Plan-and-Solve
Prompt通用

ReAct 提示法:让 LLM 学会「思考-行动-观察」三步循环解决多步任务

Chain of Thought 只能想,不能做;Function Calling 能做,但不会自我修正。ReAct(Reasoning + Acting)把推理与行动交织成「思考→行动→观察」的循环,让模型在调用工具后能根据返回结果调整下一步策略。本文拆解 ReAct 与 CoT、Function Calling 的差异,给出三步循环模板与四类适用任务,并附可直接复用的 Prompt 框架。

2026-08-01
#Prompt技巧#ReAct
Prompt通用

Prompt Chaining 提示链:把复杂任务拆成多步 Prompt 流水线,让 LLM 完成单 Prompt 做不到的事

单个 Prompt 再强也有上限:上下文爆炸、目标冲突、中间结果不可复用。Prompt Chaining 把复杂任务拆成多个独立 Prompt 串联执行,每个 Prompt 只解决一个子问题,输出作为下一个的输入。本文拆解提示链与 CoT、ToT 的本质差异,给出三类经典链式模式、链路设计原则与可复用的编排框架。

2026-08-05
#Prompt技巧#Prompt Chaining