本页目录
Lesson 10 — 长任务:跨会话的任务状态
本课目标:手写 TaskLedger(任务账本)——TODO 树的 sqlite 持久化 + 断点续跑决策 + 增量简报生成。让 Agent 能推进一个跨多次运行的长期任务,产出增量而非从零重写。
学完你能回答:「你的 Agent 能跑长任务吗?跨多次运行怎么推进?」——有任务账本,第三次运行接着第二次做,而不是从头再来。
0. 起点:为什么需要任务账本
硬任务要求"每次运行产出增量简报而非从零重写"。但现在 research-assistant 每次运行都是独立的——不知道上次做到哪了、还差什么。
L01 的记忆解决的是"记得上次查过什么"(经验),但不解决"做到哪一步了"(进度)。进度和经验是两个维度:
记忆(L01-L02)= 经验存储
"上次查了 MCP 协议,发现基于 JSON-RPC"
→ 回答"上次学到了什么"
账本(本课)= 计划存储
"MCP 演进追踪的 TODO:①协议设计(done) ②SDK语言(done) ③生态扩展(todo)"
→ 回答"做到哪了,还差什么"
🎯 核心认知:长任务 = 记忆(经验)+ 账本(进度)+ checkpoint(对话状态)。三者协同:记忆提供"上次学到了什么",账本提供"还差什么没做",checkpoint 恢复"对话到哪了"。
1. 长任务三要素
① 任务状态持久化(TODO 树)
@dataclass
class TaskItem:
id: str
topic: str # 大主题
title: str # 本节点要做什么
status: str # todo / in_progress / done
result: str # 完成后的结论
run_count: int # 被执行过几次
TODO 树持久化到 sqlite(比 Chroma 轻,结构化数据不需要向量检索)。
② 断点续跑
def next_actions(topic) -> list[TaskItem]:
# 先看 todo(还没做的)
# 再看 in_progress(做了一半的)
# 全 done → 返回空(任务完成了)
新会话先调 next_actions 决定"接着做什么"——而不是"从头做"。
③ 增量产出
def generate_incremental_brief(topic, new_findings) -> str:
# 历史结论(已确认的 done 任务)
# 本次新增(🆕)
# 修正项(✏️)
# 不变项(➡️)
增量简报是 diff 式的——上次结论 + 本次新增 + 修正项,不是从零重写。
2. 增量简报的格式
# 增量简报:MCP 生态的演进
## 历史结论(已确认)
- ➡️ 协议设计: MCP 基于 JSON-RPC 2.0
- ➡️ SDK 语言: 支持 Python/TS/Java
## 本次新增
- 🆕 MCP 生态在 2025 年扩展到了数据库场景
- ✏️ 修正: MCP 协议实际基于 JSON-RPC 2.0(旧结论遗漏版本号)
## 不变项
- ➡️ MCP 由 Anthropic 提出: 仍成立
三种标记: - 🆕 新增:上次没有的新信息 - ✏️ 修正:与旧结论不同(和 L05 的冲突修正呼应) - ➡️ 不变:旧结论仍成立(确认而非重复)
💡 增量简报的价值:读者一眼看出"这次有什么新东西",不用通读全文对比差异。这在"持续追踪"场景下极重要——第 5 次运行的报告如果还是从头写,读者根本看不出这次和上次有什么不同。
3. 流派对比
问题:Agent 怎么管理跨会话的长任务进度?
| 流派 | 做法 | 取舍 |
|---|---|---|
| ① plan-and-execute 静态计划 | 开头定计划,严格按计划走 | ✅ 可控;🚫 计划不随实际调整 |
| ② 动态 TODO 更新(本课选它) | 计划本身也会被反思修正 | ✅ 灵活、适应变化;🚫 计划可能漂移 |
| ③ 无计划(纯 ReAct) | 不显式存计划,靠对话/记忆 | ✅ 简单;🚫 长任务会"忘了还要做什么" |
选 ② 的理由:硬任务"持续追踪研究"的计划会演进——第一次可能只查协议,发现生态很大后要加"SDK 语言""场景覆盖"等新子任务。静态计划无法适应这种演进。动态 TODO 允许:新发现 → 加新 TODO;旧 TODO 完成 → 标 done;发现计划错了 → 改 TODO。
与记忆/checkpoint 的分工
┌─ 一次研究的上下文来源 ──────────────────────┐
│ │
│ Checkpointer(对话状态)→ 恢复对话中断点 │
│ "用户问到哪了,上次回答了什么" │
│ │
│ MemoryStore(经验记忆)→ recall 相关旧经验 │
│ "上次查 MCP 协议发现了什么" │
│ │
│ TaskLedger(计划进度)→ 决定接下来做什么 │
│ "MCP 追踪的 TODO 还差生态扩展没查" │
│ │
└─────────────────────────────────────────────┘
三者各管一摊,不重叠:对话恢复、经验调回、计划推进。
4. 落地清单
改了哪些文件
| 文件 | 改动 | 说明 |
|---|---|---|
src/research_assistant/task_ledger.py |
新增 | TaskLedger(TODO 树 + 断点续跑 + 增量简报) |
src/research_assistant/config.py |
加 enable_ledger/ledger_db_path/output_mode |
默认关 |
tests/test_ledger.py |
新增 12 个测试 | 增删改查/断点续跑/增量简报/多主题隔离 |
如何验证
cd portfolio-projects/research-assistant
# 1. 全量测试(92 原有 + 12 新增 = 104 全绿)
.venv/Scripts/python.exe -m pytest tests/ -q
# 预期:104 passed
# 2. 演示长任务(模拟 3 次运行)
cd ../../frontier-lessons/10_long_task
PYTHONIOENCODING=utf-8 ../../.venv/Scripts/python.exe code.py
# 预期:3 次运行,第 2/3 次产出增量简报(标注新增/修正/不变)
# 3. 真实跑(需 ENABLE_LEDGER=true + API key)
# 连跑 3 次同一主题,第 2/3 次应接着上次做
5. 本课在两条主线上的位置
- 评估主线:增量简报本身是一个可评估产出——"增量价值"(新增信息占比)可量化。L09 的 harness 可以加"增量模式 vs 全量模式"的对比指标。
- 上下文工程主线:TaskLedger 是上下文工程的规划层——决定"本次运行该把哪些信息放进上下文"(只放待办 TODO 的相关内容,不重做已完成的)。这和 L01 的记忆(经验调回)、L03 的 skills(能力调回)协同:账本说"该做什么",记忆说"上次怎么做",skills 说"怎么做规范"。
🎯 面试话术
「我的 Agent 跑长任务有任务账本——TODO 树 sqlite 持久化、断点续跑、增量产出。和记忆、checkpoint 三者分工:checkpoint 恢复对话,记忆 recall 经验,账本推进计划。第三次运行它接着上次做——next_actions 返回还没完成的 TODO,产出增量简报标注 🆕新增/✏️修正/➡️不变。计划本身是动态的——新发现可以加 TODO,不像静态 plan-and-execute 定死不改。」