2026 年 3 月 17 日·6 分钟读完·LLMTool UseAgent结构化输出

Function Calling 与结构化输出:让 LLM 可靠地动手

分清调用协议与输出格式,比较 OpenAI、Claude 的字段;用完整 schema 和工具循环说明参数验证、授权、并发、幂等与失败处理。

更新与核对 · 2026-10-11

模型回答“工单已归档”,不代表数据库里真的有记录。Function Calling(工具调用)让模型提出操作请求,由程序执行并回传结果;Structured Outputs(结构化输出)约束回答的数据格式。要完成动作,需要执行器;要返回一个对象,需要格式契约。

本文以客户端自定义工具为主,服务端内置工具的执行位置另看厂商文档。接口按 2026 年 10 月核对,例子中的业务工具为示意。

一轮调用发生了什么

程序声明工具名称、用途与参数 schema;模型返回调用请求;程序验证、授权并执行;将调用 ID 对应的结果回传;模型继续调用或回答。模型产生调用参数,不因此拥有真实权限。

工具调用循环:声明工具、生成调用、验证授权、执行、回传与终止

图 1 · 格式验证、业务授权和真实执行位于程序侧。

不同厂商的字段不能混用:

接口工具定义调用参数结果关联
OpenAI Responsestype: function、parametersfunction_call.arguments 是 JSON 字符串function_call_output.call_id
OpenAI Chat Completionstype: function、嵌套 functiontool_calls[].function.arguments 是 JSON 字符串tool 消息的 tool_call_id
Claude Messagesinput_schematool_use.input 通常已解析成对象tool_result.tool_use_id

Claude 的多个客户端工具结果通常放在紧随助手消息的 user 内容块中;OpenAI 按各自接口的结果项或 tool 消息回传。错误标记也不同,is_error 不能当作所有接口的通用字段。OpenAI 调用文档[1]与 Claude 调用文档[3]

Schema:格式约束要完整,业务含义要清晰

工具 description 说明何时使用、何时不使用和结果含义;参数尽量用枚举、明确单位与可检验边界。下面是 OpenAI Responses 风格的工具定义:

{
  "type": "function",
  "name": "get_ticket",
  "description": "读取已有工单;只用于存在 ticket_id 的记录,不用于创建、修改或归档工单。",
  "strict": true,
  "parameters": {
    "type": "object",
    "properties": {
      "ticket_id": { "type": "string" },
      "options": {
        "type": "object",
        "properties": {
          "detail": { "type": "string", "enum": ["summary", "full"] },
          "note": { "type": ["string", "null"] }
        },
        "required": ["detail", "note"],
        "additionalProperties": false
      }
    },
    "required": ["ticket_id", "options"],
    "additionalProperties": false
  }
}

OpenAI strict schema 要求各对象关闭额外属性,并把属性列入 required;可空字段用 null 表示。支持的是 JSON Schema 子集,非任意 schema 都可用。Claude 的声明形式和支持范围按其文档处理,不能只改字段名就保证兼容。

Strict 降低参数形状错误,不保证 ticket_id 存在、归当前用户所有,或模型选对了工具。身份、租户和授权范围由会话上下文注入服务端;模型不能通过一个参数把自己变成管理员。

工具循环:先完整,再执行

以下为框架中立伪代码,provider_adapter 负责厂商差异:

for round in bounded_rounds:
    response = await provider_adapter.generate(state)
    record_usage_and_status(response)
    if response.refused or response.incomplete:
        return explicit_failure(response)

    calls = provider_adapter.complete_calls(response)
    if calls is empty:
        return validated_final_answer(response)

    results = bounded_execute(calls, handler = call => {
        tool = registry.lookup(call.name)        # 未知工具拒绝
        args = adapter.parse_complete_args(call) # 字符串解析或已解析对象
        validate_schema_and_business(args)
        authorize(current_user, tool, args)
        return execute_with_deadline_and_idempotency(tool, args)
    })
    state = adapter.append_response_and_results(state, response, results)
return explicit_failure("tool_round_limit")

执行器把校验错误、超时和业务失败转成结构化结果,保留调用 ID;机密、堆栈和内部 SQL 不原样交给模型。流式参数要按调用 ID 聚合,等完整结束才解析,不能用“容错解析”把半截参数执行掉。

