要让 AI Agent 稳定、可控地完成复杂任务,必须系统设计其 Action Space(动作空间)。核心在于通过合理的工具粒度(micro/medium/macro-tool)划分工具职责,使用严格的 TypeScript Schema 定义工具输入输出,并规范 Observation(观测)输出结构以支持错误恢复和决策。本文将结合 agent-harness-constructionagent-payment-x402 的实践,提供一套从定义到度量的完整指南。

设计 AI Agent 的 Action Space:Tool Definitions 与 Observation 格式最佳实践

AI 编程助手在生产环境中面对复杂、多步骤任务时,其表现往往不取决于单个模型的能力,而取决于我们为它设计的“动作空间”是否清晰、工具定义是否严谨、反馈信息是否充分。agent-harness-construction Skill 提供了一套工程化方法论,用于系统性优化 Agent 的 Action Space、Tool Definitions 和 Observation 格式。结合 Everything Claude Code 完全指南 中阐述的插件体系,我们可以构建出任务完成率高、可维护、可恢复的 AI Agent。

1. 核心目标:为什么需要专门设计 Action Space?

一个未经精心设计的 Action Space 会导致 Agent 陷入困境:工具语义重叠使其选择混乱,模糊的输出格式使其无法判断成功与否,错误发生时缺乏恢复线索直接导致任务中断。一个良好的 Action Space 设计,旨在让 Agent 的每一步操作都明确、可控、易于追踪和恢复

2. 分步设计指南

步骤 1:梳理与定义 Tool Definitions(工具定义)

工具是 Agent 与环境交互的接口。定义工具时,必须遵循 Schema-first 原则,确保类型严格、边界清晰。

输入参数:使用明确的类型,避免 any。通过窄化范围来减少歧义和错误。 输出格式:必须包含结构化字段,为后续的决策和错误恢复提供充足信息。

以下是一个基于源文件最佳实践的 TypeScript 工具定义 Schema 示例,对比了模糊定义与结构化定义:

// 反模式:模糊、不确定的工具定义
const badTool = {
  name: "handle_code",
  input: { data: "any" },
  output: "string"
};

// 推荐实践:结构化、精细化的工具定义
interface EditFileInput {
  path: string; // 要操作的文件路径
  content: string; // 要写入或修改的内容
  mode: 'overwrite' | 'append'; // 操作模式
}

interface ToolOutput {
  status: 'success' | 'warning' | 'error';
  summary: string;
  next_actions?: string[]; // 建议的后续操作
  artifacts?: string[]; // 生成的文件路径或ID
}

const editFileTool = {
  name: "edit_file",
  input: EditFileInput, // 使用明确的接口类型
  output: ToolOutput
};

步骤 2:合理划分工具粒度(Granularity)

工具粒度决定了 Agent 操作的灵活性和风险控制水平。根据 agent-harness-construction 的指导,粒度可分为三类:

  • Micro-tool(微工具):用于执行高风险、不可逆的操作。例如:执行数据库迁移、部署生产环境、修改核心配置。其核心原则是单一职责,将影响面最小化。
  • Medium-tool(中型工具):用于执行常规编辑、查阅、搜索等操作。例如:编辑单个文件、运行一个测试套件、在代码库中搜索模式。它在效率与可控性之间取得平衡。
  • Macro-tool(宏工具):封装一系列复杂操作。仅在往返(round-trip)成本极高时使用。滥用宏工具容易导致 Agent 失控,难以调试中间步骤。

实践建议:避免为同一语义设计多个近似工具。工具粒度不是一成不变的,可以结合 Hooks 自动化体系 根据 Agent 的成熟度动态调整。

步骤 3:规范 Observation(观测)输出格式

每次工具调用后返回的 Observation,是 Agent 了解世界状态和决定下一步的唯一依据。输出必须是结构化的,而非纯文本。

一个规范的 Observation 应包含以下字段:

  • status:明确的状态标识(successwarningerror)。
  • summary:对结果的一句话人类可读描述。
  • next_actions(可选):当状态非 success 时,建议的后续操作,引导 Agent 恢复或尝试其他路径。
  • artifacts(可选):记录产出物,如生成的文件路径、报告ID等。

输出示例

// 成功执行
{
  "status": "success",
  "summary": "已成功创建用户注册页面组件 `RegisterForm.vue`。",
  "next_actions": ["编写该组件的单元测试"],
  "artifacts": ["src/components/RegisterForm.vue"]
}

// 遇到错误
{
  "status": "error",
  "summary": "构建失败,原因:缺少模块 `@/utils/auth`。",
  "next_actions": ["检查 import 路径是否正确", "确认 `@/utils/auth` 是否已安装或创建"],
  "artifacts": []
}

步骤 4:构建 Error Recovery(错误恢复)机制

