实战项目三:设计状态文件和初始化脚本,让 Agent 多次中断后无缝恢复
上篇文章我们解决了"Agent 之间怎么交接工作"的问题。这篇文章要处理一个更深层的挑战:Agent 自己怎么记住状态?
人类的记忆力不持久,但至少有短期记忆。Agent 呢?上下文窗口一满,或者对话一刷新,它的"短期记忆"就清零了。
第三个实战项目教你:用状态文件和初始化脚本,让 Agent 拥有工程级的持久记忆。
01 Agent 的"断片"场景
"断片"不是比喻,是每天都在发生的事实。
场景一:Token 耗尽
Agent 正在写一个复杂的功能,对话历史越来越长。突然,它开始"健忘"——你明明告诉过它用 PostgreSQL,它却开始写 SQLite 的代码。不是它叛逆,是上下文满了,早期的指令被挤出了窗口。
场景二:对话重启
你关闭窗口、睡一觉、第二天重新打开。Agent 完全不知道昨天做了什么。它可能重新探索目录结构、重新理解架构、重新踩一遍昨天已经踩过的坑。
场景三:任务中断
Agent 执行一个长任务,执行到一半报错了。你帮它修了一下环境,让它继续。但它不知道从哪继续——它看到的是"当前代码状态",却不知道"执行计划执行到哪一步了"。
这三种场景的共同点是:Agent 没有工作记忆的外部化机制。 一切状态都保存在上下文中,上下文一丢,状态就清零。
02 状态持久化的核心思路
解决方案不复杂:把 Agent 的工作状态显式地写进文件系统。
课程里的设计是 .agent/status.json + .agent/plan.md 的组合:
plan.md:执行计划
# 任务:重构订单模块## 阶段 1:分析现有代码(已完成)- [x] 阅读 src/services/order_service.py- [x] 阅读 src/models/order.py- [x] 识别耦合点:订单服务直接调用支付 API## 阶段 2:设计新架构(已完成)- [x] 引入 OrderRepository 抽象层- [x] 定义 PaymentGateway 接口## 阶段 3:实现重构(进行中)- [x] 创建 src/repositories/order_repository.py- [ ] 修改 src/services/order_service.py 使用 Repository 模式- [ ] 创建 src/gateways/payment_gateway.py- [ ] 更新测试用例## 阶段 4:验证(未开始)- [ ] 运行全部测试- [ ] 运行性能基准测试status.json:运行时状态
{ "current_task": "重构订单模块", "current_phase": 3, "last_action": "创建了 src/repositories/order_repository.py", "last_error": null, "context_files": [ "src/services/order_service.py", "src/repositories/order_repository.py" ], "pending_decisions": [ "PaymentGateway 接口是否需要支持异步?" ]}这两个文件的分工很明确:
- plan.md
是"地图",告诉 Agent 整体任务分几个阶段,当前在哪个阶段 - status.json
是"定位器",告诉 Agent 上一次具体做了什么、卡在哪里、还有什么没决定
03 初始化脚本:Agent 的"开机自检"
光有状态文件不够。Agent 每次"上班"时,需要一种机制来自动加载状态、恢复上下文。
课程里推荐的方案是初始化脚本.agent/init.sh:
#!/bin/bash# Agent 初始化脚本echo "=== Agent 环境初始化 ==="# 1. 检查项目依赖pip install -r requirements.txt# 2. 运行数据库迁移alembic upgrade head# 3. 加载当前状态cat .agent/status.json# 4. 显示当前任务计划cat .agent/plan.md# 5. 显示最近的 Git 变更git log --oneline -5echo "=== 初始化完成,请读取 plan.md 了解当前任务状态 ==="Agent 每次启动时,先运行这个脚本。它自动完成了:
环境准备(依赖安装、数据库迁移) 状态加载(显示当前任务和进度) 上下文恢复(最近的代码变更)
Agent 不需要问你"上次做到哪了",脚本已经告诉它了。
04 状态 Schema 的设计原则
状态文件不是随便写的。课程里总结了几个设计原则:
原则一:状态必须可机读
用结构化的格式(JSON、YAML、Markdown checklist),而不是自然语言段落。Agent 解析 JSON 比理解散文更可靠。
原则二:状态必须与代码状态一致
如果 plan.md 说"阶段 2 已完成",但代码里没有对应的实现,状态就是虚假的。每次 Agent 更新状态后,应该同时更新代码,并且通过版本控制(Git)确保两者同步。
原则三:状态更新应该是原子操作
Agent 完成一个子任务后,应该同时更新 plan.md(打勾)、status.json(更新阶段)、并提交一次 Git commit。不要把状态更新分散在多个步骤里,否则中断时可能出现状态不一致。
原则四:状态文件是代码的一部分
.agent/ 目录应该被纳入版本控制。它的变更历史就是 Agent 的工作历史,可以回溯、可以 review、可以回滚。
05 一个完整的"断片恢复"流程
让我们走一遍 Agent"断片"后恢复工作的完整流程:
Step 1:Agent 启动,运行 init.sh
脚本加载了 plan.md 和 status.json,Agent 知道当前在阶段 3,上一个动作是创建了 order_repository.py。
Step 2:Agent 读取相关代码
根据 status.json 里的 context_files,Agent 优先读取这两个文件,恢复代码上下文。
Step 3:Agent 继续执行任务
plan.md 显示下一个动作是"修改 order_service.py 使用 Repository 模式"。Agent 直接开始执行,不需要重新探索 codebase。
Step 4:Agent 更新状态
任务完成后,Agent 更新 plan.md(打勾)、status.json(更新阶段和 last_action)、并运行验证脚本。
Step 5:Agent 提交变更
代码 + 状态文件一起 Git commit,确保状态和代码永远一致。
整个流程中,Agent 没有"失忆",因为它把记忆存在仓库里,而不是脑子里。
06 写在最后
人类工程师也会忘记昨天做了什么,但我们会看 Jira、看 commit history、看聊天记录。Agent 没有这些工具——除非我们为它造。
plan.md 是 Agent 的 Jira,status.json 是 Agent 的笔记本,init.sh 是 Agent 的晨会。三者组合,Agent 就能在无数次中断后无缝恢复。
下一篇文章,第四和第五个项目:让 Agent 学会自我纠错——运行时反馈与验证闭环。
本文基于 walkinglabs/learn-harness-engineering 课程内容整理,系列共 8 篇。
夜雨聆风