复杂 Agent 如何真正落地:讲透 ReAct、Plan-and-Execute、Workflow、Reflection 与人工接管

作者:逆境不可逃
技术永无止境
希望我的内容可以帮助到你!!!!
本文承接《Agent 记忆不只是聊天记录:讲透会话、Profile、TaskState、召回与删除治理》。
如果记忆系统解决的是 “任务中断后如何记住做到哪里”,规划与执行系统解决的就是 “面对复杂目标,下一步做什么、如何验证、什么时候停止,以及何时把控制权交还给人类”。
摘要
很多 Agent Demo 的核心只是一个循环:模型思考、调用工具、读取结果,然后继续思考。它适合短任务,却很难直接承担真实业务中的长流程。一旦任务涉及多个依赖步骤、外部系统、副作用、审批、预算和失败恢复,就会出现计划不可执行、工具无限重试、任务重复运行、结果缺少证据、模型反复自我修正、失败后无法恢复等问题。
可靠的规划与执行系统,不是让模型 “想得更久”,而是建立受控的任务运行时:先把目标表示为 Goal Contract,再拆成 Milestone 和 Work Item;用 Workflow 管理全局阶段,用 Plan-and-Execute 管理任务依赖,用受限 ReAct 处理局部不确定性,用 Verification Contract 检查产物;同时通过 Attempt、Artifact、Checkpoint、Budget、Plan Version、Lease、Termination Record 和 Handoff Package 保证任务可追踪、可恢复、可停止、可接管。
本文围绕,以 “Payment SDK 迁移调研助手” 为贯穿案例,系统讲解任务拆解、状态表示、ReAct、Plan-and-Execute、Reflection、Workflow 与 Agent 的边界、终止与降级、人工接管以及端到端测试。目标不是做一个永远运行的自主 Agent,而是做一个在正确边界内自主、在证据不足时诚实停止的工程系统。
关键词
Agent、任务规划、ReAct、Plan-and-Execute、Workflow、Reflection、Checkpoint、幂等、预算控制、人工接管、后端工程
一、先纠正误解:复杂任务不是把单轮对话循环得更久
一个最小 Agent 往往长这样:
用户目标
→ 模型决定动作
→ 调用工具
→ 把结果交给模型
→ 模型继续决定
→ 直到模型说完成
这个模式可以完成天气查询、简单检索和单次数据转换,但复杂任务会提出更多工程问题:
- 目标是否已经明确;
- 哪些步骤必须先完成;
- 哪些步骤可以并行;
- 中间产物保存在哪里;
- 工具超时后能否重试;
- 重试会不会产生重复副作用;
- 模型为什么认为任务已经完成;
- 报告中的结论是否有证据;
- 预算耗尽后返回什么;
- 服务重启后从哪里恢复;
- 哪些风险必须由人类确认。
如果这些问题都交给模型临场判断,系统就会变成一个不可预测的大循环。
真正可靠的执行链路应该是:
明确目标
→ 生成结构化计划
→ 校验计划
→ 按依赖调度任务
→ 受控调用工具
→ 保存中间产物
→ 校验结果
→ 必要时有限修正或重规划
→ 完成、降级、暂停或人工接管
核心变化不是 “模型能力更强”,而是应用层开始承担状态、边界和恢复责任。
二、四种机制分工:Workflow、Plan、ReAct 与 Reflection
规划与执行系统经常同时使用四种机制。它们不是竞争关系,而是不同控制层。
| 机制 | 解决的问题 | 适合范围 | 主要风险 |
|---|---|---|---|
| Workflow | 全局流程按什么阶段运行 | 稳定业务阶段、审批、等待、补偿 | 过度固定会缺少适应性 |
| Plan-and-Execute | 复杂目标如何拆解和调度 | 多里程碑、依赖任务、长期执行 | 计划陈旧或不可执行 |
| ReAct | 信息不足时下一步探索什么 | 局部检索、诊断、参数调整 | 无限循环、重复动作 |
| Reflection | 产物是否合格,能否修正 | 报告、代码、结构化结果 | 自我评价偏差、无限改写 |
推荐采用四层控制:
第一层:Workflow 管全局阶段
第二层:Plan-and-Execute 管任务依赖
第三层:局部 ReAct 管开放式探索
第四层:Artifact Reflection 管产物质量
例如 “生成迁移评估报告” 的全局阶段可以固定:
INTAKE
→ PLAN
→ VALIDATE_PLAN
→ EXECUTE
→ VERIFY
→ HUMAN_APPROVAL
→ DELIVER
其中 “寻找 SDK 封装层” 可以使用最多 5 步的局部 ReAct;“检查报告是否遗漏风险” 可以使用 Reflection;但 ReAct 和 Reflection 都不能擅自改变全局目标、重置预算或跳过审批。
一句话概括:
Workflow 管全局,Plan 管任务,ReAct 管局部探索,Reflection 管产物质量。
三、先定义 Goal Contract,不要急着列步骤
用户经常只给出一句模糊目标:
帮我评估 Payment SDK v1 升级到 v2 的影响。
直接生成步骤会留下大量歧义:范围是一个仓库还是整个组织?只调研还是允许改代码?最终交付报告还是 Pull Request?什么叫评估完成?
因此先建立 Goal Contract:
{
"goal_id": "goal-payment-migration-001",
"objective": "分析 Payment SDK v1 到 v2 的迁移影响",
"scope": {
"repository_group": "payment-services",
"expected_repository_count": 12,
"document_spaces": ["engineering", "payment-platform"]
},
"deliverables": [
"repository-inventory.json",
"api-usage-inventory.json",
"risk-matrix.json",
"migration-assessment.md"
],
"constraints": {
"write_access": false,
"max_tool_calls": 120,
"deadline_minutes": 45,
"high_risk_requires_approval": true
},
"success_criteria": [
"覆盖所有可访问仓库",
"关键结论可追溯到证据",
"明确记录不可访问范围",
"给出迁移顺序和测试建议"
],
"failure_criteria": [
"没有权威迁移文档",
"可访问仓库比例低于 80%",
"预算不足以完成风险校验"
],
"evidence_requirements": {
"high_risk_claim": "至少一个权威来源和一个独立佐证"
}
}
3.1 硬约束与软约束
| 类型 | 示例 | 违反后处理 |
|---|---|---|
| 硬约束 | 只读访问、租户隔离、预算上限、审批门禁 | 阻止执行或人工接管 |
| 软约束 | 优先低成本工具、报告尽量简洁、优先并行 | 记录偏差并继续 |
模型不能为了 “完成任务” 突破硬约束。
3.2 完成条件必须可验证
下面这些条件无法稳定验收:
充分调研
尽可能覆盖
报告质量较高
没有明显问题
应改成:
每个可访问仓库都有 ANALYZED 或 NO_USAGE_FOUND 状态
每条高风险结论至少关联一个权威 Evidence
报告包含规定的 10 个章节
仓库数量与 inventory Artifact 一致
计划的第一原则是:先定义 “怎样算完成”,再讨论 “怎么做”。
四、三层任务模型:Goal、Milestone 与 Work Item
复杂任务不应只有一张扁平待办列表。
4.1 Goal
Goal 描述最终业务结果,通常对应一次完整 Run。
4.2 Milestone
Milestone 是可以独立验收的中间成果,例如:
- 范围和资源清点完成;
- 权威迁移知识建立完成;
- 所有仓库使用情况分析完成;
- 风险矩阵完成;
- 报告校验和交付完成。
Milestone 不应只是 “调用一次工具”。
坏例子:执行 search_code
好例子:完成所有可访问仓库的 SDK 使用清单
4.3 Work Item
Work Item 是可调度、可重试、可验收的最小工作单元:
{
"work_item_id": "W10",
"milestone_id": "M3",
"title": "寻找 SDK 封装层和动态调用",
"task_type": "LOCAL_REACT",
"dependencies": ["W08", "W09"],
"required_capabilities": ["search_code", "get_file_section"],
"output_spec": {
"artifact_type": "indirect-api-usage",
"schema_version": "1.0"
},
"completion_criteria": [
"每条记录包含仓库、文件和调用链",
"搜索范围覆盖所有可访问仓库",
"未确认项标记置信度"
],
"retry_policy": {
"max_attempts": 3,
"retryable_errors": ["TIMEOUT", "RATE_LIMITED"]
},
"max_react_steps": 5,
"risk_level": "LOW"
}
4.4 计划是 DAG,不是数组
Work Item 之间通常形成有向无环图:
W01 规范化目标
├─ W02 获取仓库清单
│ ├─ W08 搜索依赖声明
│ └─ W09 搜索直接调用
└─ W03 获取文档来源
└─ W05 搜索迁移文档
└─ W06 抽取破坏性变更
W08 + W09 + W06
→ W10 寻找封装层
→ W11 合并使用清单
→ W12 覆盖校验
只有依赖全部成功、审批已经满足、预算足够时,任务才能进入 READY。
五、状态必须结构化:不要把聊天历史当执行数据库
一个长期任务至少需要区分以下对象:
| 对象 | 作用 |
|---|---|
| Plan | 当前执行计划及版本 |
| Work Item | 一个可调度任务 |
| Attempt | Work Item 的一次具体尝试 |
| Artifact | 一次尝试产生的可复用产物 |
| Evidence | 支撑产物和结论的来源 |
| Run State | 整个任务当前状态 |
| Checkpoint | 可恢复的状态快照 |
5.1 Work Item 状态机
PENDING
→ READY
→ RUNNING
→ SUCCEEDED
RUNNING → RETRY_WAIT → READY
RUNNING → FAILED
PENDING → BLOCKED
READY → WAITING_FOR_APPROVAL
任意非终态 → CANCELLED
状态应由事实推导,而不是模型一句 “已经完成”:
def derive_work_item_status(item, attempts, verification):
if item.cancelled:
return "CANCELLED"
if item.approval_required and not item.approved:
return "WAITING_FOR_APPROVAL"
if verification and verification.passed:
return "SUCCEEDED"
if has_retryable_failure(attempts):
return "RETRY_WAIT"
if retry_exhausted(attempts):
return "FAILED"
if dependencies_failed(item):
return "BLOCKED"
if dependencies_satisfied(item):
return "READY"
return "PENDING"
5.2 Attempt 不能省略
只在 Work Item 上保存最后一个错误,会丢失关键过程:
- 第一次为什么失败;
- 第二次是否修改了参数;
- 三次失败是否为同一原因;
- 哪次调用产生了部分结果;
- 是否应该触发重复失败终止。
Attempt 至少保存 attempt_id、序号、输入快照哈希、工具调用引用、输出 Artifact、错误和最终 Outcome。
5.3 Artifact 必须可复用和可校验
Artifact 应包含类型、Schema Version、内容地址、内容哈希、来源 Attempt 和 Evidence 引用。
修正产物时创建新版本:
risk-matrix:v1
risk-matrix:v2
不要原地覆盖 v1,否则无法知道报告使用的是哪次结果。
六、Plan-and-Execute:规划、执行、校验必须分离
一个完整 Plan-and-Execute 系统至少包含五个角色。
| 角色 | 负责 | 不负责 |
|---|---|---|
| Goal Builder | 整理目标和约束 | 决定详细步骤 |
| Planner | 生成 Milestone、Work Item 和依赖 | 调用业务工具 |
| Executor | 执行一个明确 Work Item | 随意改目标 |
| Verifier | 对照契约校验 Artifact | 无限改写 |
| Replanner | 事实变化时创建 Plan Patch | 覆盖旧计划 |
6.1 Planner 输出不能直接执行
模型生成的计划可能存在:
- ID 重复;
- 依赖引用不存在;
- 环依赖;
- 工具未注册;
- 完成条件为空;
- 高风险步骤没有审批;
- 预算明显不够;
- 步骤超出 Goal Scope。
因此需要 Plan Validator:
def validate_plan(plan, capability_registry, budget):
issues = []
issues += check_unique_ids(plan)
issues += check_dependency_references(plan)
issues += check_acyclic_graph(plan)
issues += check_completion_criteria(plan)
issues += check_capabilities(plan, capability_registry)
issues += check_scope_boundaries(plan)
issues += check_approval_rules(plan)
issues += estimate_budget_feasibility(plan, budget)
return {
"passed": not has_blocking_issue(issues),
"issues": issues
}
6.2 Plan Version 与 Plan Patch
计划会因新事实而变化,但不能悄悄覆盖:
Plan v1:覆盖 12 个仓库
Plan v2:发现 1 个仓库无权限,调整验收范围
Plan v3:迁移文档版本冲突,增加权威来源确认任务
Plan Patch 至少记录基础版本、变更原因、支撑 Evidence、新增或修改的任务,以及需要保留的已完成 Work Item。这样既能调整计划,也不会丢失 W01、W02 等有效产物。
短暂超时通常只需重试,不需要重规划。只有范围、事实、能力或约束发生变化,使当前计划不再可执行时才需要 Replanner。
七、ReAct:把开放探索限制在局部任务中
ReAct 的基本闭环是:
Observation
→ Decision
→ Action
→ New Observation
工程上不需要展示模型的完整内部思维过程。系统只应保存足以审计的结构化决策摘要:
{
"decision_id": "decision-801",
"work_item_id": "W10",
"objective": "寻找 SDK 间接调用",
"observation_refs": ["obs-31", "obs-32"],
"selected_action": {
"tool": "search_code",
"arguments": {
"query": "PaymentGateway"
}
},
"reason_summary": "直接 SDK 搜索覆盖不足,继续定位内部封装类",
"remaining_steps": 3
}
7.1 受限循环
async def run_local_react(item, context):
observations = []
evidence_ids = []
for step in range(item.max_react_steps):
if context.pause_requested:
return partial_result("PAUSE_REQUESTED", observations)
if not context.budget.can_continue():
return partial_result("BUDGET_EXHAUSTED", observations)
decision = model.decide_next_action(
objective=item.description,
observations=compact(observations),
allowed_tools=item.allowed_tools,
)
if decision.type == "FINISH":
return build_artifact(observations, evidence_ids)
validate_action(decision, item.allowed_tools)
result = await tool_gateway.invoke(decision.tool_call, context)
observation = normalize_observation(result)
observations.append(observation)
evidence_ids.extend(observation.evidence_ids)
if no_progress_detected(observations):
return partial_result("NO_PROGRESS", observations)
return partial_result("STEP_LIMIT", observations)
7.2 无进展检测
满足任一条件就应停止:
- 连续两次结果哈希相同;
- 连续两步没有新增 Evidence;
- 重复提出已经失败的动作;
- 查询词只做无意义改写;
- 置信度没有提升但预算持续消耗。
7.3 ReAct 不适合什么
- 固定审批流程;
- 高风险副作用;
- 跨天长任务的全局调度;
- 可以用确定性程序完成的转换;
- 需要严格事务一致性的流程。
ReAct 是局部探索器,不是整个系统的操作系统。
八、Workflow 与 Agent:概率性判断要嵌入确定性骨架
一个稳健 Workflow 可以包含以下节点:
| 节点类型 | 示例 | 是否允许模型决定状态 |
|---|---|---|
| RULE | 预算检查、路由、状态守卫 | 否 |
| MODEL | 目标整理、风险解释、报告生成 | 只能返回建议 |
| TOOL | 查询仓库、获取文档 | 否 |
| VALIDATION | Schema、证据、覆盖率检查 | 否或受限 |
| HUMAN | 高风险审批、范围确认 | 由可信身份决定 |
| WAIT/TIMER | 等待回调、截止时间 | 否 |
| COMPENSATION | 撤销预留、标记失效 | 否 |
模型节点不应该直接:
- 修改 Workflow State;
- 跳过审批;
- 扩大工具权限;
- 覆盖历史 Artifact;
- 重置 Budget;
- 宣布高风险副作用成功。
节点契约应明确节点类型、输入 Artifact、输出 Schema、工具白名单、超时、调用预算和成功或失败后的路由。
节点只接收所需 Artifact,而不是整个对话历史。上下文越小,越容易测试、复现和控制成本。
九、工具执行:权限、重试和幂等必须统一治理
Executor 不应绕过 Tool Gateway 直接访问外部系统。
async def invoke_tool(call, context):
tool = registry.get(call.tool_name)
validate_schema(tool.input_schema, call.arguments)
authorize(context.principal, tool.permission, call.arguments)
enforce_goal_scope(context.goal.scope, call.arguments)
reserve_budget(context.budget, tool.estimated_cost)
safe_args = normalize_arguments(call.arguments)
idempotency_key = build_idempotency_key(context, call, safe_args)
try:
raw = await with_timeout(
tool.execute(safe_args, idempotency_key=idempotency_key),
seconds=tool.timeout_seconds,
)
result = validate_schema(tool.output_schema, raw)
result = truncate_and_redact(result, tool.max_result_bytes)
record_success(call, result)
return result
except Exception as error:
normalized = normalize_tool_error(error)
record_failure(call, normalized)
raise normalized
9.1 错误分类决定下一步
| 错误 | 通常处理 |
|---|---|
| TIMEOUT | 有界重试,结果未知时先对账 |
| RATE_LIMITED | 按 Retry-After 或退避重试 |
| SERVICE_UNAVAILABLE | 重试、熔断或备用来源 |
| PERMISSION_DENIED | 不盲目重试,记录缺口或接管 |
| INVALID_ARGUMENT | 修正参数后新 Attempt |
| SCHEMA_MISMATCH | 阻断并记录契约错误 |
| RESULT_TOO_LARGE | 分页、缩小查询或生成摘要 Artifact |
9.2 UNKNOWN_OUTCOME
超时只表示客户端没有及时收到结果,不代表外部动作失败。
对于发送消息、发布报告、创建工单等副作用:
调用超时
→ Attempt 标记 UNKNOWN_OUTCOME
→ 使用幂等键查询外部系统
→ 已成功则补记状态
→ 明确失败才允许重试
→ 无法判断则人工接管
这条规则可以避免最常见的重复副作用事故。
十、Reflection:检测、诊断、修正和重验不能混在一起
“让模型检查自己的答案” 过于宽泛。工程上的结果校验应分成四步:
Detection:发现问题
→ Diagnosis:定位原因
→ Repair:生成最小修正
→ Revalidation:重新执行全部必要校验
10.1 程序校验优先
确定性规则适合检查:
- JSON Schema;
- 必需章节;
- 数量一致性;
- Evidence 引用存在性;
- 仓库覆盖率;
- 重复 ID;
- 敏感字段;
- Artifact 哈希。
def verify_report(report, run_state):
issues = []
for section in REQUIRED_SECTIONS:
if section not in report.sections:
issues.append(issue("MISSING_SECTION", section))
if report.repository_count != run_state.analyzed_repository_count:
issues.append(issue("REPOSITORY_COUNT_MISMATCH"))
for claim in report.key_claims:
if not claim.evidence_ids:
issues.append(issue("CLAIM_WITHOUT_EVIDENCE", claim.id))
if contains_sensitive_content(report.content):
issues.append(issue("SENSITIVE_CONTENT"))
return issues
模型校验适合检查:
- 是否把推测写成事实;
- 结论是否真正被证据支持;
- 是否把相关性写成因果;
- 是否遗漏显著冲突;
- 建议是否回应用户目标。
10.2 Verification 不只是 PASS 和 FAIL
PASS:满足契约
FAIL:确定不满足,可以修正或终止
UNKNOWN:证据不足,无法可靠判断
UNKNOWN 不能被当成 PASS。
10.3 有限修正
def decide_after_verification(result, artifact):
if result.status == "PASS":
return "ACCEPT"
if result.has_security_issue:
return "HUMAN_HANDOFF"
if result.repairable and artifact.repair_count < 1:
return "REPAIR_ONCE"
if result.can_deliver_partial:
return "DEGRADED_DELIVERY"
return "HUMAN_HANDOFF"
无限 Reflection 会造成成本失控,还可能修复一个问题后引入另一个问题。自动修正必须有次数预算。
十一、Checkpoint、暂停和恢复
任务状态不能只存在进程内存或 Prompt 中。
11.1 Checkpoint 保存什么
{
"checkpoint_version": 23,
"run_id": "run-payment-001",
"workflow_state": "RUNNING",
"active_plan_version": 2,
"work_item_states": {
"W01": "SUCCEEDED",
"W02": "SUCCEEDED",
"W03": "SUCCEEDED",
"W09": "RUNNING"
},
"active_attempt_ids": ["attempt-W09-01"],
"artifact_ids": [
"goal:v1",
"repository-inventory:v1",
"migration-document-set:v1"
],
"budget": {
"used_tool_calls": 31,
"used_model_calls": 8,
"used_tokens": 42600,
"used_elapsed_seconds": 712
},
"saved_at": "2026-07-15T10:15:30+08:00"
}
至少在这些时机保存:
- Plan 创建或变更后;
- Work Item 开始前和结束后;
- Artifact 写入后;
- 进入暂停或人工等待前;
- 进入终态前。
11.2 暂停不是直接杀进程
RUNNING → PAUSING → PAUSED
PAUSING 阶段要停止启动新任务,让短调用安全结束,取消可取消的长调用,保存 Attempt 和 Checkpoint,再释放执行 Lease。
11.3 恢复前先对账
async def resume_run(run_id, principal):
checkpoint = checkpoint_store.load_latest_valid(run_id)
authorize_resume(principal, checkpoint)
lease = acquire_run_lease(run_id, principal)
reconcile_inflight_attempts(checkpoint)
verify_artifact_hashes(checkpoint.artifact_ids)
restore_remaining_budget(checkpoint.budget)
recompute_ready_items(checkpoint)
trace.append("RUN_RESUMED", run_id=run_id)
return scheduler.continue_run(run_id, lease)
恢复时不能重置预算,也不能直接把所有 RUNNING 任务改回 PENDING。应先根据幂等键、外部调用状态和 Artifact 证据判断它是否已经成功。
11.4 Lease 防止双重执行
同一个 Run 同时只能有一个有效 Lease。Worker 定期续租,状态写入携带 lease_version,旧 Lease 的提交必须被拒绝。
否则两个 Worker 可能同时恢复同一任务,产生重复调用、重复扣费和重复交付。
十二、会停止才是真正的可控 Agent
停止不是异常,而是一类正式结果。
| 状态 | 含义 |
|---|---|
| COMPLETED | 完整满足完成条件 |
| PARTIALLY_COMPLETED | 完成可交付子集,并明确缺口 |
| PAUSED | 已保存状态,等待恢复 |
| WAITING_FOR_HUMAN | 等待审批或决策 |
| FAILED | 已知无法完成且不能安全降级 |
| CANCELLED | 用户或上游明确取消 |
12.1 多维 Budget
不要只限制循环次数。完整 Budget 至少包括:
{
"max_elapsed_seconds": 2700,
"max_tool_calls": 120,
"max_model_calls": 35,
"max_tokens": 180000,
"max_total_attempts": 80,
"max_replans": 2,
"max_reflections_per_artifact": 1
}
启动 Work Item 前应预留预算。如果剩余工具调用只有 2 次,而任务预计需要 8 次,就不应启动后再半途失败。
12.2 无进展和重复失败
常见停止信号:
- 连续多步没有新增 Evidence;
- 相同输入重复调用相同工具;
- 相同错误连续出现;
- Plan 连续修改却没有新增可执行任务;
- Artifact 反复校验失败;
- 预算消耗但完成度不变。
12.3 Circuit Breaker
工具连续失败后,应避免所有任务一起制造重试风暴:
CLOSED:正常调用
→ 连续失败达到阈值
OPEN:快速失败,暂不调用
→ 冷却时间结束
HALF_OPEN:允许少量探测
→ 成功回到 CLOSED,失败回到 OPEN
Circuit Breaker 是工具级可靠性控制,不能替代单次 Attempt 的重试策略。
十三、证据不足时,降级比编造更有价值
一个成熟系统应提供降级阶梯:
完整报告
→ 缺少部分仓库的报告
→ 只输出事实清单和风险候选
→ 只输出已完成 Artifact 索引
→ 生成 Handoff Package
→ 安全失败
部分结果必须标明:
- 原目标;
- 已完成范围;
- 未完成范围;
- 降级原因;
- 已验证结论;
- 不可下结论的部分;
- 继续所需条件;
- 已消耗预算。
例如 12 个仓库中只有 7 个可访问,不能写成 “迁移调研已经完成,只缺少少量信息”。覆盖缺口本身就是交付结果的一部分。
13.1 Evidence Sufficiency
风险等级和置信度必须分开:
| 风险 | 置信度 | 处理 |
|---|---|---|
| 高 | 高 | 明确提示风险并进入审批 |
| 高 | 低 | 标记未知,人工确认 |
| 低 | 高 | 可以形成低风险结论 |
| 低 | 低 | 不能声称安全 |
“没有发现风险” 只说明搜索没有找到,不等于 “风险很低”。
十四、人工接管不是失败,而是控制权协议
以下情况通常需要接管:
- 高风险低置信度;
- 权威来源冲突;
- 同一工具多次失败;
- 权限缺失导致范围不足;
- 两次重规划后仍不可执行;
- 非幂等调用结果未知;
- 安全策略发现敏感信息;
- 用户主动暂停或接管。
14.1 Handoff Package
| 字段 | 内容 |
|---|---|
| 原因 | 结构化 Reason Code 和人类可读说明 |
| 当前状态 | Goal、Plan Version、已完成和阻塞任务 |
| 尝试历史 | Attempt 次数、参数变化和最后错误 |
| 证据 | 相关 Artifact 与 Evidence 引用 |
| 决策选项 | 授权后继续、接受部分范围或取消 |
| 恢复信息 | Budget 快照、Checkpoint 和 Resume Point |
好的接管问题应说明:发生了什么、已经尝试什么、影响范围、可选方案和每个方案的后果。
接管前 Agent 应停止启动新任务、保存 Checkpoint、释放 Lease,再把控制权交给可信的人类身份。人工决定本身也要进入审计记录。
十五、贯穿案例:Payment SDK 迁移调研助手
15.1 初始计划
| Milestone | Work Item 摘要 |
|---|---|
| M1 范围确认 | 规范化目标、获取仓库与文档、校验实际范围 |
| M2 迁移知识 | 搜索权威文档、抽取破坏性变更、校验版本 |
| M3 代码分析 | 搜索依赖和直接调用、用局部 ReAct 找封装层、校验覆盖率 |
| M4 风险分析 | 关联变化、分析测试缺口、规则打分、语义复核 |
| M5 报告交付 | 生成迁移顺序和报告、双层校验、有限修正、人工审批 |
15.2 正常执行
系统发现 12 个仓库,其中 11 个可访问。文档侧找到官方迁移指南和 v2 发布说明,抽取出 8 项破坏性变更。代码搜索识别 37 个直接或间接调用点,规则计算出 3 个高风险模块和 5 个中风险模块。
报告 v1 的确定性校验发现一项高风险结论缺少 Evidence,语义校验发现一个迁移顺序建议表达过度确定。系统执行一次有限修正,生成报告 v2,并再次运行全部必要校验。
最终状态:
{
"status": "COMPLETED",
"completion_mode": "DEGRADED",
"plan_version": 2,
"coverage": {
"expected": 12,
"accessible": 11,
"analyzed": 11
},
"unresolved_issues": [
"billing-worker 仓库无访问权限"
],
"final_artifact": "migration-assessment:v2"
}
15.3 工具连续失败
如果文档搜索服务连续三次超时:
错误分类
→ 指数退避重试
→ 重试耗尽
→ Circuit Breaker OPEN
→ 查询已审核缓存或备用只读来源
→ 仍无结果则生成 Handoff Package
系统不能使用模型记忆编造迁移规则,也不能擅自扩展到未授权互联网来源。
15.4 预算耗尽
如果任务在测试缺口分析时耗尽工具预算,系统应保留仓库清单、文档变更和 API 使用清单,只交付已确认事实,不生成未经校验的最终风险排名,并给出继续执行所需的预算估算。
15.5 暂停与恢复
用户请求暂停
→ 不再启动新 Work Item
→ 当前工具调用到安全点
→ 保存 Artifact 和 Checkpoint
→ Run 进入 PAUSED
用户恢复
→ 获取 Lease
→ 加载最新有效 Checkpoint
→ 对账运行中 Attempt
→ 校验 Artifact 哈希
→ 恢复剩余 Budget
→ 从 Ready Work Item 继续
已经成功的仓库搜索不会重复执行。
十六、后端实现参考
推荐组件边界:
API / Command Handler
├─ Goal Service
├─ Planning Service
│ ├─ Planner
│ ├─ Plan Validator
│ └─ Replanner
├─ Workflow Runtime
│ ├─ Scheduler
│ ├─ Executor
│ └─ State Guard
├─ Tool Gateway
├─ Verification Service
├─ Artifact Store
├─ Checkpoint Store
├─ Budget & Termination Service
├─ Handoff Service
└─ Trace / Metrics
主循环可以保持简单:
async def run_agent(run_id):
state = run_store.load(run_id)
while not state.is_terminal:
lease_service.renew(state.run_id)
control = termination_service.evaluate(state)
if control.action != "CONTINUE":
return await handle_control_action(state, control)
ready_items = scheduler.find_ready_items(state)
if not ready_items:
resolution = resolve_no_ready_items(state)
if resolution == "VERIFY":
await verifier.verify_run(state)
elif resolution == "REPLAN":
await replanner.create_patch(state)
elif resolution == "COMPLETE":
await delivery_service.finalize(state)
else:
await handoff_service.create(state, "NO_RUNNABLE_WORK")
state = run_store.load(run_id)
continue
batch = scheduler.select_batch(ready_items, max_parallel=4)
results = await executor.execute_batch(batch, state)
run_store.persist_results_atomically(results, state)
checkpoint_store.save(state)
state = run_store.load(run_id)
return run_store.build_summary(run_id)
注意这里没有:
while model_says_continue:
...
是否继续由状态、依赖、预算、策略和用户意图共同决定。
第一版可以使用单体服务、PostgreSQL、数据库任务队列和对象存储。先证明状态语义、幂等与恢复,再考虑分布式 Workflow 引擎和大规模并行调度。
十七、可观测性:不仅看调用成功率,还要看任务是否前进
Trace 层级可以设计为:
Run Span
Plan Span
Milestone Span
Work Item Span
Attempt Span
Model Call Span
Tool Call Span
Verification Span
关键事件包括 Run 创建、Goal 规范化、Plan 创建与校验、Attempt 开始、模型决策、工具成功或失败、Artifact 创建、Verification 完成、Plan Patch、暂停恢复、Budget 阈值、Handoff、人工决定以及各类终态。
推荐指标:
| 维度 | 关键指标 |
|---|---|
| 规划质量 | Plan 首次校验通过率、平均重规划次数、环依赖拦截数 |
| 执行效率 | Work Item 成功率、关键路径耗时、并行度、重复调用率 |
| 工具可靠性 | 超时率、重试成功率、熔断次数、UNKNOWN_OUTCOME 对账时间 |
| 结果质量 | Verification 通过率、无 Evidence 结论数、修正后回归失败率 |
| 恢复能力 | Checkpoint 恢复成功率、重复副作用数、双 Worker 拦截数 |
| 控制能力 | Budget 超限数、无进展停止数、降级率、人工接管率 |
Trace 不应复制完整敏感文档或模型内部思维过程。优先记录 ID、版本、哈希、原因码、决策摘要和 Evidence 引用。
十八、测试:异常路径比 Happy Path 更重要
| 测试域 | 必测行为 |
|---|---|
| Goal 与 Plan | 范围完整;依赖无环;未知工具被拒绝;高风险任务有审批 |
| Scheduler | 依赖满足后才运行;并发受限;老任务不饥饿 |
| Tool Gateway | 权限前置;可恢复错误重试;权限错误不重试;结果受限和脱敏 |
| ReAct | 工具白名单;最多 5 步;无进展终止;部分结果可保存 |
| Verification | 缺章节、缺 Evidence、数字冲突、敏感信息都被发现 |
| Reflection | 最多修正一次;修正产生新 Artifact;重验覆盖必要规则 |
| Checkpoint | 重启后不重复成功任务;运行中 Attempt 先对账 |
| Budget | 恢复不重置预算;预算不足时不启动大任务;可降级交付 |
| Handoff | 包含状态、尝试、证据、选项和恢复点;人工决定可审计 |
| 安全 | 提示注入不改变工具权限;跨租户访问为零 |
练习项目可以设置以下硬门槛:
非法状态转换成功次数 = 0
未授权工具调用次数 = 0
重复副作用次数 = 0
高风险无 Evidence 交付次数 = 0
预算重置次数 = 0
双 Worker 同时执行次数 = 0
无限 ReAct 或 Reflection 次数 = 0
暂停恢复正确率 = 100%
故障注入至少覆盖:
- 工具超时一次后恢复;
- 工具连续失败三次;
- 仓库权限拒绝;
- Planner 生成环依赖;
- ReAct 重复相同搜索;
- 报告缺少 Evidence;
- Budget 中途耗尽;
- 工具成功后、Checkpoint 前崩溃;
- 两个 Worker 同时恢复;
- 文档中包含提示注入;
- 两个权威来源冲突;
- 高风险但低置信度。
十九、常见故障与定位
| 故障 | 主要原因 | 修复方向 |
|---|---|---|
| Agent 一直循环 | 没有步数、预算和无进展检测 | 使用局部 ReAct,增加多维 Budget 和停止原因 |
| 计划执行到一半才发现工具不存在 | Planner 输出直接执行 | 增加 Capability Registry 和 Plan Validator |
| 恢复后重复调用 | 只保存当前步骤名 | Attempt、幂等键、Artifact 和外部状态对账 |
| 一个任务失败导致全部重跑 | 没有 Plan Version 和产物复用 | 使用 Plan Patch,保留成功 Work Item |
| 报告结论无法解释 | 没有 Evidence 数据模型 | 结论、Artifact 与 Evidence 建立引用 |
| Reflection 反复改写 | 没有修正次数和验收契约 | Verification Contract、最小 Repair、全量重验 |
| 权限错误重复重试 | 所有异常使用同一策略 | 错误分类,永久错误直接阻断或接管 |
| 预算耗尽仍宣称完成 | 没有 Completion Mode | 使用 PARTIALLY_COMPLETED 和降级报告 |
| 两个 Worker 重复执行 | 没有 Lease 和版本守卫 | Run Lease、心跳和乐观锁 |
| 人工接管后无法继续 | 只发送错误消息 | 生成结构化 Handoff Package 和 Resume Point |
| 搜索为空就判断无风险 | 把缺少证据当成低风险 | 区分 Risk 与 Confidence,允许 UNKNOWN |
| 文档提示改变了 Agent 行为 | 把外部内容当系统指令 | 数据与指令隔离,工具权限由 Gateway 控制 |
二十、推荐实现顺序
- 定义 Goal、Plan、Work Item、Attempt、Artifact、Evidence 和 Run State;
- 实现确定性状态机和非法转换守卫;
- 使用固定 Plan 跑通 Scheduler、Executor 和 Artifact Store;
- 实现 Plan Validator,覆盖依赖、能力、范围和预算检查;
- 用 Fixture 构造仓库、文档、超时和权限错误;
- 接入 Planner,但所有输出先做 Schema 和计划校验;
- 只在少数开放任务中加入有界 ReAct;
- 先实现程序校验,再增加证据驱动的语义 Reflection;
- 加入 Checkpoint、幂等、UNKNOWN_OUTCOME 对账和 Lease;
- 加入多维 Budget、无进展检测、熔断和终止记录;
- 实现降级交付和 Handoff Package;
- 补齐 Trace、指标和故障注入测试。
不要一开始就引入多个 Agent、分布式消息队列和复杂图编排。先用单体和固定 Fixture 证明:状态能恢复、调用不重复、结果有证据、预算会生效、失败能安全停止。
二十一、总结
可靠的 Agent 规划与执行系统,不是 “让模型自主完成一切”,而是把自主判断限制在明确、可观察、可停止的边界中。
需要记住的核心原则:
- 复杂任务不是把单轮 Agent 循环得更久;
- 先建立 Goal Contract,再生成执行步骤;
- Goal、Milestone 和 Work Item 分层,计划使用 DAG 表达依赖;
- Work Item、Attempt、Artifact 和 Evidence 必须分离;
- Planner 输出必须经过确定性 Plan Validator;
- Plan 变化要创建新版本,不能覆盖历史;
- Workflow 管全局,ReAct 只处理局部不确定性;
- 模型负责语义判断,程序负责状态、权限和预算;
- Reflection 要分成检测、诊断、修正和重验;
- Checkpoint、幂等和 Lease 是暂停恢复的基础;
- Budget、无进展和 Circuit Breaker 决定系统能否安全停止;
- 证据不足时应降级或接管,不能为了完成而编造;
- Handoff 是正式控制权协议,不是一句 “请人工处理”;
- 只有通过崩溃、并发、越权和预算测试,才能证明任务真正可控。
完整闭环可以压缩为:
用户目标
→ Goal Contract
→ Plan 与 Plan Validator
→ Scheduler 按依赖调度
→ Executor 通过 Tool Gateway 执行
→ Attempt、Artifact 与 Evidence 持久化
→ Verification 与有限 Reflection
→ Checkpoint 与 Plan Version
→ Budget、无进展和终止判断
→ 完整交付、降级交付或 Human Handoff
→ Trace、审计和持续评估
当这条链路建立起来后,Agent 才不只是 “能够连续调用工具”,而是能在任务复杂、环境变化、服务失败、预算有限和人类介入时,仍然保持状态一致、结果可验证、过程可恢复、风险可控制。

更多推荐



所有评论(0)