Agent工具调用怎么选?LangChain、Function Calling与工作流编排
开发者实战指南:厘清LangChain Tools、Function Calling与工作流编排的职责,掌握工具定义、参数Schema、工程评测与多模型接入。

一、Agent 工具调用为什么成为开发重点?
当大模型应用从聊天问答走向自动化执行,开发者面对的问题也随之发生变化。传统聊天应用主要负责接收输入、生成文本,而 AI Agent 还需要根据任务选择工具、获取外部信息、执行操作,并根据执行结果决定下一步。
例如,用户要求 AI 助手分析某个产品的销售表现。普通聊天模型可以提供分析思路,但要得到真实的销售数据,应用还需要查询数据库;要计算增长率,需要执行计算逻辑;要生成报表,还需要调用文件处理或业务系统接口。
这就是 Agent 工具调用的实际价值:将模型的理解与决策能力连接到外部程序,使 AI 应用能够完成超出文本生成范围的任务。
从技术实现来看,开发者经常接触三个概念:LangChain Tools、Function Calling 和工作流编排。它们之间存在联系,但并不是可以直接互换的三种工具。
Function Calling 主要描述模型如何提出结构化的函数调用请求;LangChain Tools 为工具提供统一的定义和执行接口;工作流编排则负责组织多个步骤之间的执行顺序、状态传递和异常处理。
选型时,应当先明确应用需要解决的问题,再决定采用哪一层技术,而不是单纯比较框架的知名度或工具数量。
二、Agent 工具、Function Calling 与普通问答有什么区别?
1. 普通大模型问答
普通问答通常由模型根据用户输入和已有上下文生成回答。它适合内容生成、文本归纳、知识解释等任务。
但当问题依赖实时数据或外部操作时,模型无法仅凭语言生成能力保证结果准确。例如,用户询问某个订单是否已经发货,模型不能通过猜测得到真实订单状态。
2. Function Calling:让模型提出结构化调用请求
Function Calling 通常指模型根据工具定义,生成一个包含函数名称和参数的调用请求。
假设应用向模型提供一个 get_order_status 函数,并说明该函数需要 order_id 参数。当用户要求查询订单时,模型可以返回函数名称及对应参数。
需要强调的是,模型生成调用请求,并不代表外部函数已经执行。应用程序仍需接收请求、验证参数、调用实际业务逻辑,再将执行结果返回模型。
3. LangChain Tools:统一定义和管理工具
LangChain Tools 是框架提供的工具抽象。开发者可以将 Python 函数封装成工具,为其指定名称、描述、参数类型和执行逻辑,再将工具交给支持工具调用的聊天模型。
例如,查询订单、搜索知识库和计算退款金额,都可以封装为独立工具。
LangChain 还提供 Agent 创建机制,使模型能够根据用户需求决定何时调用工具,并在得到工具结果后继续处理任务。
4. 工作流编排:控制多个步骤如何衔接
当任务涉及多个步骤时,仅仅定义工具还不够。
例如,企业报销助手可能需要:
- 读取用户提交的报销信息。
- 检查票据字段是否完整。
- 查询企业报销规则。
- 根据规则进行金额核验。
- 将结果提交给审批人员。
- 根据审批结果更新业务状态。
在这种场景下,工作流需要控制执行顺序、条件分支、状态传递和失败处理。模型可以参与部分步骤的判断,但不必将每个步骤都交给模型自由决定。
LangGraph 可以用于构建具有状态管理、条件分支和人工介入能力的复杂流程。对于简单任务,LangChain 的 Agent 创建接口通常已经足够;需要更精细的流程控制时,再考虑使用 LangGraph。
三、LangChain Tools 与 Function Calling 怎么选?
这两者并不是直接竞争关系。Function Calling 解决模型如何表达工具调用意图的问题,LangChain Tools 则帮助开发者组织工具定义与执行逻辑。
表格
| 对比维度 | Function Calling | LangChain Tools | 工作流编排 |
|---|---|---|---|
| 核心职责 | 生成结构化调用请求 | 定义和执行工具 | 管理任务步骤与状态 |
| 参数定义 | 通常通过 JSON Schema 等结构描述 | 支持类型注解、Pydantic 等方式 | 取决于节点及流程设计 |
| 工具执行 | 通常由应用程序负责 | 可由 Agent 或应用流程组织执行 | 由流程节点和执行规则控制 |
| 多步骤任务 | 需要应用自行组织循环 | 可结合 Agent 实现连续调用 | 适合明确或复杂的多步骤流程 |
| 灵活性 | 取决于模型接口与应用实现 | 取决于工具和模型集成 | 取决于流程设计 |
| 适用场景 | 自行构建模型工具调用机制 | 快速搭建工具型 Agent | 企业流程、条件分支和状态管理 |
因此,如果开发者希望直接控制模型请求、工具协议和调用循环,可以采用模型提供商的原生接口;如果希望减少工具封装和 Agent 组织工作,可以使用 LangChain;如果业务具有明确的步骤、分支和审批要求,则应重点考虑工作流编排。
实际项目也可以组合使用这些技术。例如,使用 LangChain 定义工具,以模型 Function Calling 生成调用请求,再由 LangGraph 管理复杂任务的状态与执行顺序。
四、LangChain Tools 实战:从定义工具到运行 Agent
下面以一个商品查询场景为例,演示如何定义工具并交给模型调用。
1. 安装依赖
在 Python 环境中,可以安装 LangChain 及对应的模型集成包:
pip install -U langchain langchain-openai实际使用时,还需要配置模型提供商的 API 凭证,并确认所使用的模型支持工具调用。
2. 使用 @tool 定义工具
from langchain.tools import tool
@tool
def search_product(keyword: str) -> str:
"""根据商品关键词查询商品信息。"""
# 这里用固定文本演示工具调用
# 生产环境应接入真实商品数据库或搜索服务
return f"已收到商品查询请求:{keyword}"@tool 装饰器将函数封装为 LangChain Tool。
这里的 search_product 是工具名称,keyword 是输入参数,文档字符串用于说明工具用途。LangChain 可以根据函数签名和类型注解生成相应的参数结构。
需要注意,当前函数只是返回固定文本,并未真正查询商品数据库。生产环境应将其替换为真实业务逻辑,并添加参数校验、权限检查及异常处理。
3. 将工具交给模型
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="your-tool-capable-model",
temperature=0
)
model_with_tools = model.bind_tools([
search_product
])
response = model_with_tools.invoke(
"帮我查询无线耳机的商品信息"
)
print(response.tool_calls)这里的 your-tool-capable-model 是占位符,需要替换成当前账户和模型服务实际支持的模型标识。
bind_tools() 会将工具定义提供给模型。模型可能返回包含工具名称、参数和调用标识的结构化请求,但是否产生工具调用仍取决于模型能力、请求内容和工具选择配置。
此处还没有执行 search_product。如果只调用 bind_tools() 和 invoke(),开发者应检查 response.tool_calls,不能假设函数已经运行。
4. 使用 Agent 组织完整调用流程
对于需要模型选择工具并根据结果继续回答的任务,可以使用 LangChain 的 Agent 接口。
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain.tools import tool
@tool
def search_product(keyword: str) -> str:
"""根据关键词搜索商品信息。"""
return f"商品搜索结果:{keyword},示例数据"
model = ChatOpenAI(
model="your-tool-capable-model",
temperature=0
)
agent = create_agent(
model=model,
tools=[search_product],
system_prompt="使用工具获取信息,并根据工具结果回答用户。"
)
result = agent.invoke({
"messages": [
{
"role": "user",
"content": "查询无线耳机的商品信息"
}
]
})
print(result["messages"][-1].content)这段代码展示了基本结构。执行前应确认安装的 LangChain 版本支持相应接口,并正确配置模型凭证。
Agent 会组织模型请求、工具调用和结果回传等步骤。具体执行结果取决于实际模型、工具实现及运行环境,不能将示例代码视为已经连接真实商品系统的完整应用。
五、参数 Schema 为什么会影响 Agent 的可靠性?
工具调用失败,并不一定意味着模型能力不足。参数设计不合理,同样会导致模型无法正确使用工具。
例如,一个退款计算工具可能需要订单编号、退款原因和商品金额。如果开发者只将函数定义为接收一个普通字符串,模型就可能将多个字段混在一起,增加后续解析和校验的难度。
更合理的做法是使用结构化参数。
from pydantic import BaseModel, Field
from langchain.tools import tool
class RefundInput(BaseModel):
order_id: str = Field(
description="需要查询的订单编号"
)
amount: float = Field(
gt=0,
description="申请退款金额,必须大于零"
)
@tool(args_schema=RefundInput)
def calculate_refund(
order_id: str,
amount: float
) -> str:
"""根据订单编号和申请金额执行退款金额核验。"""
return f"订单 {order_id} 的申请金额为 {amount}"这段示例使用 Pydantic 定义输入字段,并对金额设置大于零的约束。但它只演示参数结构,并未验证订单真实性、账户权限或企业退款规则。
在生产环境中,应当将 Schema 校验与业务校验分开处理:
- Schema 校验:检查类型、必填字段和数值范围。
- 业务校验:确认订单存在、金额合法、用户拥有相应权限。
- 执行校验:确认操作是否允许重复提交,以及是否需要人工确认。
结构化参数可以减少格式错误,却不能代替完整的业务安全机制。
六、Agent 工具调用的工程评测:哪些指标值得关注?
判断一套 Agent 工具方案是否适合生产环境,不能只看它是否能够成功调用函数。至少应从以下维度开展测试。
表格
| 评测维度 | 建议测试方法 | 关注结果 |
|---|---|---|
| 工具选择准确性 | 为不同工具设计一组典型问题 | 是否选择正确工具 |
| 参数准确性 | 测试缺失信息、歧义输入和边界值 | 参数错误率 |
| 执行成功率 | 模拟接口超时、权限错误和服务故障 | 成功率与失败类型 |
| 多步骤完成率 | 设计需要连续调用多个工具的任务 | 流程完成情况 |
| 兼容性 | 使用不同模型重复执行同一测试集 | 调用格式及行为差异 |
| 响应延迟 | 记录模型请求和工具执行耗时 | 平均延迟及高分位延迟 |
| 调用成本 | 记录模型使用量、工具调用和重试情况 | 单任务总成本 |
| 安全性 | 测试越权请求、恶意输入和重复操作 | 权限拦截与异常处理结果 |
建议为每个测试场景准备固定输入、预期工具、预期参数和结果判定规则。对关键业务任务,还应检查最终结果是否符合业务事实,而不只是判断模型有没有调用工具。
不同模型、提示词和工具定义可能带来不同结果。在没有实际测试数据的情况下,不应直接宣称某个框架具有更高成功率或更低延迟。
七、多模型 API 接入:Agent 开发中容易忽略的问题
当一个 Agent 只使用单一模型时,开发者主要需要关注模型配置、工具调用协议和业务逻辑。但当项目需要测试多个模型时,工程复杂度往往会进一步增加。
不同模型可能在工具调用格式、参数约束、上下文长度、流式响应和错误处理方面存在差异。即使两个模型都支持 Function Calling,也不意味着它们能够在所有工具场景下无差别替换。
因此,建议将应用拆分为三个层次:
第一层:Agent 业务层。 负责用户输入、工具定义、任务流程和业务校验。
第二层:模型接入层。 负责模型选择、接口配置、凭证管理、请求发送和响应处理。
第三层:外部工具层。 负责数据库查询、业务 API 调用、文件操作以及其他真实执行任务。
这样的架构可以降低模型配置与业务逻辑之间的耦合。但在切换模型时,仍需要执行兼容性测试,不能只修改一个模型名称就认定整个应用已经完成迁移。
对于需要评估多个模型的开发团队,可以考虑采用统一 API 接入方案。例如,KoalaAPI 作为 API 中转站,可以纳入多模型接入方案的评估范围。开发者应结合平台当前支持的模型、接口协议、计费规则、错误处理方式和实际服务表现,判断它是否适合自己的 Agent 架构。
需要特别关注的是,统一 API 入口并不会自动解决所有模型兼容问题。工具调用、结构化输出、流式响应等能力仍需按目标模型逐项验证。
八、常见问题与排查思路
1. 模型没有调用工具
先检查响应中是否存在工具调用请求,再检查模型是否支持该能力、工具描述是否明确,以及调用配置是否符合接口要求。
如果业务必须执行某个工具,可以研究当前模型接口支持的工具选择模式。但强制调用并不意味着参数一定正确,仍需要校验。
2. 工具参数错误
检查函数签名、类型注解、Pydantic Schema 和模型生成的参数是否一致。对于缺少关键信息的用户请求,应通过追问补全,而不是让模型猜测订单编号或用户身份。
3. 工具执行失败
将模型请求错误与工具服务错误分开记录。模型可能成功生成调用请求,但实际业务接口仍可能因为超时、权限不足或数据不存在而失败。
对于可以安全重试的临时错误,应设置重试次数和超时上限;对于具有副作用的操作,则需要考虑幂等性和重复提交问题。
4. 更换模型后工具不能正常工作
不要只检查普通文本回答。应使用相同的测试集,分别验证工具选择、参数格式、工具结果回传和最终回答。必要时针对特定模型调整工具描述或参数 Schema。
5. Agent 调用成本持续增加
记录每个任务的模型请求次数、Token 使用量、工具执行耗时和重试次数。对于固定流程,可以减少不必要的模型决策步骤;对于简单计算,优先使用确定性程序逻辑,而不是反复调用模型。
九、结论:根据任务选择技术,而不是盲目追求框架
Agent 工具调用并不存在适用于所有项目的唯一方案。
如果开发者需要直接控制模型请求与函数调用循环,可以直接采用模型提供商的原生 Function Calling 接口;如果希望简化工具定义和 Agent 构建,可以使用 LangChain Tools;如果任务包含复杂分支、状态管理和人工审批,则可以进一步引入 LangGraph 等工作流编排方案。
对于需要接入多个模型的项目,还应将模型接入层与业务逻辑分开,统一管理模型配置,并通过真实任务测试不同模型的工具调用能力。API 中转站可以作为接入架构中的一种选择,但应重点验证模型支持范围、协议兼容性、调用成本和服务稳定性,而不是仅根据接口形式判断是否适合生产环境。
从开发实践来看,可靠的 Agent 系统应当具备三个基础能力:清晰的工具定义、可验证的执行流程,以及完善的异常与权限控制。 模型能够正确理解任务只是起点,工具能否稳定执行、结果能否准确返回,才是决定应用实际价值的关键。
如果正在搭建 AI Agent,建议先选择一个边界明确的业务场景,完成工具定义和端到端测试,再逐步增加工具数量与任务复杂度。这样更容易定位问题,也能避免在项目早期引入不必要的架构成本。

