要让 AI Agent 稳定、可控地完成复杂任务,必须系统设计其 Action Space(动作空间)。核心在于通过合理的工具粒度(micro/medium/macro-tool)划分工具职责,使用严格的 TypeScript Schema 定义工具输入输出,并规范 Observation(观测)输出结构以支持错误恢复和决策。本文将结合 agent-harness-construction 与 agent-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:明确的状态标识(
success,warning,error)。 - 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”后茫然无措。
在设计工具输出时,错误信息应明确包含:
- Root Cause Hint(根因提示):尽可能指向错误的直接原因。
- Safe Retry Instruction(安全重试建议):Agent 应该采取的、安全的恢复步骤。
- 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”,无任何细节。对策:强制使用包含
summary和next_actions的结构化输出。 - 缺乏错误恢复线索:错误输出后 Agent 直接停止。对策:在错误输出中明确给出
next_actions,引导 Agent 尝试安全重试或切换方案。 - 上下文无序堆积:将大量文档直接塞入提示。对策:按需加载 Skill,使用文件引用。
FAQ
Q: 划分 micro、medium、macro 工具粒度的主要依据是什么? A: 主要依据操作的风险等级、影响范围以及执行的往返成本。高风险、不可逆的操作(如部署、删除)应使用 micro-tool;常规编辑查询用 medium-tool;只有在组合操作成本极高且步骤固定时,才考虑 macro-tool。
Q: 一个结构化的 Observation 输出,最必不可少的字段是哪些?
A: status 和 summary 是最基础的。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 等。其核心思想(清晰定义、结构化反馈、错误恢复)具有普适性。