Files
Agent-System-Documents/docs/guides/squad-and-subagents.md
T
weichen 4ce8155161 Expand guides with worked examples for intents, runs, and squads
Why: 补充实例让导览可对照实操:意图打分/填槽/多意图裁决给出
intentctl explain 实测轨迹(含样例意图、歧义、优先级 tie-break、
能力目录),任务执行给出工具清单与典型回合走查(含 ClaimGate
三类拦截),小队给出 agent-squad demo 全流程实测与真实工作区
目录树/TASK.md 实拍;并修正事实:默认意图目录为空、插件 overlay
与 registry loader 两种文件形态不同。

Evidence: intentctl explain/catalog 与 agent-squad demo 为 2026-10-08
本地实测输出(命令见各节);锚点仍为 Dev R0 218fc4b1;git diff
--check 通过;五篇互链全部可解析。SRC=SELF。

Impact: 仅文档增补(02/03/04/05 四篇),无代码影响。

Refs: Dev 任务分支 feature/architecture-guides。
2026-10-08 09:33:13 +00:00

8.6 KiB
Raw Blame History

何时启动小队或子 Agent:触发条件与调用链

基准:Agent-System-Dev 组合 218fc4b1ba00b0a03b5bb79f292b3eba6c987a58(R0,2026-10-08 锚点核验)。 行号为该提交下的函数入口位置(个别内部区段为约略范围),随代码演进漂移;文件与函数名是稳定锚点。 internal/ 指 modules/backend/internal/。


1. 一句话结论

系统有两条"委派"线,都发生在普通 run 的执行过程中(小队不是独立的一层):

  • 子代理(sub-agent):模型在回合中调用 delegate_task 工具 → runmgr 派生 Kind=subagent 的子 run(任务树)。
  • 小队(squad):三条触发路径 —— ① 设置 runtime.entry=squad 让对话本身 走 SquadRunner;② 模型调用 squad_orchestrate 工具;③ 演示消息含 #squad。 三者最终都汇入 deps/agent-squad 引擎。成员执行统一走 agent-native 内核 (legacy 的 agent-system 子 run 压缩路径已退役,internal/squadadapter/adapter.go:289-292 注释明示;后端缺席时 fail-closed,不静默降级)。

另有第三种"规划委派":run_workflow 触发的规划子代理(workflowPlannerID), 见任务规划与执行第 7 节。


2. 子代理:delegate_task 触发链

触发条件

主对话模型判断某段工作适合独立完成(如长调研、批量整理)时,在 ReAct 循环里发出 delegate_task 工具调用(工具名常量 internal/runtime/llm.go:58)。工具声明与门禁在 internal/runtime/llm.go:267-315(编排型工具随上下文声明;子代理 spec 由 prompts 包提供 tools/model/maxTurns 约束,禁止子代理再持有派发类工具,internal/prompts/service.go)。

调用链

# 步骤 位置
1 内核循环解析出 delegate_task 调用 → runTool 分派 internal/runtime/llm_direct.go:471 runTool,case 在 :493 起
2 后台模式:经 rc 端口断言调 SpawnBackground;前台:SpawnAgent llm_direct.go:502, 516 附近
3 runmgr 派生子 run internal/runmgr/runmgr.go:1348 spawnSubagent → :1358 startChild(深度检查在此,注释 :1356)
4 建 Kind=subagent 子 run,ParentRunID 指向父 run(任务树) runmgr.go startChild 内;契约 modules/core/model.go:188
5 发 agent.spawn 事件(前端 AgentTracker 可见) runmgr.go:1375
6 独立 ctx 执行(后台模式 detach) runmgr.go startChild 内
7 子代理执行器 = SubLLMRunner.Execute —— 同样进入 nruntime.Run 内核循环(独立转录、按子代理 spec 收窄工具) internal/runtime/sub_loop.go:31
8 完成回填 AgentResultPayload;结果截断 32000 字 runmgr.go:1401 finishChild;runmgr.go:1780 capSubagentResult

后台子代理

  • delegate_task 可请求后台模式 → spawnBackground(runmgr.go:1475), 每会话上限 3 个(runmgr.go 常量)。
  • 后台子代理完成后不直接打扰当前回合,而是进通知队列:deliverNotices (runmgr.go:1560)在会话空闲时以 system-reminder 消息启动一个新父回合汇报结果 (startNoticeRun,runmgr.go:1616)。
  • 取消级联:子 run 的 ctx 派生自父 run,CancelRun(runmgr.go:1222)取消根 run 即级联取消全部子 run。

3. 小队:三条触发路径

路径 A:squad_orchestrate 工具调用(工具路径)

