任务委派
wescode 中的 delegate_task 工具——子 Agent 委派、Actor 传播与安全模型。
delegate_task 工具
delegate_task 允许主 Agent 将子任务委派给独立的子 Agent 执行:
{
"tool": "delegate_task",
"goal": "为 UserService 编写单元测试",
"context": "UserService 位于 internal/service/user.go,有 12 个公开方法",
"toolsets": ["terminal", "file"]
}
治理分类
delegate_task 被归类为 ZoneRed(INV-GOV-03)——子 Agent 启动必须经过完整审计。这是最高安全级别,因为子 Agent 拥有独立的工具执行能力。
委派模式
同步委派(默认)
主 Agent 等待子 Agent 完成后继续:
{
"tool": "delegate_task",
"goal": "分析 API 响应时间",
"context": "关注 P95 延迟"
}
// → 主 Agent 阻塞等待
// → 子 Agent 执行并返回摘要
// → 主 Agent 继续
背景委派
{
"tool": "delegate_task",
"goal": "运行完整测试套件并报告结果",
"background": true
}
// → 主 Agent 立即获得 delegation id
// → 子 Agent 后台执行
// → 结果通过 async-delegation 完成队列回到对话
重要:背景委派是进程内异步,不是跨进程持久化。进程重启后丢失。需要持久化的工作应使用 cronjob 或 terminal(background=true)。
批量委派
{
"tool": "delegate_task",
"tasks": [
{"goal": "为 UserService 写测试", "context": "..."},
{"goal": "为 OrderService 写测试", "context": "..."},
{"goal": "为 PaymentService 写测试", "context": "..."}
]
}
// → 三个子 Agent 并发执行
// → 并发上限 delegation.max_concurrent_children(默认 3)
Actor 传播
核心规则
子 Run 必须继承父 Run 的 Actor:
// internal/agent/tool.go
// 同时写入 Actor 一等字段和 Tags["actor"]
pp.Actor = tc.Actor // ← 一等字段
pp.Tags["actor"] = tc.Actor // ← Tags 同步
防御性继承
// runner.go
// 子 actor 为空时从父 Run 继承
if childParams.Actor == "" {
childParams.Actor = parentParams.Actor
}
为什么必须传播
如果子 Run 没有 Actor:
- 记忆写入静默失败(
RequireActor) - Run 记录在 owner 收口后不可见(INV-OBS-10:无主 = 隐藏)
"我不知道这是谁的"的安全读法是隐藏,不是公开
CycleDetect 覆盖
委派的子 Run 可以使用更严格的循环检测阈值:
{
"tool": "delegate_task",
"goal": "修复 Bug #123",
"cycle_detect_override": {
"action_term_threshold": 40,
"identical_call_term_threshold": 5
}
}
为什么需要覆盖
| 场景 | 主 Run | 子 Run |
|---|---|---|
| 大型重构 | 宽松阈值(50 action) | - |
| 子任务:修 bug | - | 严格阈值(40 action) |
子 Run 的任务更聚焦,较低的阈值可以更快检测死循环。
委派与记忆
记忆继承
子 Run 继承父 Run 的 Actor,因此可以访问:
| 记忆层 | 子 Run 可见 | 说明 |
|---|---|---|
| L3 关于我 | ✅ | 同一 Actor 的个人记忆 |
| L4 角色记忆 | ✅ | 同一 Agent 命名空间 |
| L1 环境 | ✅ | Cell 级共享 |
| L2 共识 | ✅ | Cell 级共享 |
子 Run 的记忆写入
子 Run 可以写入记忆(经过标准管道),写入的 Actor 来自继承:
子 Run 写入 memory(save, "发现 X 模块有循环依赖")
→ Actor = 继承的 "local"
→ 所有标准管道(威胁扫描 / 质量门控 / WriteGate)
→ 写入成功
委派与观测
子 Run 必须有 owner(INV-OBS-10)
子 Run 的 owner = 继承的 Actor
有 owner → 该 Actor 可以在观测面看到子 Run
无 owner → 隐藏(不可见)
可见性规则
GET /cells/{id}/observe/runs?actor=local
→ 返回 local 发起的所有 Run
→ 包括 local 发起的委派子 Run
→ 不包括无主 Run(被隐藏)
多层委派
max_spawn_depth 限制
委派可以嵌套,但有深度限制:
delegation.max_spawn_depth: 2(默认)
主 Agent → 子 Agent(depth=1)→ 孙 Agent(depth=2)→ ❌ 达到上限
角色分类
| 角色 | 是否能 delegate | 限制 |
|---|---|---|
leaf(默认) | ❌ | 不能调 delegate_task |
orchestrator | ✅ | 受 max_spawn_depth 限制 |
orchestrator 角色需要 delegation.orchestrator_enabled=true(默认开启)。
配置参数
| 参数 | 默认值 | 说明 |
|---|---|---|
max_concurrent_children | 3 | 批量委派最大并发数 |
max_spawn_depth | 2 | 嵌套委派最大深度 |
child_timeout_seconds | - | 子 Agent 超时 |
orchestrator_enabled | true | 是否允许 orchestrator 角色 |
subagent_auto_approve | - | 子 Agent 自动批准 |
inherit_mcp_toolsets | - | 继承 MCP 工具集 |
max_iterations | - | 子 Agent 最大迭代数 |
子 Run 的工具集
leaf 角色
leaf 子 Agent 是聚焦的工作者,不能访问:
delegate_task(不能再委派)clarify(不能向用户提问)memory(不能写记忆)send_message(不能发消息)
orchestrator 角色
orchestrator 保留 delegate_task,可以继续委派子任务。
安全注意事项
- ZoneRed 审计:每次委派都有完整审计记录
- Actor 不可伪造:子 Run 的 Actor 从父 Run 继承,不由子 Agent 指定
- 进程内执行:子 Agent 在同一进程中运行,共享 Cell 治理策略
- 不持久化:背景委派不跨进程重启
最佳实践
- 明确 goal 和 context:给子 Agent 足够信息
- 使用 toolsets 限制工具:减少子 Agent 的攻击面
- 合理设置深度:大多数场景不需要超过 2 层
- 优先使用同步委派:除非任务独立且耗时长