拆.
工具——AI 怎么'做事' · 第 08

Task tool

让 AI 把活分给'子 AI'

4500读完约 23 分钟craft:B+发布于 2026-06-21

一、原理:subagent 调用是怎么实现的

到目前为止我们看的工具(read、edit、bash、grep……)都是"原子操作"——做一件具体的事。

Task 工具不一样。Task 让 AI 派生一个"子 AI"去处理任务

具体说,LLM 调用 task 工具时:

  • 它指定一个 subagent_type(比如 "general"、"explore"、"task-runner")
  • 它写一段 prompt 描述要做的任务
  • opencode 启动一个新的 LLM 会话——用指定的 agent 类型
  • 这个新会话独立跑(自己的 system prompt、自己的工具集、自己的 context)
  • 完成后把结果返回给父 LLM

这是个"AI 内部的雇佣"——父 AI 把活外包给子 AI,子 AI 跑完汇报。

为什么需要这种能力?三个理由。

理由 1:context 隔离

父 AI 的 context 越长越贵、越长越容易 lost in the middle。如果某个子任务需要"深度探索"(比如读 50 个文件理解整个模块),让父 AI 直接做会吃掉大量 context。

派生子 agent 让"深度探索"在独立 context 里完成——子 agent 的 context 跑完即释放,父 AI 只保留子 agent 返回的简洁结果。这种"分块清理"让父 AI 的 context 保持精简。

理由 2:能力分工

不同任务需要不同的 system prompt 和工具集。"探索代码"的 agent 应该被引导"先 grep 后 read"、"画 architecture diagram"的 agent 应该被引导"用 mermaid 语法"、"重构代码"的 agent 应该被引导"先写测试再改"。

把这些"专家 agent"做成独立类型,父 AI 根据需要派生对应类型。这是 multi-agent 的核心——不同 agent 有不同的"职业"

理由 3:并行加速

某些任务可以并行做——比如"在 5 个不同的模块里 grep 同一个关键词、汇总结果"。串行做要 5 次 grep 顺序跑、5x 时间。并行派生 5 个 subagent,同时跑——1x 时间。

这是 AI Agent "工程化"的红利——把"分布式计算"的思路用到 AI 任务编排。

但 Task 工具有个根本风险——它是最贵的工具

每次 task 调用都启动一个新 LLM 会话——意味着完整的 system prompt 重新发送、新的 token 计费、新的循环可能跑几轮。一次 task 的成本可能是 read 的 100 倍。

如果 LLM 滥用 task——"简单任务也用 task"——会浪费大量 token。这是 opencode 给 task 写最多反例的原因。

二、案例:opencode 的 task.txt 的 6 条反例

我们看 packages/opencode/src/tool/task.txt

Launch a new agent to handle complex, multistep tasks autonomously.

When using the Task tool, you must specify a subagent_type parameter to select which agent type to use.

When NOT to use the Task tool:
- If you want to read a specific file path, use the Read or Glob tool instead of the Task tool, to find the match more quickly
- If you are searching for a specific class definition like "class Foo", use the Grep tool instead, to find the match more quickly
- If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Task tool, to find the match more quickly
- If no available agent is a good fit for the task, use other tools directly

Usage notes:
1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
2. Once you have delegated work to an agent, do not duplicate that work yourself. Continue with non-overlapping tasks, or wait for the result. For background tasks, you will be notified automatically when the result is ready.
3. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session.
4. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
5. The agent's outputs should generally be trusted
6. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent. Tell it how to verify its work if possible (e.g., relevant test commands).

注意几个特征。

特征 1:反例放最前面

"When NOT to use" 是 description 的第一段(在简介之后)。LLM 在看 task 工具时,第一件事就是知道"什么时候不用我"

这是个反直觉的设计——大多数 description 把"用法"放前面。task 反过来,因为它的滥用风险高——优先把刹车踩住。

特征 2:每条反例都给替代方案

不是单纯"不要用 task",是"不要用 task,用 X 代替":

  • 读特定文件 → 用 Read 或 Glob
  • 找 class 定义 → 用 Grep
  • 读 2-3 个文件 → 用 Read

让 LLM 知道"那我该用什么"——明确替代路径而不是模糊禁令。

特征 3:跟其他工具的关系明确写出

task vs read、task vs grep、task vs glob——这种"工具间关系"在 task.txt 里被显式表达。LLM 看到这些关系,知道任务应该被分给最便宜的工具。

这就是 3.10 章会展开的"工具决策树"——task.txt 是这个决策树的核心节点。

特征 4:并行使用明确鼓励

"Launch multiple agents concurrently" 在 Usage notes 第一条。这告诉 LLM——既然要用 task,就批量用

因为 task 的固定成本(启动 LLM 会话)高,单次 vs 5 次的成本差别不大。如果有 5 个独立子任务,并行跑比串行跑快很多。

特征 5:明确"trust the output"

"The agent's outputs should generally be trusted"——这一条让 LLM 不要"质疑"子 agent 的返回。

为什么?因为如果父 LLM 不信任子 agent,它会重新验证——"我看看子 agent 说的对不对"。结果就是父 LLM 把子 agent 的工作重做一遍——白雇佣了。

明确"信任输出"让父 LLM 把子 agent 当"专家"——直接接受结果。

特征 6:清晰的 task description 要求

