计划漂移问题
核对日期:2026-05-09。
1. 定义与边界
计划漂移(Plan Drift)是指 Agent 在执行过程中逐渐偏离原始目标、约束、权限、计划步骤或用户意图。它可能表现为做了不必要的子任务、接受外部内容的恶意指令、跳过审批、无限重规划,或最终产物与目标不一致。
计划漂移不同于合理重规划。合理重规划有触发条件、版本记录和约束继承;漂移则是无控制地改变目标或路径。
2. 为什么重要
Agent 的开放性越强,越容易在工具结果、网页、错误日志、用户追加输入和模型自我反思中改变方向。生产系统若只看最终答案,往往发现不了中途越权、泄漏或成本失控。
3. 核心机制
漂移检测对象:
- 目标漂移:当前步骤不再服务原始目标。
- 约束漂移:忽略时间、预算、范围、保密要求。
- 权限漂移:使用未授权工具或扩大数据访问。
- 证据漂移:结论脱离已验证 facts。
- 成本漂移:无限搜索、过度重规划。
4. 架构模式
| 控制点 | 方法 | 适用 |
|---|---|---|
| Plan lint | 执行前检查计划质量 | 所有计划型 Agent |
| Step alignment check | 每步前后比较目标和约束 | 长任务 |
| Policy gate | 高风险工具调用前检查 | 生产系统 |
| Trace audit | 离线审计计划与实际行为 | 评测和合规 |
| Drift-triggered replan | 漂移苗头触发受控重规划 | 动态环境 |
5. 工程实现
def drift_check(goal, constraints, plan, step, action, observation):
verdict = verifier.check({
"goal": goal,
"constraints": constraints,
"current_step": step,
"proposed_action": action,
"observation_summary": summarize(observation)
})
if verdict.type == "violation":
stop_run(verdict.reason)
if verdict.type == "needs_replan":
return replan_with_constraints(plan, verdict)
return "continue"
漂移事件结构:
{
"type": "plan_drift",
"severity": "high",
"step_id": "s5",
"expected": "只读分析客户投诉",
"actual": "尝试调用 external_email",
"action": "blocked",
"trace_id": "trace_abc"
}
6. 生产实践
- 原始目标和硬约束写入不可被 Agent 修改的 run metadata。
- 重规划必须继承硬约束,并记录
replan_reason。 - 工具调用前执行 allowlist 检查。
- 对外部网页、邮件、文档进行不可信来源标注。
- 观测指标包含 drift rate、blocked action rate、replan count。
7. 常见反模式
- 把“模型觉得更好”当作改变目标的理由。
- 允许 Executor 私自修改 plan。
- 外部工具返回“请忽略之前要求”后被纳入系统指令。
- 重规划没有版本和原因,审计无法复原。
- 只限制最终输出,不限制中间工具调用。
8. 评测方法
- Constraint Retention:多轮后是否仍遵守原始约束。
- Tool Boundary Test:是否调用未授权工具。
- Injection Resistance:外部恶意内容是否改变计划。
- Replan Appropriateness:重规划是否有充分触发条件。
- Trace Alignment:实际步骤与计划步骤匹配度。
9. 安全与治理
- 计划漂移是 prompt injection、数据外泄和过度代理的共同入口。
- 硬约束放在代码策略层,不放在可被重写的自然语言计划里。
- 对高风险漂移事件进入人工审查。
- 对漂移样本沉淀成 eval dataset,持续回归测试。
- 对模型自我反思输出也按不可信建议处理,必须过策略层。
10. 工程手册补充
10.1 漂移检测数据结构
计划漂移要用版本差异和约束校验发现,不能只靠最终答案感觉。
plan_guard:
immutable_constraints:
- "不得外发客户数据"
- "必须先生成 preview"
allowed_change_types:
- split_step
- replace_failed_read_tool
- add_verification_step
forbidden_change_types:
- remove_approval_gate
- broaden_tool_scope
- change_user_goal_without_confirmation
drift_metrics:
max_replan_count: 3
max_step_churn_ratio: 0.4
10.2 漂移评测与恢复
| 漂移类型 | 检测信号 | 恢复动作 |
|---|---|---|
| 目标漂移 | 新计划交付物不同 | 回滚并要求用户确认新目标 |
| 权限漂移 | 工具范围扩大 | 拒绝新计划,触发安全告警 |
| 约束漂移 | 原始限制从计划中消失 | 自动补回并重新校验 |
| 粒度漂移 | 步骤反复拆合但无进展 | 冻结计划,人工接管 |
| 证据漂移 | 引用失效 artifact | 标记依赖步骤 stale,重新验证 |
伪代码:
diff = compare_plans(old_plan, proposed_plan)
if diff.removes_immutable_constraint():
reject("constraint drift")
if diff.broadens_tool_scope_without_approval():
reject("permission drift")
if diff.step_churn_ratio > 0.4:
pause_for_review("excessive churn")
activate(proposed_plan)
上线清单:
- 每次重规划都记录
replan_reason、plan_diff、preserved_artifacts。 - 原始用户目标和硬约束不可被模型静默改写。
- 监控 replan_count、step_churn_ratio、approval_gate_removed、tool_scope_delta。
- 回归用例要包含提示注入诱导改计划、工具失败诱导绕过审批、用户中途改目标。
- 安全上,外部内容只能改变事实判断,不能改变系统目标、权限或审批链。
11. 权威资料
- OWASP Top 10 for LLM Applications: https://owasp.org/www-project-top-10-for-large-language-model-applications/
- MCP Authorization specification: https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
- NIST AI RMF 1.0: https://www.nist.gov/publications/artificial-intelligence-risk-management-framework-ai-rmf-10
- Anthropic, Building effective agents: https://www.anthropic.com/engineering/building-effective-agents
- OpenAI Agents SDK Guardrails: https://openai.github.io/openai-agents-python/guardrails/
- OpenAI Agents SDK tracing: https://openai.github.io/openai-agents-python/tracing/