一个强大的 Agent 必须具备“自愈”能力。这要求每个错误路径都必须提供清晰的恢复线索,而不是让 Agent 在遇到“error”后茫然无措。

在设计工具输出时,错误信息应明确包含:

  1. Root Cause Hint(根因提示):尽可能指向错误的直接原因。
  2. Safe Retry Instruction(安全重试建议):Agent 应该采取的、安全的恢复步骤。
  3. Explicit Stop Condition(明确终止条件):什么情况下应该停止重试,避免无限循环。

结合 Verification Loop Skill 可以将这种恢复机制自动化,实现“执行-验证-恢复”的闭环。

步骤 5:优化 Context Budget(上下文预算)

Action Space 的设计直接影响上下文(Context)消耗。优化原则是只在正确的时间传递正确的最小信息

  • 保持 System Prompt 精简且稳定。
  • 大量的领域知识和复杂指南,应封装为 Skill,在需要时按需加载,而非永久占据上下文窗口。
  • 对于长文档或大量代码,使用文件引用(path)而非全文内联。
  • 只在明确的阶段边界进行上下文压缩,避免随意丢弃信息。

可以借助 Context Budget Skill 来审计和优化 Token 占用。

3. 集成外部能力:x402 协议支出策略配置示例

当 Agent 需要调用付费 API 或服务时,agent-payment-x402 Skill 提供了基于 x402 协议的安全支付能力。其核心是支出策略(SpendingPolicy),这本身也是一种需要精密定义的 Action Space 扩展。

关键点:策略只能由**编排层(Orchestrator)**设定,Agent 自身无权修改预算,这确保了资金安全。

以下是使用 TypeScript 配置支出策略的示例代码:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

// 初始化 MCP 客户端,连接支付服务
const transport = new StdioClientTransport({
  command: "npx",
  args: ["agentwallet-sdk@6.0.0"],
  env: {
    WALLET_PRIVATE_KEY: process.env.WALLET_PRIVATE_KEY, // 安全地传入私钥
  },
});
const agentpayClient = new Client({ name: "orchestrator", version: "1.0.0" });
await agentpayClient.connect(transport);

// 在任务开始前,由编排层设置支出策略
const policyResult = await agentpayClient.callTool({
  name: "set_policy",
  arguments: {
    per_task_budget: 0.50,       // 单任务最大支出 $0.50
    per_session_budget: 5.00,    // 单会话累计上限 $5.00
    allowlisted_recipients: ["api.openai.com", "api.example.com"], // 收款方白名单
    rate_limit_per_minute: 5,    // 每分钟最多支付5次
  },
});

if (policyResult.isError) {
  throw new Error(`设置支出策略失败: ${JSON.stringify(policyResult.content)}`);
}

之后,Agent 在调用付费 API 前,应通过 check_spending 工具校验余额,并在任务后通过 list_transactions 进行审计。

4. 常见错误模式与规避方法

  • 工具数量爆炸且语义重叠:导致 Agent 决策困惑,调用错误工具。对策:定期审查工具定义,合并功能相近的工具。
  • Observation 输出不透明:仅有 “Done” 或 “Error”,无任何细节。对策:强制使用包含 summarynext_actions 的结构化输出。
  • 缺乏错误恢复线索:错误输出后 Agent 直接停止。对策:在错误输出中明确给出 next_actions,引导 Agent 尝试安全重试或切换方案。
  • 上下文无序堆积:将大量文档直接塞入提示。对策:按需加载 Skill,使用文件引用。

FAQ

Q: 划分 micro、medium、macro 工具粒度的主要依据是什么? A: 主要依据操作的风险等级、影响范围以及执行的往返成本。高风险、不可逆的操作(如部署、删除)应使用 micro-tool;常规编辑查询用 medium-tool;只有在组合操作成本极高且步骤固定时,才考虑 macro-tool。

Q: 一个结构化的 Observation 输出,最必不可少的字段是哪些? A: statussummary 是最基础的。status 让程序能快速判断成功与否,summary 提供人类可读的结果描述。next_actions 对于提升错误恢复能力至关重要。

Q: 如何为 x402 的 SpendingPolicy 选择合理的预算值? A: 预算值应基于历史任务成本和风险承受能力来设定。开发测试环境应使用小额预算(如 per_task_budget: 0.1),并连接测试网。生产环境需精确核算典型任务成本,并留有合理安全边际。per_session_budget 应作为总额控制阀。

Q: 除了支付,这套 Action Space 设计思路还能用在哪些 Agent 类型上? A: 适用于任何需要与外部环境交互、执行多步骤任务的 Agent,例如:代码构建与部署 Agent、自动化测试 Agent、数据抓取与处理 Agent、文档生成 Agent 等。其核心思想(清晰定义、结构化反馈、错误恢复)具有普适性。