厂商的截断、拒绝、暂停和完成状态分别处理;不能把 Claude 的 stop_reason 套到 Responses 上。tool_choice 是否能强制某工具取决于模型与接口,不能笼统说“新模型都已移除”。

并行:独立读取可以,依赖写入不可以

一个响应可能包含多次调用,但是否并行生成取决于模型与配置。程序不必无条件并发执行:两次独立检索可并发;“创建订单后付款”有依赖,应串行或拆成不同轮。

并发要有上限、每调用截止时间和部分失败结果。写入工具用业务幂等键、唯一约束或事务防重复;模型请求重试和工具写入去重是不同问题,详见 兜底设计。

对发布、删除、支付等操作,把“草稿生成”与“提交”拆开。模型给出的 suggested_status 只能作为建议;最终状态由授权、业务规则、执行结果或审核机制确认。

结构化输出:对象合法不等于对象正确

抽取文档字段、分类反馈、生成报告适合结构化输出。Responses 的 text.format、Chat Completions 的 response_format 和 Claude 的 output_config.format 是不同配置位置。OpenAI 结构化输出[2]

消费结果前先看完成状态与拒绝,再解析并做 schema、业务校验。合法 JSON 中的日期也可能错误,引用 ID 也可能不存在;格式能力解决结构稳定,正确性仍由任务评测负责。

工具体积与权限治理

工具定义和结果占上下文,缓存只是改变重复处理成本。按任务加载工具、合并重叠工具、分页和按需读取都值得比较,工具数量没有统一的“最多十个”上限。

大结果可返回摘要与受控引用,注明截断、总条数和后续 cursor;外部系统之间用有授权的 artifact ID,不能假设对方可读取本地路径。按角色少暴露工具有助于路由,执行侧仍必须授权。

工具结果包含网页、日志等不受信任内容。模型读到“执行删除”的文字,不应因此获得删除能力。工具注册表、授权与高风险提交规则才是边界。

OpenAI 与 Anthropic:格式契约之外怎样改善工具使用

OpenAI 的 Function Calling 与 Structured Outputs 文档提供 API 层面的 schema 和回传契约;Anthropic 的 Writing effective tools[5]则从 Agent 使用工具的行为出发,讨论工具选择、命名、返回相关信息与 token 效率。两者可以结合:schema 限制格式,工具设计帮助模型正确选择和理解。

工程推导:固定模型、任务集和业务权限,分别比较工具描述、重叠接口数量、结果字段与简洁/详细模式。记录误选、参数错误、缺失 ID、重试次数和最终任务成功率;精简结果时保留后续动作所需的稳定 ID,不能只追求 token 最少。以相同预算比较,避免把工具优化与换模型的收益混在一起。

执行循环与审批边界由生产架构篇继续展开。

落地检查

  1. API 适配器独立处理字段与回传格式。
  2. strict schema 校验完整,同时校验业务含义和身份权限。
  3. 流式调用参数完整后执行,按调用 ID 记录状态。
  4. 并行只用于独立操作,写入有幂等与审批语义。
  5. 限制轮数、并发、时间、费用和结果体积。
  6. 回归覆盖未知工具、截断、拒绝、重复调用和越权。

长任务还需要 上下文与记忆管理。

参考资料

正文中的编号可跳转至对应来源。工程报告、官方文档与研究论文分别标注;支撑范围说明该资料能证明什么,以及不能推导什么。

  1. [1]官方文档
    OpenAI — Function calling

    支撑范围: 工具定义、调用 ID、参数与结果回传的 API 契约;执行和授权由应用负责。

    developers.openai.com核对于 2026-10-11
  2. [2]官方文档
    OpenAI — Structured outputs

    支撑范围: 结构化输出格式与 schema 限制;合法对象不自动保证事实正确。

    developers.openai.com核对于 2026-10-11
  3. [3]官方文档
    Claude — Tool use

    支撑范围: Claude tool_use / tool_result 的调用流程;与其他 API 的字段不能直接互换。

    platform.claude.com核对于 2026-10-11
  4. [4]官方文档
    Claude — Structured outputs

    支撑范围: Claude 结构化输出配置与限制;业务规则仍要独立校验。

    platform.claude.com核对于 2026-10-11
  5. [5]工程报告
    Anthropic — Writing effective tools for AI agents

    支撑范围: 工具命名、相关结果和 token 效率的工程方法;优化要保留任务所需信息并评测。

    www.anthropic.com核对于 2026-10-11
↑ 回到全部文章