"your prompt should contain a highly detailed task description ... specify exactly what information the agent should return"——给 LLM 关于"怎么写好 task prompt"的指引。

为什么?因为子 agent 启动后是独立的 LLM——它不知道父任务的上下文。父 LLM 必须把"任务描述"写得足够清楚,子 agent 才能独立完成。

这种"prompt 内 prompt"的设计要求父 LLM 学会"如何指导一个新员工"。这本身是个能力——不擅长的 LLM 给的 task prompt 模糊,子 agent 做不好。

特征 7:明确 research vs implementation

"Clearly tell the agent whether you expect it to write code or just to do research"——子 agent 不知道父任务的"意图"。父 LLM 要明确说是要"探索"还是要"实现"。

这是个常见误用——父 LLM 派生子 agent 探索,子 agent 误以为要实现,结果改了一堆文件。避免这种误解需要明确指示。

我们再看 task.ts 实现里几个细节。

细节 1:subagent_type 必须指定

parameters: {
  subagent_type: z.enum(["general", "explore", "task-runner", ...]),
  prompt: z.string(),
  background: z.boolean().optional(),
  task_id: z.string().optional(),
}

强制 subagent_type 不能省。这避免 LLM "随便 task 一下"——它必须明确说"我要派生 general agent 做这个" vs "我要派生 explore agent 做那个"。

每个 agent type 有自己的 system prompt 和工具集。第 5 篇会展开 multi-agent 编排。

细节 2:task_id 让 task 可以"接着跑"

如果同一个父 LLM 想跟同一个子 agent 多轮对话,可以传 task_id resume。这避免每次 task 都启动新 session——重用之前的 context。

但 LLM 在使用 task_id 时容易混乱——它必须自己记住"上次的 task_id 是什么"。task.txt 明确说明 task_id 的用法——让 LLM 知道这个能力。

细节 3:background mode

跟 bash 类似——background: true 让 task 不阻塞父 LLM。task 跑起来后立刻返回,父 LLM 可以继续做别的事。task 完成后异步通知。

这对长 task 是关键——一个深度 exploration 可能跑 5 分钟,父 LLM 不能卡 5 分钟。

三、设计启示:派生子 AI 的产品判断

这一章的核心论点:Task 工具是 AI Agent 的"分工机制"——但它最贵,所以 description 反例最多

如果你做 AI 产品要支持 multi-agent,下面几条原则有用:

1. 不是所有"复杂任务"都需要 subagent

简单复杂任务(多个 read 然后写代码)父 LLM 自己做就行。真正需要 subagent 的是"context 大"或"独立专家能力"的任务。

判断标准:

  • 这个子任务的 context 需求超过 50K tokens?→ subagent
  • 这个子任务需要专门的"职业知识"?→ subagent
  • 这个子任务跟主流程独立?→ subagent
  • 否则 → 父 LLM 自己做

2. subagent 的反例要详尽

最贵的工具应该有最长的"不该用我"清单。让 LLM 默认偏向"用便宜工具",只在真正需要时升级到 subagent。

3. subagent 是无状态的——每次都从 system prompt 开始

除非用 task_id resume,否则每个 subagent 启动都重新载入 system prompt + tools。成本固定开销大。

考虑设计上能不能减少 fresh subagent 的频率——比如让 task_id 默认 resume、或者把多个子任务合并成一次 task。

4. 父 LLM 必须学会"写 task prompt"

这是个被低估的能力。父 LLM 给子 agent 的 prompt 决定了子 agent 的表现。description 里要明确教 LLM "怎么写好 task prompt"——详细背景、明确目标、明确返回格式。

opencode 的 task.txt 用 usage notes 4 和 6 教这件事。

5. subagent 类型不要太多

opencode 有几个 agent 类型——general、explore、task-runner、build、plan、subagent 等。每个类型有明确职业。

不要为了"灵活性"做 20 种 agent 类型——LLM 选择困难。3-5 个清晰职能的类型够用了。

6. trust the output

明确告诉 LLM "相信 subagent 的返回"。否则父 LLM 会重做子 agent 的工作——浪费。

如果你担心 subagent 出错——加 validation 在 subagent 内部(让 subagent 自己 verify),不要让父 LLM 重做。

7. background mode 必须有

长 task 必须支持 background。否则父 LLM 卡死等结果,用户也跟着卡死。

8. 监控 task 的 ROI

每个 task 调用要记录:成本(token)、时间(秒)、是否完成、父 LLM 是不是采纳了结果。

如果发现某些 task 的 ROI 低(比如 30% 的 task 父 LLM 没用结果),考虑是不是 description 没引导对——优化 task 使用模式。

最后一个观察。Task 工具是 AI Agent "工程化"的高级形态——单 agent 能做 80% 的事,但要做到 95% 需要 multi-agent。

但 multi-agent 不是简单"更多 AI 更好"——它是精细的能力分工。每个 agent 做自己擅长的、父 LLM 学会"何时雇佣 vs 何时自己做"——这是产品工程的真正难题。

opencode 通过 task.txt 的 6 条反例 + 严格 subagent_type 强制 + background 支持,把 multi-agent 工程化做到了实用层面。第 5 篇会专门讲多 agent 编排——task 工具是这个体系的基础。

下一章 3.9 我们看 TodoWrite——一个更"低调"但极其重要的工具——让 AI 给自己写待办清单。