Skip to content
imshengli blog
Go back

当 AI 成为你的 API 用户:Agent-Friendly API 设计指南

你的 API 将不再只服务人类开发者——AI Agent 正在成为新的调用方。本文用类比和实例,从零讲清如何设计让 AI 能自主决策的 API。

· 10 min

先说结论

如果你今天设计的 API,只能靠人类读文档才能用对,那它在 Agent 时代就是残废的。

一个好的 Agent-Friendly API 需要满足三点:

  1. 错误响应能指导下一步行动(不是 “Something went wrong”)
  2. API 自己会说话(不需要翻文档就知道能干什么)
  3. 重复调用不会出事(幂等性)

下面我从”为什么需要”讲到”怎么做”,全程带类比和代码示例。


问题:API 的用户变了

想象你开了一家餐厅。以前的顾客都是人——看菜单、问服务员、自己决定吃什么。

现在来了一个机器人顾客。它不会问服务员,不会看墙上的推荐,只会读菜单上的字。如果菜单写”今日特色”但没写具体是什么菜,人类会喊服务员问,机器人直接卡住。

这就是 AI Agent 调用传统 API 时的困境:

核心矛盾:传统 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 四件事:

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"
  }
}

逐字段解释:

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:

有了这张”地图”,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 米有家面馆”,想看菜单你再去看。

做法:


误区:六个常见错误

你以为没问题的做法为什么对 Agent 有毒
HTTP 200 里藏业务错误Agent 看 status code 是 200,以为成功了
同一字段有时是 string 有时是 objectAgent 解析直接崩溃
分页没有 has_more: falseAgent 会无限翻页,永远不停
错误信息只有人话 “请稍后再试”机器无法解析”稍后”是多久
随意新增枚举值Agent 的 switch-case 遇到未知值就炸
没有幂等保证Agent 重试一次,数据库多一条重复记录

总结

API 设计正在经历一次范式转移:

旧范式:让人类读懂文档 → 人类做决策 → 人类写代码调用

新范式:让机器从响应中推理 → 机器自主决策 → 机器自主执行

三句话记住核心:

  1. 错误要可行动 — 告诉 Agent 下一步做什么,不是告诉它发生了什么
  2. API 要自描述 — 响应本身就是文档,包含所有可选动作
  3. 操作要幂等 — 重试多少次结果都一样

最终洞察:

最好的 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 设计)。


Share this post on:

Previous Post
你可能只用了 Claude Code 20% 的功能
Next Post
AI 原住民开发者:当编程遇上大模型