11 子智能体与技能系统原理(复杂任务怎么拆,怎么持续更新)
这篇把两个核心能力讲透:
- 子智能体编排(任务分治)
- 技能快照系统(能力热更新)
核心源码入口
src/agents/tools/sessions-spawn-tool.tssrc/agents/subagent-registry.tssrc/agents/subagent-announce.tssrc/agents/tools/sessions-send-tool.tssrc/agents/skills.tssrc/agents/skills/workspace.tssrc/agents/skills/refresh.tssrc/agents/skills/env-overrides.tssrc/infra/skills-remote.tssrc/agents/pi-embedded-runner/run/attempt.ts
模块一 子智能体 spawn 状态机
createSessionsSpawnTool(...) 的真实流程:
- 参数解析:
task/agentId/model/thinking/runTimeoutSeconds/cleanup - 递归防护:若当前会话是 subagent(
isSubagentSessionKey(...))直接拒绝 - agent 白名单:
subagents.allowAgents校验跨 agent spawn 权限 - 创建子会话 key:
agent:<target>:subagent:<uuid> - 可选配置覆盖:
sessions.patch写 modelsessions.patch写 thinkingLevel
- 构造子系统提示:
buildSubagentSystemPrompt(...) - 调网关启动子运行:
method=agent(lane=AGENT_LANE_SUBAGENT) - 注册生命周期:
registerSubagentRun(...)
模块二 子运行生命周期管理
subagent-registry.ts 做了几件很工程化的事:
- 内存 + 落盘:
subagentRuns+saveSubagentRegistryToDisk(...) - 启动恢复:
restoreSubagentRunsOnce(),重启后恢复未完成 run - 等待完成:
- 事件监听
onAgentEvent(lifecycle) - RPC 兜底
agent.wait
- 通知主会话:
runSubagentAnnounceFlow(...) - 清理策略:
cleanup=delete删除子会话cleanup=keep保留结果
- 归档清扫:按
archiveAfterMinutes定时清理历史 run
这就是“子任务不会丢、重启也能续”的关键。
模块三 子结果回传机制
runSubagentAnnounceFlow(...) 的关键设计:
- 先等待 child run 彻底 settled(避免压缩重试中提前汇报)
- 构造
triggerMessage给主智能体,不直接对用户硬回写 - 由主智能体用自己的语气二次总结,保证对话风格一致
- 支持
NO_REPLY,允许内部子任务静默完成
模块四 sessions_send 的跨会话协同
sessions_send 不是简单转发,它支持:
sessionKey或label定位目标会话- sandbox 可见性限制(
sessionToolsVisibility=spawned) - agent-to-agent 策略校验(
tools.agentToAgent.allow) - 嵌套 lane 执行:
AGENT_LANE_NESTED - A2A 宣告流:
runSessionsSendA2AFlow(...)
模块五 技能快照系统原理
skills/workspace.ts 负责把散落技能文件变成稳定快照:
- 多来源合并与优先级:
- extra < bundled < managed < personal < project < workspace
- 生成快照:
buildWorkspaceSkillSnapshot(...)
promptskills(含primaryEnv)resolvedSkillsversion
- 执行时取 prompt:
resolveSkillsPromptForRun(...)(优先 snapshot)
模块六 技能热更新与环境注入
热更新
ensureSkillsWatcher(...):
- 监听
SKILL.mdadd/change/unlink - debounce 后
bumpSkillsSnapshotVersion(...) - 通过
getSkillsSnapshotVersion(...)驱动新轮执行刷新
环境注入
applySkillEnvOverrides(...) / applySkillEnvOverridesFromSnapshot(...):
- 按 skill config 写入 env
primaryEnv+apiKey自动注入- 返回 restore 函数,执行结束后回滚环境
模块七 远程技能能力同步(多设备场景)
skills-remote.ts 解决“技能依赖的系统命令在远程节点是否可用”:
- 维护远程节点缓存:
remoteNodes(nodeId、platform、commands、bins) - 启动预热:
primeRemoteSkillsCache()从 pairing 信息恢复节点能力 - 能力探测:
refreshRemoteNodeBins(...)通过远程命令探测可执行 bin - 版本联动:远程能力变化后
bumpSkillsSnapshotVersion({ reason: "remote-node" })
意思是:不仅本地 SKILL.md 变化会触发快照更新,远程节点能力变化也会触发更新。
最小复刻骨架
ts
async function spawnSubagent(task: string, parent: SessionCtx) {
if (parent.isSubagent) throw new Error("subagent cannot spawn subagent");
const childSessionKey = `agent:${parent.agentId}:subagent:${crypto.randomUUID()}`;
const runId = await gateway.agent({
sessionKey: childSessionKey,
message: task,
lane: "subagent",
extraSystemPrompt: buildSubPrompt(task, parent.sessionKey, childSessionKey),
});
registerSubagentRun({ runId, childSessionKey, requesterSessionKey: parent.sessionKey });
return runId;
}
function buildSkillsContext(workspaceDir: string, cfg: Config) {
const version = getSkillsSnapshotVersion(workspaceDir);
const snapshot = buildWorkspaceSkillSnapshot(workspaceDir, { config: cfg, snapshotVersion: version });
const restoreEnv = applySkillEnvOverridesFromSnapshot({ snapshot, config: cfg });
return { snapshot, restoreEnv };
}自检清单
- 子智能体是否被禁止再递归 spawn。
- 主进程重启后未完成子任务是否能恢复。
- 子任务结果是否稳定回传主会话。
cleanup=delete/keep是否行为可预测。- 修改
SKILL.md后下一轮是否拿到新 snapshot version。 - 技能注入的 env 是否在结束后正确回滚。