# 工具调用：一套请求格式，调所有模型

> https://router.one/zh/llm-tool-calling 的 Markdown 镜像，供 AI 助手与爬虫使用。Router One 是 OpenAI 兼容的统一 LLM API 网关。
> 最后更新：2026-09-05

Tool calling（函数调用）让模型返回一个结构化的函数调用请求，而不是一段文字。各大模型家族都支持它，但每家官方 API 的格式都不一样——这正是网关能省掉的集成成本。Router One 遵循 OpenAI Chat Completions 规范：同一个 tools 数组、同一套响应处理循环，在 GPT、Claude、Gemini、Grok 上通用；具体支持程度因模型而异，动手前先查目标模型的目录页。

## 在请求里声明工具

工具就是附在普通 chat completion 上的 JSON Schema 函数声明。从 /models 目录选一个支持工具调用的模型 ID：

`request.sh`

```bash
curl https://api.router.one/v1/chat/completions \
  -H "Authorization: Bearer sk-your-router-one-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model-id-from-/models>",
    "messages": [{"role": "user", "content": "上海今天天气？"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "查询指定城市的当前天气",
        "parameters": {
          "type": "object",
          "properties": {"city": {"type": "string"}},
          "required": ["city"]
        }
      }
    }]
  }'
```

## 四步调用循环

处理一次工具调用是一段四步对话，无论请求最终由哪个模型家族服务，结构完全一致：

### 1. 模型请求调用工具

响应里没有 content，而是 finish_reason 为 "tool_calls" 和一个 tool_calls 数组——每个元素带 id、函数名，以及 JSON 字符串形式的参数。

### 2. 你执行函数

解析参数字符串、按你的 schema 校验，然后执行真正的函数。模型自己不会执行任何东西——它只是提出调用。

### 3. 你回传结果

先把收到的 assistant 消息原样追加进消息列表，再追加一条 role 为 "tool" 的消息，带上对应的 tool_call_id 和函数结果。

### 4. 模型完成回答

把扩展后的消息列表发回同一个端点。模型把工具结果融入最终回复——或者继续请求下一个工具，循环重复。

`tool_loop.py`

```python
from openai import OpenAI
import json

client = OpenAI(
    base_url="https://api.router.one/v1",
    api_key="sk-your-router-one-key",
)

resp = client.chat.completions.create(
    model="<model-id-from-/models>", messages=messages, tools=tools
)
msg = resp.choices[0].message

if resp.choices[0].finish_reason == "tool_calls":
    messages.append(msg)
    for call in msg.tool_calls:
        result = run_tool(call.function.name,
                          json.loads(call.function.arguments))
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result),
        })
    final = client.chat.completions.create(
        model="<model-id-from-/models>", messages=messages, tools=tools
    )
```

## 各模型的差异在哪

- 是否支持工具调用——先看模型目录页上的能力标记，再决定在它上面构建。
- 并行调用：有的模型一次响应返回多个 tool_calls，有的一次一个。永远遍历整个数组，不要只读第 0 个。
- Schema 严格度：不同模型对参数遵循 JSON Schema 的程度不同。执行前一律先校验。
- 调用意愿：有的模型逢机会就调工具，有的更倾向直接文字回答。更明确的函数描述和 tool_choice 参数对两类都有效。
- /v1/messages 上的服务端工具：在 Anthropic 兼容的 /v1/messages 端点，web_search 与 code_execution 服务端工具（含 code_execution 的 bash 与 text editor 子工具）会被接受，并按该模型的标准 token 费率计量；web_fetch 与 mcp_servers 会在调用任何模型之前以 400 拒绝。本页讲的客户端函数工具则通过 /v1/chat/completions 对所有支持工具调用的模型通用。

## 在网关上排查工具调用

两类故障占绝大多数。模型用文字回答而不调工具：收紧函数描述、写明触发条件，或用 tool_choice 强制。参数解析失败或校验不过：绝不要盲目执行——先校验，失败时把错误信息作为工具结果回传，让模型自己纠正。无论哪种，每次尝试都是 Dashboard → Logs 里的一行请求记录，带 Token、花费、延迟和状态——循环每转一圈花了多少，看得一清二楚。

## 常见问题

### 哪些模型支持工具调用？

支持程度因模型而异。Router One 遵循 OpenAI Chat Completions 规范，/models 目录标注了每个模型的能力——按你要用的具体模型查目录页，不要按家族想当然。

### 工具声明算 Token 吗？

算——工具声明随 prompt 一起发送，按输入 Token 计费，而且循环每一轮都会计入。Dashboard → Logs 的每请求 Trace 会显示 Token 和费用影响，过大的 schema 一眼就能看出来。

### 该用工具调用还是结构化输出？

工具调用适合「要执行动作」：模型决定调你的函数，你把结果喂回去。如果只是想让回复固定成某个 JSON 结构、没有真函数要跑，用 response_format（json_object，或带命名 schema 的 json_schema）约束输出是更简单的模式——网关检查信封并转发给模型，schema 是否被强制执行取决于模型。很多应用两者并用。详见结构化输出指南。

### 带工具调用的响应可以流式吗？

可以。开启流式后，工具调用的片段会在 delta 分块中逐步到达——累积 id、函数名和参数片段，直到流以 finish_reason 为 tool_calls 结束，然后走正常循环。分块格式见 LLM 流式输出指南。

### 同一套循环真的跨模型家族通用吗？

这正是 OpenAI 兼容规范的意义：tools 数组、tool_calls 响应、tool 角色的结果消息保持同一个形状，Router One 把请求路由到你指定的模型。各模型的行为差异（并行调用、严格度）依然存在，但循环结构不用变。

## 相关页面

- OpenAI 兼容 API：https://router.one/zh/openai-compatible-api
- LLM 流式输出：https://router.one/zh/llm-streaming
- 结构化输出（JSON Schema）：https://router.one/zh/llm-structured-outputs
- OpenAI SDK 接入：https://router.one/zh/integrations/openai-sdk
- LangChain 接入：https://router.one/zh/integrations/langchain
- LlamaIndex 接入：https://router.one/zh/integrations/llamaindex
- /v1/messages 上的 Claude 联网搜索与代码执行：https://router.one/zh/blog/claude-web-search-code-execution-api
- 错误码速查：https://router.one/zh/llm-api-error-codes
- 网关层负责什么：https://router.one/zh/llm-api-gateway
- API 文档：https://router.one/zh/docs
- 本页规范地址：https://router.one/zh/llm-tool-calling
- 模型与每模型 token 价格：https://router.one/zh/models （markdown：https://router.one/zh/models.md ）
- 定价：https://router.one/zh/pricing
- API 文档（markdown）：https://router.one/zh/docs.md
- 公司事实（markdown）：https://router.one/zh/facts/company.md