# 步骤 位置
A1 模型在回合中调用 squad_orchestrate goal=... 工具名常量 internal/runtime/llm.go:62;声明 llm.go:268 附近
A2 声明门禁:settings runtime.squad(默认 true)开启才声明;entry 已是 squad 时不再提供,避免套娃 internal/runtime/llm.go:467 squadToolEnabled;:266 注释
A3 runTool 分派 → squadadapter.Orchestrate(rc, dataDir, goalText) internal/runtime/llm_direct.go:479 → internal/squadadapter/adapter.go:47 Orchestrate
A4 之后进入 agent-squad 引擎(规划→调度→质检) 见小队工作机制

路径 B:对话入口模式(entry=squad)

# 步骤 位置
B1 灰度开关 runtime.entry=squad(默认 direct) internal/settings/settings.go:90
B2 runmgr 选 Runner:selectConversationRunner 检查 runtime.entry=="squad" → 返回 SquadRunner internal/runmgr/runmgr.go:918(注入点 :908 SetSquadRunner,装配 internal/app/app.go:306)
B3 SquadRunner.Execute(internal/runtime/squad_runner.go:26)先做 LLM 分诊:modelRouter.Route(:146,轻量模型输出 JSON `direct plan,parseRoute :167)—— direct = 单步 assistant 直通(deps/agent-squad/squad/router.go:55 directAssistantPlan);plan = 进 Leader 委派(router.go:29 applyRoute设metadata["mode"]="leader"`)
B4 plan 模式 → squadadapter.RunEntry → 引擎 leader 模式 internal/squadadapter/entry.go:42 RunEntry;deps/agent-squad/squad/engine.go(RunOptions.Mode="leader",Options 注释 engine.go:99-105)

路径 C:演示/脚本

用户消息含 #squad → MockRunner 走同样 Orchestrate(internal/runtime/mock.go)。

一条"不可达"的路径(设计预留)

意图识别绑定 blueprint 动作可路由到 KindSquad(internal/route/route.go:96-97), 但当前双重不可达:server.go:664 明确注释 SquadReady 保持 false(per-run entry 覆盖未就位);且系统默认意图目录为空(见意图识别 4.5 节), 不装插件就没有意图可命中 blueprint。小队的实际启动走上面 A/B/C 三条路径;意图目录 对小队的现实作用是注入规划者/Leader 提示词的能力目录(deps/agent-squad/adapters/intent/catalog.go)。


4. 装配(启动期)

内容 位置
runmgr 注入三个 runner(LLMRunner / SubLLMRunner / MockRunner),SquadRunner 经 SetSquadRunner internal/app/app.go:287-306
角色指令来源接提示词库(agent.squad.<kind>) app.go:176 → squadadapter.RoleInstructions(adapter.go:303)
agent-native 内核选项:模型路由、Tavily 搜索、解释器、MCP、技能根、Subagent 桥接、PermissionAsk、检查点 app.go:196 squadadapter.AgentNativeOptions
小队后端解析器:只注册 "agent-native" 内核工厂(legacy "agent-system" SpawnSubagent 压缩路径已退役删除;工厂缺席解析 fail-closed) internal/squadadapter/adapter.go:292 BuildBackends(退役注释 :289-291);entry.go:103 DefaultBackend="agent-native"
内核工厂注册 deps/agent-squad/adapters/native/register.go:61 RegisterFull

5. 两条线的对比小结

子代理 delegate_task 小队 squad
触发者 主对话模型 设置开关 / 主对话模型 / 演示脚本
执行单位 一个子 run(Kind=subagent) 一组角色化步骤(每步一个 agent-native 内核 agent)
编排者 主对话(单层委派,子代理不可再委派) agent-squad 引擎(DAG 调度 / Leader 循环)
并发 后台最多 3/会话 无写集冲突的步骤可并行
深度 1 层(startChild 深度检查,runmgr.go:1356-1358;子代理 spec 禁派发工具) 成员内核里的 delegate_task 经 SubagentFactory(adapter.go:234)桥回产品 SpawnSubagent,深度恒为 1,子 run 不再嵌套小队
汇总 AgentResultPayload 回父 run 交付物聚合 output.md → 主 run 工件(见小队工作机制)

6. 关键文件清单

职责 文件
delegate_task 分派 internal/runtime/llm_direct.go:493 起
子 run 派生与任务树 internal/runmgr/runmgr.go:1348-1475、1560-1616
子代理执行器 internal/runtime/sub_loop.go
工具声明与门禁 internal/runtime/llm.go:267-315, 466-467
squad_orchestrate 分派 internal/runtime/llm_direct.go:479
小队适配器(工具路径 + 后端组装 + Subagent 桥接) internal/squadadapter/adapter.go(Orchestrate :47、SubagentFactory :234、BuildBackends :292、builtinRoles :306)
小队适配器(入口路径) internal/squadadapter/entry.go(RunEntry :42、kernelRoles :177)
对话入口 Runner + LLM 分诊 internal/runtime/squad_runner.go(Execute :26、Route :146)
Runner 选择 internal/runmgr/runmgr.go:918
灰度开关 internal/settings/settings.go:90
装配 internal/app/app.go:176, 196, 287-306