技术博客
LLM 大语言模型AI Agent理解与问答推理优化工具

如何设计Agent友好的API/CLI?

NOTA62026-08-13 17:10
如何设计Agent友好的API/CLI?

过去我们设计 CLI 和 API,默认使用者是人,或者是一段已经写好的程序。

人会看文档,会理解业务,也知道 customer.owner = alice 的实际含义是“把这个客户分配给 Alice”。程序则更简单,工程师提前把逻辑写死,它只负责执行。

但是Agent 不一样。Agent 需要在运行过程中自己理解系统有什么能力,判断应该调用什么,填写参数,观察结果,遇到失败还要决定下一步怎么办

所以,真正对 Agent 友好的 CLI 或 API,不只是“支持 JSON”,也不只是“接入 MCP”,而是要让 Agent 能稳定完成一个闭环:

Discover → Understand → Act → Verify → Recover,

这五步基本可以解释 Agent-friendly interface 的全部核心。

1. Agent更容易发现能力:Discover

Agent 首先要知道:这个系统到底能做什么。

传统 CLI 往往只有:

tool --help

这主要是给人看的。然而,Agent 需要的是机器可读的能力目录,例如:

crm capabilities --json

返回:

{
  "actions": [
    "search_customer",
    "assign_customer_owner",
    "activate_customer",
    "close_opportunity"
  ]
}

它不应该先读几十页文档,再猜哪个命令能完成任务。

API 也是一样。传统 API 往往从资源出发:

GET /customers
PATCH /customers/:id
POST /orders

人知道这些 endpoint 背后的含义,但 Agent 真正关心的是:

“我能不能分配客户?”
“我能不能关闭商机?”
“我能不能取消订单?”

所以对 Agent 来说,更好的能力暴露方式是直接告诉它:

assign_customer_owner
close_opportunity
cancel_order

这就是 Discover 的关键:能力要显式,而不是隐藏在数据结构和文档里。

2. Agent更容易理解能力:Understand

发现一个动作以后,Agent 还必须知道:这个动作到底意味着什么。

比如一个接口叫:

update_customer(id, value)

虽然参数很简单,但对 Agent 并不好。

因为它不知道 update 什么,也不知道 value 代表什么,更不知道调用以后会产生什么副作用。

如果换成:

assign_customer_owner(
  customer_id,
  owner_id
)

语义就完全不同了。

Agent 可以直接理解这是:“把一个客户分配给某个销售负责人。”

再进一步,一个更好的 Action Contract 还应该告诉它:

intent:
  Assign a customer to a sales representative.

preconditions:
  customer.status: active
  owner.status: active

effect:
  customer.owner_id changes

过去 API schema 主要回答:**参数是什么类型。**Agent 时代还必须回答:**这个动作什么时候应该用,会发生什么。**也就是说,schema 开始从“类型系统”变成“语义系统”。

3. Agent更容易执行能力:Act


Act 执行过程中的关键是Agent 实际执行的动作,应该尽量贴近业务意图。

举一个最典型的例子。假设系统里有一个客户:

{
  "id": "cus_123",
  "name": "Acme",
  "status": "active",
  "owner": "bob"
}

现在希望把它分配给 Alice。传统 REST API 很可能是:

PATCH /customers/cus_123

传入:

{
  "owner": "alice"
}

这里的 PATCH 意思是:修改 customer 资源的一部分字段。

对程序员来说,这很自然。因为程序员知道:

修改 owner 字段
=
把客户分配给 Alice

但 Agent 要自己完成一次额外推理:

我要把客户分配给 Alice
↓
分配客户意味着修改 customer
↓
要修改的是 owner 字段
↓
owner 填 Alice 的 ID
↓
调用 PATCH customer

真正对 Agent 友好的接口可以直接是:

assign_customer_owner(
  customer_id="cus_123",
  owner_id="alice"
)

于是整个过程变成:

我要把客户分配给 Alice
↓
assign_customer_owner

底层可能仍然只是执行一次数据库更新,区别只在于业务语义被接口承担了,而不是被 Agent 推理出来。这就是为什么 Agent 时代很多接口会从 Resource-centric 逐渐走向 Action-centric。

过去喜欢:

PATCH customer
PATCH order
PATCH invoice

未来更适合 Agent 的是:

assign_customer_owner
cancel_order
approve_invoice

前者描述“修改什么数据”。后者描述“完成什么事情”。

这并不意味着传统 REST API 不好了。完全可以同时存在两层:

底层:
PATCH /customers/:id

Agent 层:
assign_customer_owner

就像我们不会让 Agent 为了转账,自己执行:

UPDATE account_a ...
UPDATE account_b ...

而更愿意给它一个:

transfer_money(...)

