先说结论
如果你今天设计的 API,只能靠人类读文档才能用对,那它在 Agent 时代就是残废的。
一个好的 Agent-Friendly API 需要满足三点:
- 错误响应能指导下一步行动(不是 “Something went wrong”)
- API 自己会说话(不需要翻文档就知道能干什么)
- 重复调用不会出事(幂等性)
下面我从”为什么需要”讲到”怎么做”,全程带类比和代码示例。
问题:API 的用户变了
想象你开了一家餐厅。以前的顾客都是人——看菜单、问服务员、自己决定吃什么。
现在来了一个机器人顾客。它不会问服务员,不会看墙上的推荐,只会读菜单上的字。如果菜单写”今日特色”但没写具体是什么菜,人类会喊服务员问,机器人直接卡住。
这就是 AI Agent 调用传统 API 时的困境:
- 人类看到
"error": "请稍后再试"→ 等几秒再试 - Agent 看到同样的信息 → 等多久?1 秒还是 1 小时?要不要换个参数?还是彻底放弃?完全不知道。
核心矛盾:传统 API 假设调用者有”常识”,但 Agent 没有常识——它只有你给它的结构化信息。
原理:三条设计哲学
哲学一:确定性优于灵活性
类比:交通信号灯 vs “请根据情况通行”。
人类可以在”请根据情况通行”的路口判断——看车流、看行人、凭经验。但自动驾驶系统需要红绿灯那样明确的信号。
API 也一样。给 Agent 的响应必须是”红灯还是绿灯”,不能是”看情况”。
// 这是"看情况"——Agent 无法决策
{ "status": "error", "message": "Something went wrong" }
Agent 收到这个响应后的内心活动:重试吗?改参数吗?报错吗?三个选项完全没有依据。
// 这是"红绿灯"——Agent 能直接行动
{
"error_code": "RATE_LIMITED",
"retry_after_ms": 3000,
"is_retryable": true,
"suggested_action": "WAIT_AND_RETRY"
}
看到 retry_after_ms: 3000,Agent 就知道:等 3 秒,再试一次。零歧义。
哲学二:自描述优于文档依赖
类比:自助点餐机 vs 需要服务员解释的手写菜单。
自助点餐机上,每道菜有图片、价格、可选配料、库存状态——你不需要问任何人就能完成点餐。这就是”自描述”。
API 的自描述长这样:
{
"order": { "id": "ord_123", "status": "pending_payment" },
"available_actions": [
{
"action": "pay",
"method": "POST",
"href": "/orders/ord_123/pay",
"required_params": ["payment_method_id"],
"effects": ["order.status -> paid"]
},
{
"action": "cancel",
"method": "POST",
"href": "/orders/ord_123/cancel",
"effects": ["order.status -> cancelled"]
}
]
}
这段响应告诉 Agent 四件事:
- 订单当前状态是”待支付”
- 你现在能做两件事:付款或取消
- 付款需要提供
payment_method_id参数 - 付款后订单状态会变成
paid
Agent 不需要事先读过任何文档,光看这个响应就能做出正确决策。
哲学三:幂等性是生存基础
幂等性(Idempotency)是什么?简单说:同一个操作执行一次和执行十次,结果一样。
类比:电梯按钮。你按一次”3楼”和狂按十次”3楼”,电梯都只去 3 楼一次。这就是幂等的。
为什么 Agent 需要幂等性?因为 Agent 会:
- 网络超时后重试
- 崩溃恢复后重新执行
- 并发执行同一个流程
没有幂等保障的后果:Agent 发起一笔转账,超时了,不确定是否成功,重试一次——钱扣了两次。
解决方案很简单,一个请求头:
POST /transfers
Idempotency-Key: agent-session-42-step-7
服务端看到相同的 Idempotency-Key,直接返回上次的结果,不重复执行。就像电梯记住了”已经在去 3 楼的路上了”。
实践:四个关键设计
实践一:结构化错误分类
传统 HTTP 状态码(404、500)对 Agent 几乎没用。Agent 真正需要的是:我下一步该做什么?
把所有错误分成四类,按 Agent 的行动来分:
| 错误类别 | Agent 该做什么 | 现实例子 |
|---|---|---|
RETRYABLE_TRANSIENT | 等一会儿重试 | 服务器暂时繁忙 |
RETRYABLE_AFTER_FIX | 改正参数再试 | 邮箱格式不对 |
TERMINAL | 放弃,报告给人类 | 没有权限 |
REQUIRES_HUMAN | 暂停,等人类决定 | 金额超限需审批 |
一个完整的错误响应示例:
{
"error": {
"category": "RETRYABLE_AFTER_FIX",
"code": "INVALID_PARAM",
"param": "email",
"constraint": "must be valid email format",
"received": "not-an-email",
"fix_hint": "Apply email validation regex before retry"
}
}
逐字段解释:
category— 告诉 Agent 这是什么类型的错误(可修复后重试)param— 具体哪个参数有问题constraint— 这个参数的规则是什么received— 你传了什么值fix_hint— 怎么修
Agent 读完这个响应,能精确地修正 email 字段后重试。不需要任何人介入。
实践二:暴露状态机
状态机(State Machine)是什么?就是”资源从一个状态到另一个状态的合法路径图”。
类比:快递物流追踪。你在 App 上不仅看到”运输中”,还能看到后面可能的状态——“派送中”或”退回”。你知道包裹接下来会走哪条路。
{
"current_state": "building",
"state_machine": {
"building": { "next": ["ready", "failed"], "timeout_ms": 300000 },
"ready": { "next": ["deploying"], "actions": ["deploy"] },
"failed": { "next": ["building"], "actions": ["retry_build"] }
}
}
这段告诉 Agent:
- 现在是
building状态 - 可能变成
ready或failed - 最多等 5 分钟(300000ms)
- 如果失败了,可以执行
retry_build回到building
有了这张”地图”,Agent 能提前规划——“如果失败我就重试,如果成功我就部署”——而不是走一步看一步。
实践三:安全边界与人类兜底
Agent 不应该拥有的能力:
- 不可逆的批量删除(删了就没了)
- 无限额的资金操作(转一个亿)
- 修改自身权限(给自己提权)
当 Agent 触碰边界时,API 返回结构化的”请示”响应:
{
"action_result": "REQUIRES_APPROVAL",
"reason": "Amount $15,000 exceeds agent limit of $10,000",
"approval_request": {
"expires_at": "2026-05-19T11:00:00Z",
"approve_url": "/approvals/apr_456/approve",
"reject_url": "/approvals/apr_456/reject"
},
"agent_should": "PAUSE_AND_WAIT"
}
agent_should: "PAUSE_AND_WAIT" — 这五个字就是给 Agent 的明确指令:别动,等人来决定。
实践四:上下文预算友好
Agent 的”大脑”(context window)有容量限制。一个返回 200 个字段的响应会浪费大量”脑容量”。
类比:你问路人”附近有吃的吗”,他把方圆 5 公里所有餐厅的完整菜单念给你——这就是不友好的 API。好的回答是”前面 100 米有家面馆”,想看菜单你再去看。
做法:
- 默认返回精简信息(
?fields=id,status,next_actions) - 分页用游标(cursor)不用页码——Agent 不记页码
- 详情给链接,不内联
误区:六个常见错误
| 你以为没问题的做法 | 为什么对 Agent 有毒 |
|---|---|
| HTTP 200 里藏业务错误 | Agent 看 status code 是 200,以为成功了 |
| 同一字段有时是 string 有时是 object | Agent 解析直接崩溃 |
分页没有 has_more: false | Agent 会无限翻页,永远不停 |
| 错误信息只有人话 “请稍后再试” | 机器无法解析”稍后”是多久 |
| 随意新增枚举值 | Agent 的 switch-case 遇到未知值就炸 |
| 没有幂等保证 | Agent 重试一次,数据库多一条重复记录 |
总结
API 设计正在经历一次范式转移:
旧范式:让人类读懂文档 → 人类做决策 → 人类写代码调用
新范式:让机器从响应中推理 → 机器自主决策 → 机器自主执行
三句话记住核心:
- 错误要可行动 — 告诉 Agent 下一步做什么,不是告诉它发生了什么
- API 要自描述 — 响应本身就是文档,包含所有可选动作
- 操作要幂等 — 重试多少次结果都一样
最终洞察:
最好的 Agent-Friendly API 同时也是最好的 Human-Friendly API——因为消除歧义对所有消费者都有益。
FAQ
Q: 我的 API 只给内部用,也需要 Agent-Friendly 吗?
A: 取决于你的内部工具链。如果你已经在用 Cursor、Claude Code、GitHub Copilot 这类 AI 工具调用内部 API,那它们本质上就是 Agent。结构化错误和幂等性在任何场景下都是好实践,不亏。
Q: 改造现有 API 成本大吗?
A: 分阶段来。Phase 1 只需要改错误响应格式和加 Idempotency-Key 支持——这两个改动向后兼容,不影响现有调用方。
Q: Agent-Friendly 和 RESTful 冲突吗?
A: 完全不冲突。Agent-Friendly 是在 RESTful 基础上的增强——HATEOAS(超媒体)本身就是 REST 的最高级别,只不过以前没人真正落地,现在 Agent 时代终于有了刚需。
Q: 所有 API 都需要暴露状态机吗?
A: 不需要。只有涉及多步骤流程的资源(订单、部署、审批)才需要。简单的 CRUD 操作做好错误分类和幂等就够了。
Q: 参考哪些现有 API?
A: Stripe(幂等性和结构化错误的标杆)、GitHub API(HATEOAS 链接和透明的速率限制)、Anthropic Tool Use(tool schema 设计)。