工具搜索允许模型根据需要动态搜索并将工具加载到模型的上下文中。这使您可以避免预先将所有工具定义加载到模型的上下文中,并且 可能有助于减少整体的 token 用量和成本。为了获得最佳的成本和延迟,工具搜索旨在 保持模型的缓存。当模型发现新工具时,它们会被注入到上下文窗口的末尾。
gpt-5.4 and later models support tool_search.要激活工具搜索,您必须执行两项操作:
- 添加
tool_search作为工具添加到您的toolsarray. - 如果你正在使用 函数,请将要延迟加载的项标记为
defer_loading: true。如果您正在使用 MCP 服务器,请设置defer_loading: true在 MCP 服务器工具定义上。
尽可能使用命名空间
您可以将工具搜索与延迟 函数, 命名空间, or MCP 服务器,但我们建议尽可能使用命名空间或 MCP 服务器。我们的模型主要针对这些表面进行了搜索训练,而且在这些地方节省 token 的效果通常更显著。
For namespaces, defer_loading 适用于命名空间内部的函数,而不适用于命名空间对象本身。
在请求开始时,模型仍然会看到任何可搜索内容的名称和描述。对于命名空间或 MCP 服务器,这意味着模型在开始时仅看到命名空间或服务器的名称和描述,而不会显示其中包含的各个函数的详细信息,直到工具搜索工具将它们加载。对于单个延迟函数,模型仍然会看到函数的名称和描述,因此实际上工具搜索主要是在延迟参数模式(parameter schema)。
为了最大限度地节省 token,我们建议将延迟函数分组到具有清晰、高级描述的命名空间或 MCP 服务器中,让模型对其中包含的内容有强有力的概览,从而使其能够有效地搜索并仅加载相关的函数。作为最佳实践,建议将每个命名空间的函数数量保持在 10 个以内,以获得更好的 token 效率和模型性能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"tools": [
{
"type": "namespace",
"name": "crm",
"description": "CRM tools for customer lookup and order management.",
"tools": [
{
"type": "function",
"name": "list_open_orders",
"description": "List open orders for a customer ID.",
"defer_loading": true,
"parameters": {
"type": "object",
"properties": {
"customer_id": { "type": "string" }
},
"required": ["customer_id"],
"additionalProperties": false
}
}
]
},
{
"type": "tool_search"
}
]
}命名空间可以混合使用延迟和非延迟的工具。没有 defer_loading: true 的工具可立即调用,而同一命名空间中的延迟工具则通过工具搜索进行加载。
工具搜索类型
有两种使用工具搜索的方式:
- 托管工具搜索: OpenAI 会在您在请求中声明的延迟工具中进行搜索,并在同一响应中返回加载的子集。
- 客户端执行的搜索工具: The model emits a
tool_search_call,您的应用程序将执行查找,并返回匹配的tool_search_output.
如果在创建请求时候选工具已知,请从托管工具搜索开始。当工具发现依赖于项目状态、租户状态或您的应用程序控制的另一个系统时,请使用客户端执行的工具搜索。
托管工具搜索
当您已经知道希望模型搜索的 函数, 命名空间, or MCP 服务器 的完整清单时,托管工具搜索是最简单的方法。您预先声明它们,添加 {"type": "tool_search"},并让 API 决定要加载的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from openai import OpenAI
client = OpenAI()
crm_namespace = {
"type": "namespace",
"name": "crm",
"description": "CRM tools for customer lookup and order management.",
"tools": [
{
"type": "function",
"name": "get_customer_profile",
"description": "Fetch a customer profile by customer ID.",
"parameters": {
"type": "object",
"properties": {
"customer_id": {"type": "string"},
},
"required": ["customer_id"],
"additionalProperties": False,
},
},
{
"type": "function",
"name": "list_open_orders",
"description": "List open orders for a customer ID.",
"defer_loading": True,
"parameters": {
"type": "object",
"properties": {
"customer_id": {"type": "string"},
},
"required": ["customer_id"],
"additionalProperties": False,
},
},
],
}
response = client.responses.create(
model="gpt-5.5",
input="List open orders for customer CUST-12345.",
tools=[
crm_namespace,
{"type": "tool_search"},
],
parallel_tool_calls=False,
)
print(response.output)如果模型决定需要延迟工具,则响应将在最终的函数调用之前包含两个额外的输出项:
tool_search_call,它记录了托管搜索步骤。tool_search_output,其中包含被加载并变为可调用状态的子集。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[
{
"type": "tool_search_call",
"execution": "server",
"call_id": null,
"status": "completed",
"arguments": {
"paths": ["crm"]
}
},
{
"type": "tool_search_output",
"execution": "server",
"call_id": null,
"status": "completed",
"tools": [
{
"type": "namespace",
"name": "crm",
"description": "CRM tools for customer lookup and order management.",
"tools": [
{
"type": "function",
"name": "list_open_orders",
"description": "List open orders for a customer ID.",
"defer_loading": true,
"parameters": {
"type": "object",
"properties": {
"customer_id": { "type": "string" }
},
"required": ["customer_id"],
"additionalProperties": false
}
}
]
}
]
},
{
"type": "function_call",
"name": "list_open_orders",
"namespace": "crm",
"call_id": "call_abc123",
"arguments": "{\"customer_id\":\"CUST-12345\"}"
}
]In hosted mode, execution 设置为 server and call_id 设置为 null.
对于更复杂的任务,模型也可以在同一次请求中加载多个命名空间或 MCP 服务器。 tool_search_call。例如,如果它需要来自不同命名空间的函数来完成某项任务,它可以选择在执行后续函数调用之前,一起搜索并加载这些表面。
客户端执行的搜索工具
由客户端执行的工具搜索使您的应用程序能够完全控制工具发现机制。当可用工具取决于无法在初始请求中实际声明的信息时,此功能非常有用。 tools list.
使用 tool_search 配置工具, execution: "client" 以及应用程序预期的搜索参数 schema:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from openai import OpenAI
client = OpenAI()
first_response = client.responses.create(
model="gpt-5.5",
input="Find the shipping ETA tool first, then use it for order_42.",
tools=[
{
"type": "tool_search",
"execution": "client",
"description": "Find the project-specific tools needed to continue the task.",
"parameters": {
"type": "object",
"properties": {
"goal": {"type": "string"},
},
"required": ["goal"],
"additionalProperties": False,
},
}
],
parallel_tool_calls=False,
)
search_call = next(
item for item in first_response.output if item.type == "tool_search_call"
)
loaded_tools = [
{
"type": "function",
"name": "get_shipping_eta",
"description": "Look up shipping ETA details for an order.",
"defer_loading": True,
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
},
"required": ["order_id"],
"additionalProperties": False,
},
}
]
second_response = client.responses.create(
model="gpt-5.5",
input=[
*first_response.output,
{
"type": "tool_search_output",
"execution": "client",
"call_id": search_call.call_id,
"status": "completed",
"tools": loaded_tools,
},
],
)
print(second_response.output)在第一轮中,模型会发出一个 tool_search_call and stops there:
1
2
3
4
5
6
7
8
9
10
11
[
{
"type": "tool_search_call",
"execution": "client",
"call_id": "call_abc123",
"status": "completed",
"arguments": {
"goal": "Find the shipping ETA tool for order_42."
}
}
]然后,您的应用程序执行搜索并返回一个 tool_search_output 其中包含它想要加载的工具:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[
{
"type": "tool_search_output",
"execution": "client",
"call_id": "call_abc123",
"status": "completed",
"tools": [
{
"type": "function",
"name": "get_shipping_eta",
"description": "Look up shipping ETA details for an order.",
"defer_loading": true,
"parameters": {
"type": "object",
"properties": {
"order_id": { "type": "string" }
},
"required": ["order_id"],
"additionalProperties": false
}
}
]
}
]在下一轮中,加载的工具可以像普通函数一样被调用:
1
2
3
4
5
6
7
8
9
[
{
"type": "function_call",
"name": "get_shipping_eta",
"namespace": "get_shipping_eta",
"call_id": "call_xyz456",
"arguments": "{\"order_id\":\"order_42\"}"
}
]In client mode, execution 设置为 client and call_id 已定义。回显相同的 call_id from the tool_search_call in your tool_search_output.
高级用法
保持命名空间描述清晰
使命名空间描述清晰明了且能准确描述用例,因为模型依赖此描述来决定何时加载该命名空间中的一部分函数。避免过长的描述。相反,应将更丰富的细节放在按需加载的延迟函数描述中。
了解已加载的内容
tool_search_output.tools 包含由模型动态加载的工具列表。模型在后续轮次中将能够调用这些工具中的任何一个,因此在客户端模式下,您无需在多轮之间重复加载相同的工具。未在此数组中列出的工具将无法供模型使用。如果您想禁用某个已加载的工具,可以从 tool_search_output 项中移除它,您可以在该项中定义已加载的工具集,但请注意,更改已加载的工具集将会从该点起破坏模型的缓存。
高级注入模式
大多数集成在请求的 tools 参数中声明工具。由客户端执行的工具搜索还支持更高级的模式,即您的应用程序可以返回原始请求中不存在的工具。请将其视为高级工作流:仔细验证返回的 schema,并且仅暴露受信任的工具定义。
工具搜索与缓存
所有工具都在模型上下文窗口的末尾加载。这对于托管工具搜索和客户端执行的工具搜索都适用。这使得模型的缓存可以在请求之间得到保留,从而降低整体成本并提升速度。