跳到正文

Agent 工具调用链路怎么搭?

从指令解析到错误处理,全流程实现与关键设计

原题:在基于大语言模型的智能体(LLM Agent)系统中,如何构建一个完整的工具调用链路?请描述从用户指令解析、工具选择、参数提取、API调用到结果反馈和错误处理的全流程实现方式。

Prompt工程 · 美团真题

30 秒回答

  1. 工具描述Schema设计(OpenAI格式)
  2. 意图识别与工具选择的Prompt工程
  3. 参数提取的约束与校验机制
  4. API执行的安全隔离与超时控制

回答与解析

答案要点

  • 工具描述Schema设计(OpenAI格式)
  • 意图识别与工具选择的Prompt工程
  • 参数提取的约束与校验机制
  • API执行的安全隔离与超时控制
  • 结果回传与对话上下文的维护
  • 错误分级处理与优雅降级策略

完整工具调用链路设计

1. 工具注册与描述(前置层)

  • 每个工具按 OpenAI Function Calling Schema 注册:name/description/parameters(required字段)
  • 关键:description要清晰说明工具能力边界,避免模型误选

2. 意图识别与工具选择

Prompt设计要点:
- 系统Prompt明确角色定位:"你是工具调度助手,从以下工具中选择..."
- 提供工具列表 + 当前对话上下文
- 强制输出格式:{"tool": "xxx", "reason": "..."} 或 直接走Function Call
  • 复杂场景可用 两阶段:先意图分类,再细选工具

3. 参数提取与校验

  • 结构化抽取:利用模型JSON输出能力,严格按schema生成参数
  • 校验层:类型检查、必填项检查、业务规则校验(如日期格式)
  • 失败处理:校验失败时把错误信息回传模型,要求重新生成

4. API执行与隔离

  • 沙箱执行:工具代码运行在隔离环境,限制网络/文件访问
  • 超时控制:设置硬超时(如5s),防止阻塞
  • 异步设计:重IO工具走异步队列,避免阻塞主链路

5. 结果回传与上下文维护

  • 工具返回结果 → 格式化为自然语言 → 注入对话历史
  • 关键:保留原始调用记录(tool_call_id),支持多轮工具链

6. 错误处理策略(分层)

层级 处理方式
参数错误 回传模型自纠正,限3次
工具执行失败 返回错误摘要,询问用户或切换备选工具
系统异常 优雅降级:直接回复"该功能暂不可用"

7. 进阶:ReAct模式扩展

Thought → Action(工具调用) → Observation → ... → Final Answer
  • 适合多步推理场景,每步显式输出思考过程

口语版讲法(约4分钟)

  • 一句话定位:本质是让模型学会用工具,不是简单的API调用
  • 前置设计:工具注册与Schema要写对,否则模型选错
  • 核心流程:意图识别、参数提取、执行与错误处理
  • 边界与风险:ReAct适合多步,Function Calling适合单步,落地要混合
  • 收尾与可延伸点:错误处理的分层策略,追问会引向自纠正机制

这个问题问的是工具调用链路,本质上就是在解决一个问题:怎么让大语言模型能准确地去调用外部工具,同时保证整个过程可控、可容错。它不是一个简单的API调用,而是一个从理解用户意图到最终返回结果的完整闭环。

先说前置设计。工具注册这块,我一般会用OpenAI的Function Calling Schema来定义每个工具,把name、description、parameters都写清楚。这里有个关键点:description一定要写到位,不能太含糊。比如一个查询订单的工具,你要是只写“查询订单”,模型可能就会在用户说“帮我查一下”的时候选它,但实际上用户想查的是物流状态,不是订单信息。所以description要精确描述工具的能力边界,不然模型很容易选错。

接下来是核心流程,我把它分成几步。第一步是意图识别和工具选择。系统Prompt里我会明确告诉模型它的角色是工具调度助手,然后给出当前可用的工具列表和对话上下文。输出格式我会强制成JSON,比如{"tool": "xxx", "reason": "..."},或者直接用Function Call。如果场景比较复杂,比如用户问“帮我安排下周的会议并通知参会人”,这就涉及两个工具,我会考虑用两阶段:先做意图分类,判断是要安排会议还是通知人,然后再细选工具。

第二步是参数提取和校验。模型输出参数的时候,我会利用它的JSON输出能力,严格按照Schema生成。但模型有时候会漏掉必填参数或者格式不对,比如日期写成了“明天”,工具需要的是“2025-03-28”。所以我会加一个校验层,做类型检查、必填项检查,还有业务规则校验。校验失败的时候,我不会直接报错,而是把错误信息回传给模型,让它重新生成。这样一般两三次就能纠正过来。

第三步是API执行。这块有一个重要的落地风险:安全隔离。工具代码一定要跑在沙箱里,限制网络和文件访问,不然恶意输入可能导致数据泄露。另外超时控制也很关键,我会设一个硬超时,比如5秒,防止模型死循环或者工具卡住。对于重IO的工具,比如要查数据库或者调外部API,我会设计成异步队列,避免阻塞主链路。

执行完拿到结果后,需要把结果格式化成自然语言,注入到对话历史里。同时要保留原始调用记录,比如tool call id,这样支持多轮工具链。比如用户先查了库存,发现不够,又让调货,这两步就能串起来。

这里我想说一下边界划分。ReAct模式适合多步推理的场景,比如用户问“帮我比较一下这两款手机的参数,然后推荐一个”,模型需要先查参数,再对比,再推荐,每一步都要显式输出思考过程。而Function Calling更适合单步、确定性的调用,比如“查一下明天北京的天气”。真正落地的时候,我通常会把两者结合起来:简单查询直接用Function Calling,复杂推理走ReAct,这样既高效又灵活。

最后是错误处理,我一般会做分层。参数级别的错误,比如格式不对,我会让模型自纠正,限制三次。工具执行失败,比如API返回500,我会把错误摘要返回给模型,让它询问用户或者切换备选工具。系统级别的异常,比如沙箱挂了,我就直接降级,回复用户“该功能暂不可用”。

这里有个值得深挖的点:错误处理中的自纠正机制。如果模型连续三次都生成错误的参数,比如一直把日期格式写错,这时候是继续让它重试还是直接报错?我的做法是看错误类型:如果是模型能力问题,比如它就是不理解日期格式,我会考虑给它few-shot示例;如果是工具本身的问题,比如参数设计不合理,那我会反过来优化Schema。

所以整体上,我会把工具调用链路看成是一个从意图到执行的工程化系统,核心是让模型在可控范围内发挥能力,同时做好兜底。

关键一句:错误处理中的自纠正机制:连续三次参数错误时,根据错误类型决定是给few-shot示例还是优化Schema。

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设你在做一个智能客服Agent,用户说‘帮我查一下上周三的订单,如果没发货就催一下’。这背后涉及解析指令、选查询工具、抽参数、调API,再把结果反馈回去。你整个链路会怎么设计?

  2. 问法 2 · 层层追问

    用户让Agent调用工具时,你怎么知道该调哪个工具?……参数怎么从自然语言里准确抽出来?……调用失败了怎么办,比如接口超时或者参数不对?……从指令到结果,整个流程你一步步讲一下。

  3. 问法 3 · 直球架构

    设计一个LLM Agent的完整工具调用链路,从用户指令解析、工具选择、参数提取、API调用到结果反馈和错误处理,描述清楚每一步的实现方式。

同模块相关题目