Engineering note
计划、执行与反思:把多步任务变成可恢复过程
这是「Agent 工程实战」的第 17 篇。专题从一个能聊天、能调工具的 .NET Agent 出发,逐步补齐可靠性、安全、测试与发布能力。
本篇要解决的问题: 让 Agent 维护显式计划、处理失败,并在必要时把控制权交还给人。
本章定位:本章讨论多步骤任务的计划、执行和反思。你会从线性计划器开始,理解任务状态、失败恢复和反思上限,避免把 Agent 变成无限自我对话。
建议阅读方式:先通读原理,再对照当前项目源码,最后完成本章实践。计划应该服务于可观察执行,而不是生成一份好看的长文本。
本章导读
本章讨论多步骤任务的计划、执行和反思。你会从线性计划器开始,理解任务状态、失败恢复和反思上限,避免把 Agent 变成无限自我对话。
本章采用“源码观察 → 概念拆解 → 工程改造 → 实践验证”的顺序。示例中的接口和代码骨架用于说明设计方向,真正提交代码时应结合项目当前状态逐步落地。
17.1 什么时候需要计划
单步工具调用可以由模型直接完成;当任务包含多个依赖步骤时,才需要显式计划。例如:分析项目、提出修改、运行测试、总结结果。
计划不是让模型输出一篇漂亮的计划,而是把任务拆成可观察、可重试、可终止的步骤。
17.2 任务图
public sealed record AgentTask(
string Id,
string Title,
IReadOnlyList<string> DependsOn,
TaskStatus Status);
先实现线性任务列表,再考虑并行任务。并行执行前必须确认工具是线程安全、互不冲突且不会产生竞态副作用。
17.3 反思要有约束
“反思”不应变成无穷自我对话。应当限定:
- 反思触发条件;
- 最多反思次数;
- 反思输入只包含必要信息;
- 反思必须产出下一步动作或终止理由。
17.4 本章交付物
- 线性任务计划器;
- 任务状态持久化;
- 失败重试和人工接管;
- 最大计划步数;
- 计划执行日志。
17.5 什么时候计划反而有害
简单问题不需要计划。让模型先生成很长的计划,再执行一个读取操作,会增加延迟、token 成本和失败机会。
计划也可能把错误假设固化:模型一开始理解错了目标,后续所有步骤都围绕错误方向展开。因此计划应当短、可修改,并且在关键步骤后重新检查目标。
17.6 线性计划的最小实现
第一版不必实现复杂 DAG,可以使用:
public sealed class PlanExecutor
{
public async Task<PlanResult> ExecuteAsync(
IReadOnlyList<PlanStep> steps,
CancellationToken cancellationToken)
{
foreach (var step in steps)
{
step.MarkRunning();
var result = await _agent.RunStepAsync(step, cancellationToken);
step.Complete(result);
if (!result.Success) return PlanResult.Failed(step.Id);
}
return PlanResult.Completed();
}
}
重点是每个步骤有状态、有输出、有失败边界。后续再增加依赖、并行和人工接管。
17.7 计划和工具调用的关系
计划步骤不应该绕过工具策略。计划器只是更高一层的编排器,实际每个动作仍然要经过 schema、权限、审批和审计。
例如“部署应用”可能拆成检查代码、运行测试、构建镜像和发布。即使计划器自动生成了这些步骤,发布动作仍然应当根据风险要求人工确认。
17.8 反思的可执行格式
不要让反思只产生自然语言长文。可以要求结构化结果:
{
"status": "needs_retry",
"reason": "测试失败是因为缺少配置",
"nextAction": "读取配置模板",
"stop": false
}
结构化反思才能被程序判断是否继续,而不是通过关键词猜测模型意思。
17.9 练习:实现一个项目分析计划
让 Agent 执行“分析当前项目并给出三条改进建议”:读取项目文件、识别工具、运行构建、汇总警告。要求每一步都记录状态,构建失败时停止后续建议,而不是继续假装分析完成。
17.10 本章产出
本章结束时,你应该拥有一个受步骤数和权限约束的线性执行器,而不是一个可以无限自我对话的“反思 Agent”。
单篇实战作业
实践:实现一个三步项目分析计划,要求每一步可暂停、可失败、可重试,且总步骤数有上限。
建议把作业拆成一个独立提交,并在提交说明中写清楚:改动前的行为、改动后的行为、验证命令、尚未解决的风险。计划应该服务于可观察执行,而不是生成一份好看的长文本。
章节复盘
复盘问题:计划是否让简单任务变慢?是否存在无意义的反思循环或不受约束的自动重试?
本章的完成标准不是把所有设计一次性做完,而是能把它变成项目中的一个明确边界,并为下一章留下可验证的接口。