因为事务、权限、约束和正确性应该尽量由系统承担,而不是交给 Agent 自己拼。

4. Agent更容易验证结果:Verify

完成 Act 以后,下一步是 Verify。

这一层特别容易被忽略。很多 CLI 做完事情以后只返回:

Success!

对人类程序员来说似乎够了。但 Agent 会继续产生几个问题:

  • 到底改了什么?

  • 真的发生变化了吗?

  • 之前是什么状态?

  • 现在是什么状态?

所以更好的返回应该是:

{
  "status": "success",
  "customer_id": "cus_123",
  "previous_owner": "bob",
  "new_owner": "alice",
  "changed": true
}

这样 Agent 一次调用以后,就能确认结果。

一个非常重要的原则是:

Agent 调用 write action 后,最好不用再额外调用一次 read action,只为了确认刚才是否成功。

也就是说,执行结果本身应该具有可验证性。

CLI 也一样。一个 Agent-friendly CLI 最好明确区分:

stdout = 结构化执行结果
stderr = 日志和诊断信息
exit code = 成功或失败状态

而不是把进度条、warning、日志和最终结果全部混在一起。

5. Agent如何从错误中恢复执行:Recover

这一层可能是 Agent-friendly API 和普通 API 差别最大的地方。

传统错误定义经常是:

{
  "error": "Invalid request"
}

或者:

{
  "error": "Customer status invalid"
}

人看到以后会去看文档。Agent 看到以后只能继续猜。

对于Agent更好的错误定义和描述应该是:

{
  "code": "CUSTOMER_NOT_ACTIVE",
  "message": "Owner can only be assigned to an active customer.",
  "retryable": false,
  "required_action": "activate_customer"
}

这样 Agent 可以立即形成下一步:

assign_customer_owner
↓
CUSTOMER_NOT_ACTIVE
↓
activate_customer
↓
assign_customer_owner

这时候错误信息就不再只是“报错”,它实际上是 Agent 执行路径的一部分。

所以 Recover 的核心并不是“错误写得更详细”,而是:错误必须可指引行动。

Agent 应该知道:

  • 为什么失败;

  • 能不能重试;

  • 缺什么前置条件;

  • 应该调用哪个动作恢复。

如果把这五层连起来看,一个真正 Agent-friendly 的接口就非常清晰了。

Discover
系统能做什么?
↓  
Understand
每个动作是什么意思?
↓
Act
用最接近业务意图的动作执行
↓
Verify
执行以后明确知道发生了什么
↓
Recover
失败以后知道下一步怎么走

它最终形成的就不只是 API Schema,而是一份完整的 Agent Action Contract

例如:

name: assign_customer_owner

description:
  Assign a customer to a sales representative.

input:
  customer_id: string
  owner_id: string

preconditions:
  customer.status: active
  owner.status: active

effect:
  customer.owner_id changes

idempotent:
  true

output:
  customer_id: string
  previous_owner_id: string
  owner_id: string
  changed: boolean

errors:
  CUSTOMER_NOT_ACTIVE:
    retryable: false
    next_action: activate_customer

  OWNER_NOT_ACTIVE:
    retryable: false
    next_action: select_active_owner

这里实际上已经把 Discover、Understand、Act、Verify、Recover 都包含进去了。

namedescription 帮助 Discover 和 Understand。

inputpreconditionseffect 定义 Act。

output 支撑 Verify。

errorsnext_action 支撑 Recover。

6. 总结:Agentic Action Contract

所以我越来越觉得,未来 CLI、REST API、SDK 和 MCP 不应该被完全分开设计。真正的 one source of truth 可以是一份统一的 Action Contract。

比如系统先定义:

assign_customer_owner

然后由它生成:

CLI:
crm customer assign-owner

HTTP:
POST /customers/:id/assign-owner

SDK:
crm.assignCustomerOwner(...)

MCP:
assign_customer_owner

表面上是四种接口。本质上是同一个业务动作。这是一种很深的变化。过去的软件接口主要围绕:**数据模型。**Agent 时代的软件接口,会越来越围绕:能力模型。

过去我们问:

  • “有哪些资源,我可以怎样修改它?”

  • 未来更重要的问题会变成:

  • “这个系统到底能完成哪些动作?”

而判断一个 CLI 或 API 是否真正对 Agent 友好,也可以直接沿着这五步去看:

  • Agent 能不能发现能力,

  • 能不能理解语义,

  • 能不能低风险执行,

  • 能不能确认结果,

  • 失败以后能不能继续。

如果这五步都成立,那么这个接口系统就不只是“提供了 API”。

它开始真正成为一个 Agent 可以工作的环境

点赞收藏
// 评论0
0 / 500
还没有评论,快来抢沙发