需求拆解中的防扩散设计:如何限制 Agent 的上下文边界
在构建用于自动化软件研发的自主 Agent(如自主修复 Bug、端到端重构或全自动特性开发)时,最棘手的问题往往不是大模型的单步推理能力不足,而是多步循环推理过程中的“上下文发散(Context Explosion)”与“目标漂移(Goal Drift)”。
当一个 Agent 面对宏观需求(例如“将订单服务从同步 HTTP 改造为异步事件总线驱动”)时,如果没有严格的上下文边界防扩散控制,Agent 在递归拆解子任务的过程中会过度检索关联代码,将不相关的辅助工具类、旧历史提交和无关配置通通塞进上下文窗口。最终导致 Prompt 膨胀触顶、幻觉倍增,甚至擅自修改无关目录的文件。
构建一套“防扩散(Anti-Sprawl)”架构,是让软件研发 Agent 能够稳定交付生产级代码的核心工程保障。
上下文扩散的三大病理特征
防扩散架构:四重隔离防火墙
为了将 Agent 限制在受控的边界内,我们设计了四层上下文隔离模型:
┌───────────────────────────────────────┐
│ Planner Agent (战略规划层) │ ── 仅维护全局目标与 DAG 拓扑
└───────────────────┬───────────────────┘
│ 分发原子子任务 (仅限单节点元数据)
▼
┌───────────────────────────────────────┐
│ Sub-Task Scope Firewall (防火墙) │ ── 强制裁剪上下文,拦截越界读写
└───────────────────┬───────────────────┘
│ 纯净上下文 + 沙箱环境
▼
┌───────────────────────────────────────┐
│ Worker Agent (战术执行层) │ ── 专注当前单个函数的实现与单测
└───────────────────┬───────────────────┘
│ 结构化输出结果 (Schema Enforced)
▼
┌───────────────────────────────────────┐
│ State Reducer (状态归集器) │ ── 仅提取 Diff 与 Summary,丢弃中间废话
└───────────────────────────────────────┘
1. 任务静态切分与 DAG 拓扑化(DAG Decomposition)
顶层规划器(Planner)被严格剥夺了直接编写代码的权限,它的唯一职责是将总目标拆解为有向无环图(DAG),并为每个节点显式划定“只读白名单(Read Scope)”和“可写白名单(Write Scope)”。
{
"task_id": "sub_task_03",
"name": "实现 OrderCreatedEvent 消息发布逻辑",
"dependencies": ["sub_task_01", "sub_task_02"],
"write_scope": [
"internal/service/order_service.go",
"internal/service/order_service_test.go"
],
"read_scope": [
"internal/event/order_event.go",
"internal/repository/order_repo.go"
],
"token_budget": 12000,
"max_tool_calls": 8
}
2. 沙箱路径隔离与文件系统权限拦截
在执行子任务时,工作 Agent 的文件系统访问工具必须经过代理中间件(Proxy Middleware),严禁扫描或读取白名单之外的文件:
from typing import List
import os
class ScopeViolationError(PermissionError):
pass
class ScopedFileSystem:
"""
带边界防火墙的文件系统代理,拦截越界读写与上下文发散
"""
def __init__(self, allowed_reads: List[str], allowed_writes: List[str], workspace_root: str):
self.allowed_reads = [os.path.abspath(os.path.join(workspace_root, p)) for p in allowed_reads]
self.allowed_writes = [os.path.abspath(os.path.join(workspace_root, p)) for p in allowed_writes]
self.workspace_root = workspace_root
def read_file(self, rel_path: str) -> str:
abs_path = os.path.abspath(os.path.join(self.workspace_root, rel_path))
# 检查是否在允许的只读或可写作用域内
is_allowed = any(abs_path.startswith(p) for p in self.allowed_reads + self.allowed_writes)
if not is_allowed:
raise ScopeViolationError(
f"[权限拦截] 尝试读取超出任务边界的文件: {rel_path}。当前子任务仅允许访问声明的文件列表。"
)
with open(abs_path, 'r', encoding='utf-8') as f:
return f.read()
def write_file(self, rel_path: str, content: str) -> None:
abs_path = os.path.abspath(os.path.join(self.workspace_root, rel_path))
# 严格检查可写范围
is_allowed = any(abs_path == p or abs_path.startswith(p + "/") for p in self.allowed_writes)
if not is_allowed:
raise ScopeViolationError(
f"[越界拦截] 尝试修改非白名单文件: {rel_path}。请仅在当前任务授权的文件范围内修改代码。"
)
os.makedirs(os.path.dirname(abs_path), exist_ok=True)
with open(abs_path, 'w', encoding='utf-8') as f:
f.write(content)
3. 上下文状态重置(Context Reset & State Distillation)
子任务之间绝不共享全量对话历史(Chat History)。每个子任务启动时,其 Context 都是一个全新初始化(Clean Slate)的状态:
- 注入:当前子任务的目标、相关接口声明(Stub)、父任务产出的结构化摘要。
- 丢弃:上一个子任务中经历的 10 次报错重试过程、庞大的标准输出。
def build_clean_subtask_prompt(task_node, upstream_summaries: dict) -> list:
return [
{
"role": "system",
"content": "你是一个专注的单模块实现专家。仅针对给定目标编写代码与单测,禁止修改未授权文件。"
},
{
"role": "user",
"content": f"""
【当前子任务】: {task_node.name}
【依赖任务摘要】: {upstream_summaries.get(task_node.dependencies[0], '无')}
【只读依赖契约】:
{task_node.get_stub_definitions()}
请仅输出针对 {task_node.write_scope} 的具体修改代码。
"""
}
]
生产实践收益
在某大型支付系统的重构实践中,引入防扩散上下文边界控制机制前后,Agent 系统的各项指标对比显著:
| 单任务平均 Token 消耗 | 148,000 Tokens | 21,500 Tokens | 算力消耗降低 85.5% |
| 跨模块误改引发的回归 Bug | 34% 的 PR 存在误改 | 0% (被沙箱物理拦截) | 杜绝越界代码污染 |
| 复杂长任务完成率 (Task Success Rate) | 41.2% (常因窗口爆炸崩溃) | 89.6% | 交付成功率翻倍 |
限制 Agent 上下文的自由度,看似约束了模型的自主性,实则是保证工程确定性与商业可用性的唯一路径。



