Agent-as-Tool:把 Agent 封装成工具

提出问题

很多多 Agent 系统最后都会落到一种朴素实现:主 Agent 把另一个 Agent 当工具调用。

这不是因为多 Agent 等于 Tool Calling,而是因为 Tool Calling 提供了一个很适合工程化的边界:调用方给出输入,被调用方在自己的上下文和工具范围内工作,最后返回结构化结果。

对主控系统来说,被调用的 Agent 像一个高级工具;对被调用 Agent 来说,它仍然可以有自己的目标、工具、记忆和执行循环。

场景

假设你做一个本地开发编排器,希望同时利用不同 AI 编程工具:

Dev Orchestrator
  ├── runClaudeCode(task)
  ├── runCodex(task)
  ├── runStaticAnalysis()
  ├── runTests()
  └── applyPatch()

用户输入:

帮我分析这个重构需求,让 Claude Code 和 Codex 分别给出方案,然后综合成一个保守实现路径。

主控 Agent 不需要知道 Claude Code 内部如何读文件、规划和编辑。它只需要一个稳定工具契约:

  • 输入:任务、仓库路径、允许范围、期望输出。
  • 输出:方案、风险、修改建议、证据、是否需要人工确认。
  • 运行约束:超时、预算、是否允许写文件。

这就是 Agent-as-Tool 的核心:把一个复杂 Agent 包装成一个可调用、可限制、可观测的能力。

分析问题

Agent-as-Tool 和普通 Tool 的区别

普通工具通常是确定性函数。Agent 工具则是一个可能多步运行的子系统。

维度普通 ToolAgent-as-Tool
执行方式一次函数调用可能多轮推理、检索、工具调用
输出稳定性较高需要结构化约束和校验
耗时通常较短可能较长,需要异步和超时
成本可预测与上下文、步骤和模型有关
权限工具自身权限子 Agent 还可能拥有工具集
可观测性请求和响应需要子 trace、步骤日志、产物

因此,Agent-as-Tool 不能只写成 exec("codex ...")。它需要像生产工具一样有契约、权限、错误、预算和审计。

调用契约

一个可治理的 Agent 工具,至少要定义这些字段。

type AgentToolRequest = {
  task: string;
  scope: {
    repo?: string;
    files?: string[];
    businessObjects?: string[];
    readonly: boolean;
  };
  context: {
    summary: string;
    evidence?: string[];
    constraints: string[];
  };
  outputSchema: string;
  budget: {
    maxTokens: number;
    maxToolCalls: number;
    timeoutMs: number;
  };
};

type AgentToolResult = {
  status: "succeeded" | "failed" | "needs_human" | "partial";
  summary: string;
  evidence: string[];
  artifacts: string[];
  risks: string[];
  nextActions: string[];
};

调用方要避免传“你随便看看”。好的请求应该给出范围、约束、输出格式和停止条件。

上下文隔离

Agent-as-Tool 的一个重要价值,是隔离上下文。

主控 Agent 不必把完整对话和全部系统信息传给子 Agent。它应该传一个任务切片:

  • 当前子任务目标。
  • 与子任务相关的上下文摘要。
  • 必须遵守的约束。
  • 允许访问的数据或文件范围。
  • 期望返回的结构化结果。

这样做有三个收益:

  • 降低 token 成本。
  • 减少上下文污染。
  • 降低越权和泄漏风险。

权限和副作用

把 Agent 封装成工具后,最容易忽略的是副作用。

一个 runResearchAgent 只读资料,风险较低。一个 runCodeAgent 如果可以修改文件、提交代码、推送分支,风险就完全不同。

Agent 工具要按能力分级:

类型允许动作推荐控制
Readonly Agent搜索、读取、分析、总结记录证据和来源
Draft Agent生成草稿、生成 patch 建议不直接写入,返回 artifact
Write Agent修改文件、创建任务、写数据库幂等、审计、确认或沙盒
High-risk Agent发布、付款、删除、改权限默认不开放,必须人工确认

主控 Agent 可以请求执行,但真实执行权限应该由 runtime 决定。

列举方案

同进程 Agent 工具

最简单的方式,是在同一个服务里定义多个角色函数。

const tools = {
  askReviewer: async (input) => callLLM({
    system: reviewerPrompt,
    messages: input.messages,
    schema: reviewSchema,
  }),
  askPlanner: async (input) => callLLM({
    system: plannerPrompt,
    messages: input.messages,
    schema: planSchema,
  }),
};

