Skip to main content
子代理让 agent 把大任务拆开并行处理,而不是在一个上下文里串行做完。 每个子代理是一个独立的 Agent 实例:独立上下文、独立工具集、独立记账。
一份子代理定义能碰到什么,由五个能力维度(工具、技能、MCP、知识源、记忆) 逐个声明、逐个生效。详见子代理能力模型。

四个调度工具

1

Task

派发一个子代理,带独立上下文与工具集,立即返回。
2

TaskWait

等待某个子代理完成并取回结果。
3

TaskList

列出当前存活的子代理及其状态。
4

TaskStop

中止一个正在跑的子代理。
并行规则很直白:一条消息里发多个 Task 就是并行;一旦和其他工具混在同一条消息里, 就退化成一个个串行跑。并发上限 8。子代理跑着的时候你不必干等——继续干活或继续聊天, 报告会在完成时自己回到对话里。

主代理自己就能建定义

除设置页之外,主代理手里还有三个管理工具:
1

subagents_list

列出全部定义(工具、轮次、模型、开关、来源文件、各层存储目录)。
2

subagents_save

新建或更新一份系统级 / 工作区级定义。
3

subagents_delete

删除一份自定义定义。
它们与设置页走同一套语义:schema 校验、层目录解析、内置重名拒绝、跨层查重、 改名时清理旧文件——所以 agent 建出来的定义和你手写的没有区别。 这组工具挂在 Task 组旁边,不在基础工具表里:子代理按定义取工具时结构性拿不到它们。 委派不能继续委派,也不能改定义——这是第二道闸门(第一道是可授予工具白名单)。 保存后协议层重排工具组,下一个 turn 即生效,不需要重启应用。

四层发现

定义是一份纯 YAML 文件,按四层加载:

内置

随应用分发:Explorer、Code-reviewer、Test-runner、Fixer。 设置页只读——可开关、可复制为系统级,永不被写回。

系统级

应用数据目录下的 subagents/*.yml,全局生效。 内置之外的个人定义放这一层。

工作区级

<工作区>/.kova/subagents/*.yml,跟着 git 走,只对该工作区生效。 同名的工作区层与内置层互不影响。

插件提供

插件清单里的 subagents 目录贡献自己的定义, 开关与模型覆盖按 pluginId 命名空间隔离。
同名时后加载的遮蔽先加载的。一份坏文件只降级成一条诊断,不赔掉整份清单—— 更不能赔掉整个 turn。 开关与模型覆盖不写进定义文件。 定义文件会进 git,内置更是只读常量, 所以「启用了没」「用哪个模型」是本机决定,整包存在 SQLite 里。 模型覆盖因此也是内置定义的唯一可调项。生效优先级: Task 参数 > 本机覆盖 > 定义自带 > 会话当前模型

给它什么能力,由定义说了算

一份子代理定义可以声明五个正交维度。未声明即不可达—— 没写的东西不会出现在它的工具表和提示词里。 细节与设计取舍见子代理能力模型。

为什么活动过程要落盘

这是子代理系统里最实际的一课。 改动前的问题:子代理干活的过程(它想了什么、调了什么工具、写了什么字) 只活在内存里,上限 400 条、满了还会优先裁掉思考与正文的增量。 应用一重启,打开「子智能体」面板就只剩一句「记录已过期」—— 只有最终报告还留在主对话里。 设计就三件事:

存哪

每个子代理一个文件: sessions/subagents/<它的id>.jsonl,一行一条记录,append-only。

怎么存

边干边写,但攒一批再写(250ms 批次), 所以又快又不伤硬盘,也不阻塞 agent 主循环。

丢了怎么办

重启后从文件读回来,面板照常显示, 前端 store 逻辑零改动。

崩溃丢失率

先定义才能谈保证——丢失率 = 崩溃时丢失的记录数 / 该委派已产出的记录数。
  • 崩溃最多丢失当前未刷批次(≤250ms 的增量);
  • 终态(报告)强制同步刷,所以结果永不失;
  • 推论:委派跑得越久,边界损失占比越低。短任务不承诺这个指标—— 它记录本来就少,且短任务的过程价值低,刻意接受。

恢复与「已中断」

读取是懒加载:只在内存未命中时读盘,不做启动期全量预热。 持久化时还在 running 的委派,恢复后标成 interrupted—— 进程没了,它不可能还在跑,但它的完整过程(思考、工具调用、正文、报告)都还在。

保留与护栏

  • 单文件 > 5MB 时截尾保留 1MB,防止长任务把磁盘打满;
  • 文件数量按目录盘点(不是按内存——重启后内存是空的,必须扫盘), 超上限删最旧的;
  • 只在无委派在跑时清理,running 的文件永不淘汰。

token 结算:子代理自己记账

子代理是独立 Agent,用量从不写进父会话转录。如果只读父转录, 「目标靠子代理干完了大半活」时读数会严重少报。 所以子代理自己记账(SubagentRun.tokens),结算时汇给父 run; 重复结算被 record.status 守卫挡住,同一笔不会记两次。
这也是目标模式把 token 账从「读转录」改成 「现累增量」的原因之一:看不见子代理的账,目标模式的消耗读数就是错的。

明确不做的

设计里写明了边界,这些是刻意的取舍:
  • 不做续跑:重启后不恢复执行链,未完成的委派只是「可回放的历史」, 不自动接着干;
  • 不写进父会话转录:父转录会被整份读取,写进去会污染它;
  • 不引入新存储引擎:复用 JSONL 与现有写入纪律;
  • 不嵌套委派:子代理拿不到 Task 组,也拿不到子代理管理工具组, 它不能再往下派活;
  • 不让子代理决定主记忆:它可以选「共享」目录直接写工作区记忆, 但没有「把它的私有记忆导入主记忆」这种动作。

下一步

一份定义怎么拿到知识库、技能和记忆——子代理能力模型。