跳到正文

执行型子 Agent

探索器收集信息。执行器会根据它采取行动。

这两个角色的分工沿着委托分开的线条划分,就像委托分开了Agent本身一样。探索成本低廉,只读且流量大。执行成本更高,可能修改文件,且需要更强的模型,因为出错的成本更高。

执行器从父 Agent那里继承信任。父 Agent决定执行器可以做什么,执行器严格按照指令操作,两个角色都不会向用户提出任何要求。这就留在父 Agent里。

学习成果

任务工具中的第二个分支会生成一个执行器子 Agent,包含readgrep和委托模式bash,使用claude-sonnet-4-6和15步预算。父 Agent现在可以在委派时选择探索器或执行器。

快速路径

  1. subagentType: "explorer" | "executor"场扩展task工具schema
  2. 添加一个执行器分支,使用更强的模型、更大的步长预算和委托模式的bash
  3. 更新描述,使路由对父 Agent清晰可见

动手练习 6.3

添加执行器角色并从task工具中路由到它。

要求:

  1. subagentType添加到任务工具的输入 schema中,作为"explorer" | "executor"枚举,默认为"explorer"
  2. subagentType === "executor"后,实例化一个包含readgrep和委托模式的ToolLoopAgent``bash
  3. 执行器使用claude-sonnet-4-6stopWhen: stepCountIs(15)
  4. createApproval({ mode: "delegated", trust: [...] })建立执行器的bash,通过一个小型信托名单("npm test""npm run build""npx tsc"
  5. 更新任务工具描述,向父 Agent解释这两个角色

实现提示:

  • 执行器需要自己的bash工具,并支持委托模式的审批。不要重复使用父 Agent的互动式攻击,因为互动模式会暂停给提示词执行器无法回答的用户
  • Sonnet是执行器工作的正确默认选择。Opus对大多数实现任务来说是大材小用,速度慢到让人感觉不到
  • 信任名单故意较小。执行器应只运行父 Agent认为安全的命令。测试运行器和构建命令通常是安全的。软件包安装和迁移则不是

执行器分支

ts
export function createTaskTool(
  sandbox: Sandbox,
  parentTools: { read: any; grep: any },
) {
  return tool({
    description: `Delegate work to a subagent.
Explorer (default): read-only research with a fast model.
Executor: implementation with a stronger model and delegated trust on bash.

WHEN TO USE: research across many files (explorer), bulk implementation (executor).
WHEN NOT TO USE: ambiguous requirements (use askUser),
  architectural decisions (the parent decides).`,
    inputSchema: z.object({
      description: z.string().describe("Task instructions for the subagent"),
      subagentType: z
        .enum(["explorer", "executor"])
        .default("explorer")
        .describe("Subagent role"),
    }),
    execute: async ({ description, subagentType }) => {
      if (subagentType === "executor") {
        const executorBash = createBashTool(
          sandbox,
          createApproval({
            mode: "delegated",
            trust: ["npm test", "npm run build", "npx tsc"],
          }),
        );

        const executor = new ToolLoopAgent({
          model: "anthropic/claude-sonnet-4-6",
          instructions: `You are an executor agent. Follow instructions precisely.
Working directory: ${sandbox.workingDirectory}
Do NOT ask questions. Do NOT explore beyond what's needed. Execute the task.`,
          tools: {
            read: parentTools.read,
            grep: parentTools.grep,
            bash: executorBash,
          },
          stopWhen: stepCountIs(15),
        });

        try {
          const { text, steps } = await executor.generate({ prompt: description });
          return text
            ? `[Executor: ${steps.length} steps]\n${text}`
            : "(no response from executor)";
        } catch (e: any) {
          return `Executor error: ${e.message}`;
        }
      }

      const explorer = new ToolLoopAgent({
        model: "anthropic/claude-haiku-4-5",
        instructions: `You are an explorer agent. Investigate and report back concisely.
Working directory: ${sandbox.workingDirectory}`,
        tools: { read: parentTools.read, grep: parentTools.grep },
        stopWhen: stepCountIs(5),
      });

      try {
        const { text, steps } = await explorer.generate({ prompt: description });
        return text
          ? `[Explorer: ${steps.length} steps]\n${text}`
          : "(no response from explorer)";
      } catch (e: any) {
        return `Explorer error: ${e.message}`;
      }
    },
  });
}

探索器与执行器一览

探索器执行器
工具readgrepreadgrepbash(委派)
模型claude-haiku-4-5claude-sonnet-4-6
阶梯预算515
可以修改是的(在信托名单内)
可以问问用户

这两个角色在工具能力、模型强度和预算上存在差异。他们一致同意一点:两人都不能向用户提问。这种责任属于父 Agent,也就是让人类参与其中的角色。

教学质量对执行器更重要

探索器主要是四处看看。模糊的描述仍然能带来有用的信息。执行器字面上完全按照指示操作。模糊的描述会得到模糊(甚至有害)的结果。

缺点:

Fix the auth bug.

好:

In src/auth.ts, the login function at line 42 doesn't check for null email.
Add a null check before the database query. Run `npx tsc --noEmit` after the change.

父 Agent的工作是提供目标、程序、约束和验证步骤。执行器的工作就是跟随他们。系统提示词的“请问问题吗”这句话在这里NOT真正发挥了作用。它迫使执行器要么基于现有条件采取行动,要么失败,而不是拖延澄清。

**注意:委托信任,而非全面信任**

执行器的bash使用模块2审批配置中的mode: "delegated"。父 Agent决定哪些命令值得信任。执行器可以npm test。它不能运行npm install、无rm -rf或列表中其他任何项目。这正是最初可辨识联合类型的合理性。

动手试试

请父 Agent委派需要行动的事务,而不仅仅是研究:

bash
bun run index.ts . "Delegate to an executor: rename the 'cwd' variable in src/sandbox-local.ts to 'workingDir'. Then run npx tsc --noEmit and report the result."

父 Agent应该调用 tasksubagentType: "executor"。执行器应该进行更改,运行typecheck,并返回摘要。把你用探索器模式做同一任务的效果做比较(它不会改变任何东西)。

bash
npx tsc --noEmit

提交

bash
git add src/tools.ts
git commit -m "feat(subagents): add executor role with delegated bash"

完成标准

  • [ ] task工具schema包括subagentType: "explorer" | "executor"
  • [ ] 执行器使用claude-sonnet-4-6和15步预算
  • [ ] 执行器在mode: "delegated"有自己的bash,信托名单较小
  • [ ] 执行器严格执行指令,不问问题
  • [ ] 探索器行为与上一节课无异
  • [ ] npx tsc --noEmit

**注意:从父 Agent处继承信任**

执行器的信任名单现在是硬编码的。试着把父 Agent的信任列表串联进去:当父 Agent生成执行器时,执行器会接收父 Agent的安全命令。现在想想界限。执行器是否应该被允许以同样的信任孕育出另一个执行器?还是说每升级一级就应该缩小信任组? 生产Harness的做法不同,答案取决于你对Agent规划的信任程度。

参考实现

完整实现请参见上文createTaskTool代码块。练习的解法是同样的代码,应用到你的src/tools.ts上。

非官方简体中文翻译 · 原课程来自 Vercel Academy