适合早期产品、低风险评审和固定角色分工。优点是实现简单,缺点是隔离性弱,难以复用外部 Agent。

CLI Agent 工具

开发场景常见做法是把 Claude Code、Codex 或内部脚手架包装成 CLI 工具。

async function runCodeAgent(request: AgentToolRequest) {
  const job = await createSandboxJob(request);
  const result = await execAgentCli(job);
  return parseAgentResult(result);
}

这种方式适合本地开发提效,但要注意:

  • 在独立工作区或沙盒中运行。
  • 明确是否允许修改文件。
  • 输出必须机器可解析。
  • 超时后能终止子进程。
  • 保留 stdout、stderr、diff 和测试结果。

Remote Agent 工具

当 Agent 是独立服务时,可以通过 HTTP、RPC、队列或 MCP 风格协议调用。

这种方式适合多个产品复用同一 Agent 能力。新增成本是服务治理、版本兼容、鉴权、限流和 trace。

异步 Agent 工具

Agent 工具可能运行很久。长任务不应该阻塞一次 HTTP 请求。

更稳的方式是:

  1. 主控创建 Agent job。
  2. 子 Agent 异步运行。
  3. 状态写入任务表。
  4. 主控轮询或订阅结果。
  5. 完成后进入合并、评审或人工确认。

适合调研、代码修改、数据分析、批处理等长任务。

决策判断

方案选型表

场景条件推荐方案不推荐方案判断理由额外成本
只是角色化评审同进程 Agent 工具独立 Agent 服务简单 prompt 和 schema 足够角色 prompt 管理
本地开发工具编排CLI Agent 工具 + 沙盒主 Agent 直接改所有文件可隔离外部工具能力进程管理、diff 解析
多产品复用专家 AgentRemote Agent 工具每个产品复制一套 prompt统一治理和版本更稳网关、鉴权、trace
长时间运行任务异步 Agent job同步阻塞调用避免超时和无法恢复任务表、状态协议
有写入副作用Write Agent + 确认/沙盒Agent 工具自由写生产需要幂等和责任边界审计、回滚、确认
输出进入后续自动流程结构化结果 + 校验只返回自然语言下游需要稳定字段schema、解析、重试

反模式

第一种反模式:把 Agent 工具当普通函数。

Agent 工具可能慢、贵、不稳定、会调用其他工具。它需要超时、预算、错误分类和 trace,而不是只等一个字符串返回。

第二种反模式:主控把全部上下文原样传给子 Agent。

这会造成成本上升、权限扩大和信息污染。子 Agent 应该拿任务切片,不是拿完整世界。

第三种反模式:子 Agent 返回“完成了”。

Agent 工具的结果必须包含证据、产物、风险和状态。否则主控无法判断能否采纳。

第四种反模式:没有版本。

Agent prompt、模型、工具集合和输出 schema 变化都会影响调用方。Agent-as-Tool 一旦被多个流程复用,就要像 API 一样管理版本。

第五种反模式:让主 Agent 直接执行子 Agent 建议。

子 Agent 的建议只是输入。主控仍要校验权限、风险、结果格式和人工确认要求。

结论收束

Agent-as-Tool 是多 Agent 最容易工程化的实现方式,因为它把协作关系压缩成清晰的调用契约。

但它的本质不是“把命令包一层”,而是把一个复杂执行者封装成可调用、可限制、可观测、可回放的能力。只要 Agent 工具会运行多步、访问数据或产生副作用,就必须按生产工具治理。

工程清单

  • 工具契约:输入、输出、错误、状态是否结构化。
  • 上下文切片:是否只传子任务所需信息。
  • 权限范围:readonly、draft、write、高风险能力是否分级。
  • 运行隔离:CLI 或写入型 Agent 是否在沙盒或独立工作区运行。
  • 超时预算:token、工具调用、耗时和费用是否有限制。
  • 产物记录:diff、报告、证据、测试结果是否可追踪。
  • 结果校验:输出 schema 是否校验,失败是否可重试。
  • 版本管理:prompt、模型、工具集、schema 是否有版本。
  • 审计回放:能否查看子 Agent 的运行 trace。
  • 主控决策:子 Agent 结果是否经过合并、评审或确认后才执行。