Skip to content

LLM Agent 如何进行动态 API 调用? ​

  • 标签:大模型、AI、Agent

🏛 业务架构师 ​

Agent 动态调用 API 的机制,核心是"工具描述注入+模型结构化决策+运行时执行"三段:

1. 工具注册:把 API 封装成工具,向 Agent 声明三要素——名称、自然语言描述(干什么用、什么时候用)、参数 JSON Schema。2026 年的标配做法是 MCP 协议:API 方发布 MCP Server,Agent 侧自动发现工具清单。

2. 动态决策:用户任务进入后,模型结合所有工具的描述判断"这一步需要调哪个 API、传什么参数",输出结构化调用意图(工具名+参数 JSON)——这就是 Function Calling 能力,模型不执行任何东西,只出"调用指令"。

3. 运行时执行:Agent 框架接住调用意图,真正发起 HTTP 请求(带鉴权、超时、重试),把响应摘要回填给模型,模型继续决策下一步。

"动态"的业务价值:相比写死的集成代码,模型按任务临场选择和编排 API——同一个 Agent 今天查订单、明天对账单,不需要改代码。新增能力只需注册新工具。

工程与治理要点(生产化的关键):工具描述质量决定选对率,要像写产品说明书一样打磨;调用要过权限网关(谁能调、限流、审计);返回结果可能超大要做截断摘要保护上下文窗口;写操作要幂等+确认防重复执行。动态调用放大的不仅是能力,还有风险面。

🏗 系统架构师 ​

动态 API 调用的完整机制是**"注册 → 发现 → 决策 → 执行 → 回填"**五段,我拆开讲:

  • 注册:工具进系统时声明 name、description、inputSchema(JSON Schema)、权限级别、幂等性——描述是写给模型看的 API 文档,质量决定准确率;
  • 发现与注入:运行时按场景加载工具子集(不是全量塞给模型——工具太多稀释选择准确率),schema 转成模型可读的工具定义随请求下发;
  • 决策:LLM 结合任务与工具描述输出结构化调用意图 {tool: search_order, args: {...}}——模型只产生意图,不直接执行,这是安全边界;
  • 执行:框架层校验参数(Schema validation)→ 权限检查 → 真实调用(HTTP/RPC/MCP);失败返回结构化错误供模型改道;高危/非幂等操作挂人工审批;
  • 回填与迭代:结果作为 tool message 回上下文,模型决定继续调用、换工具或产出答案。

动态性设计:工具列表按用户权限和任务上下文过滤(动态裁剪);OpenAPI 规范可自动转工具定义(存量 API 快速接入);结果超大时摘要压缩再回填。

架构要点:执行层的超时、重试、幂等键、限流是分布式系统老三样,一样不能少——模型决策的不确定性之下,工程层的确定性兜底是生产可用的前提。

💻 全栈开发专家 ​

动态 API 调用指 Agent 运行时按需选择并调用 API,而不是写死流程。实现链路:

1. 工具注册(把 API 变成工具):每个 API 的名字、描述、参数 JSON Schema 注册进工具表。基于 OpenAPI 可自动生成:

java
@Tool(description = "查询订单物流状态,返回承运商与轨迹")
public LogisticsVO trackOrder(@ToolParam(description = "订单号,如 A123") String orderId) {
    return logisticsClient.track(orderId);
}

2. 模型选择:用户消息 + 工具列表喂给 LLM,模型输出 tool call(工具名+参数 JSON)——「动态」就体现在这一步由模型实时决策。

3. 执行保障(生产的关键):JSON Schema 校验参数(模型会幻觉出非法参数)→ 鉴权(带上用户级 token,做数据隔离)→ 超时重试 → 结果压缩成模型友好的摘要。

4. 工具太多时:工具检索(RAG for tools)。几十上百个工具全塞 prompt 会爆 token 且选择准确率下降。做法:工具描述做 Embedding 入库,用户 query 先检索出 top-5 相关工具再注入——这是工具规模化的标准解法。

踩坑记录:工具描述写「查询信息」这种空话模型必然选错,要写清楚「什么场景用、和相邻工具的区别」;返回值不要直接透传大 JSON,先裁剪字段;写操作工具必须幂等(带 idempotency key),模型重试是常态。