show-me + teach-me · GPT-5.6 Responses · SDK issue #4083

Tool search — load tool schemas only when the model needs them

An OpenHands agent loads a fat toolset and re-sends every schema every turn. Tool search lets the model pull rarely-used tool definitions on demand, cutting input tokens while preserving the prompt cache. This page shows how it works and why it's a clean add.

1What the feature is

Tool search lets the model dynamically search for and load tool definitions into its context as needed, instead of loading them all up front. Mark rarely-used tools defer_loading: true; the model sees only their name and description at the start, and pulls the full parameter schema (via a tool_search tool) when it decides to use them.

★ The cache trick: newly loaded tools are injected at the end of the context window. The earlier, cached prefix isn't invalidated, so deferral saves tokens and preserves the prompt cache. Supported on gpt-5.4+.

2Why OpenHands cares

A typical OpenHands agent loads bash, str_replace_editor, browser, task/delegate, plus one function per MCP tool. On the Responses path all those schemas are re-sent every turn. Deferring the long tail — especially large MCP surfaces — is a direct input-token win with no loss of capability.

before
bash + editor + browser
+ N MCP schemas
re-sent every turn
after (deferred)
bash + editor loaded;
browser + MCP =
name+desc only

3What OpenAI needs in the request

tools = [
  {"type": "namespace", "name":"crm", "description":"...",
   "tools":[{"type":"function","name":"list_open_orders",
             "defer_loading": true, "parameters":{...}}]},
  {"type": "tool_search"}
]

Two modes: hosted (OpenAI searches the deferred tools you declared and returns the loaded subset in the same response) and client-executed (the model emits a tool_search_call; your app looks up and returns a tool_search_output echoing the call_id). Loaded tools become callable on later turns. OpenAI recommends grouping deferred functions into namespaces or MCP servers, each < ~10 functions.

4The greenfield gap

Unlike Programmatic Tool Calling, nothing here is subtly broken — it's simply absent:

NeededSDK today
defer_loading flag on toolsnone — to_responses_tool() always emits the full schema (tool.py:497)
namespace grouping + tool_search injectionnone (llm.py:1258)
parse tool_search_call/tool_search_outputnone (message.py:541)
ⓘ First cut: add an opt-in defer_loading marker + optional namespace grouping, inject the tool_search tool when any deferred tool is present (start with hosted mode — the simplest), preserve/replay the two new item types for store=false, gate on gpt-5.4+. Watch the interaction with PTC: deferred tools aren't available to a program until the model has loaded them. Tracked in #4083.

4Quiz

Five questions to check you actually understood it — not trivia. Click an answer to see whether it's right and why.

Companion pages: Programmatic Tool Calling · WebSocket mode · Multi-agent  |  SDK issue #4083  |  ← Home