Sub-agents

Sub-agents 是从现有 agent 运行中派生出的后台 agent 任务。它们在自己的 session 中运行(agent:<agentId>:subagent:<uuid>),完成后会将结果通知回请求者的聊天 channel。

斜杠命令

使用 /subagents 来检查或控制当前 session 的 sub-agent 运行:

  • /subagents list
  • /subagents stop <id|#|all>
  • /subagents log <id|#> [limit] [tools]
  • /subagents info <id|#>
  • /subagents send <id|#> <message>

/subagents info 会显示运行的元数据(状态、时间戳、session id、transcript 路径、清理设置)。

主要目标:

  • 并行处理”研究任务 / 长时间任务 / 慢速工具”,不阻塞主运行
  • 默认保持 sub-agents 隔离(session 分离 + 可选的沙箱)
  • 保持工具接口不易被误用:sub-agents 默认不获得 session 工具
  • 避免嵌套扩散:sub-agents 不能再派生 sub-agents

成本提示:每个 sub-agent 都有自己的 context 和 token 使用量。对于繁重或重复性任务,可以给 sub-agents 设置更便宜的模型,而主 agent 保持使用高质量模型。你可以通过 agents.defaults.subagents.model 或针对每个 agent 的覆盖配置来设置。

工具

使用 sessions_spawn

  • 启动一个 sub-agent 运行(deliver: false,全局队列:subagent
  • 然后运行一个通知步骤,将通知回复发送到请求者的聊天 channel
  • 默认模型:继承调用者的模型,除非你设置了 agents.defaults.subagents.model(或针对每个 agent 的 agents.list[].subagents.model);显式的 sessions_spawn.model 参数优先级最高

工具参数:

  • task(必需)
  • label?(可选)
  • agentId?(可选;如果允许的话,在另一个 agent id 下派生)
  • model?(可选;覆盖 sub-agent 模型;无效值会被跳过,sub-agent 会在默认模型上运行,并在工具结果中显示警告)
  • thinking?(可选;覆盖 sub-agent 运行的思考级别)
  • runTimeoutSeconds?(默认 0;设置后,sub-agent 运行会在 N 秒后中止)
  • cleanup?delete|keep,默认 keep

白名单:

  • agents.list[].subagents.allowAgents:可以通过 agentId 参数指定的 agent id 列表(["*"] 表示允许任何)。默认:仅请求者 agent。

发现:

  • 使用 agents_list 查看当前允许用于 sessions_spawn 的 agent id。

自动归档:

  • Sub-agent sessions 会在 agents.defaults.subagents.archiveAfterMinutes(默认:60)分钟后自动归档
  • 归档使用 sessions.delete 并将 transcript 重命名为 *.deleted.<timestamp>(同一文件夹)
  • cleanup: "delete" 会在通知后立即归档(仍然通过重命名保留 transcript)
  • 自动归档是尽力而为的;如果 gateway 重启,待处理的计时器会丢失
  • runTimeoutSeconds 不会自动归档;它只会停止运行。session 会保留到自动归档时

认证

Sub-agent 的认证是通过 agent id 解析的,而不是通过 session 类型:

  • Sub-agent 的 session key 是 agent:<agentId>:subagent:<uuid>
  • 认证存储从该 agent 的 agentDir 加载
  • 主 agent 的认证配置文件会作为后备合并进来;agent 配置文件在冲突时会覆盖主配置文件

注意:合并是累加的,所以主配置文件始终可用作后备。目前还不支持每个 agent 完全隔离的认证。

通知

Sub-agents 通过通知步骤报告结果:

  • 通知步骤在 sub-agent session 内运行(不是在请求者 session 中)
  • 如果 sub-agent 回复的内容正好是 ANNOUNCE_SKIP,则不会发送任何内容
  • 否则,通知回复会通过后续的 agent 调用(deliver=true)发送到请求者的聊天 channel
  • 通知回复会在可用时保留线程/主题路由(Slack 线程、Telegram 主题、Matrix 线程)
  • 通知消息会规范化为稳定的模板:
    • Status::从运行结果派生(successerrortimeoutunknown
    • Result::通知步骤的摘要内容(如果缺失则显示 (not available)
    • Notes::错误详情和其他有用的上下文
  • Status 不是从模型输出推断的;它来自运行时结果信号

通知内容在末尾包含统计信息(即使被包装):

  • 运行时间(例如 runtime 5m12s
  • Token 使用量(输入/输出/总计)
  • 配置了模型定价时的估算成本(models.providers.*.models[].cost
  • sessionKeysessionId 和 transcript 路径(这样主 agent 可以通过 sessions_history 获取历史记录或检查磁盘上的文件)

工具策略(sub-agent 工具)

默认情况下,sub-agents 获得除 session 工具外的所有工具

  • sessions_list
  • sessions_history
  • sessions_send
  • sessions_spawn

通过配置覆盖:

{
  agents: {
    defaults: {
      subagents: {
        maxConcurrent: 1,
      },
    },
  },
  tools: {
    subagents: {
      tools: {
        // deny wins
        deny: ["gateway", "cron"],
        // if allow is set, it becomes allow-only (deny still wins)
        // allow: ["read", "exec", "process"]
      },
    },
  },
}

并发

Sub-agents 使用专用的进程内队列通道:

  • 通道名称:subagent
  • 并发数:agents.defaults.subagents.maxConcurrent(默认 8

停止

  • 在请求者聊天中发送 /stop 会中止请求者 session,并停止从它派生的所有活动 sub-agent 运行。

限制

  • Sub-agent 通知是尽力而为的。如果 gateway 重启,待处理的”通知回传”工作会丢失
  • Sub-agents 仍然共享相同的 gateway 进程资源;将 maxConcurrent 视为安全阀
  • sessions_spawn 始终是非阻塞的:它会立即返回 { status: "accepted", runId, childSessionKey }
  • Sub-agent context 只注入 AGENTS.md + TOOLS.md(没有 SOUL.mdIDENTITY.mdUSER.mdHEARTBEAT.mdBOOTSTRAP.md