Skip to content

Add provider-agnostic deferred tool loading and tool discovery support #281

Description

@superdav42

Context

Function declarations are currently sent to the model in full on every request. This works well for a small set of functions, but becomes expensive when an application exposes dozens or hundreds of tools, such as a large WordPress Abilities API catalog.

OpenAI and Anthropic now support deferred tool loading. Applications still declare the available tools, but selected definitions are withheld from the model context until the model searches for and loads them.

This issue proposes a provider-agnostic representation for:

  • marking function declarations as deferred;
  • requesting tool discovery;
  • representing tool discovery calls and results when they need to be carried across turns;
  • declaring whether a model or provider supports native deferred loading.

Provider implementations would translate this common configuration into their native API formats.

Value

Lower token usage and cost

Tool parameter schemas count as input tokens. Sending a large tool catalog on every request can consume a material portion of the context window before the conversation begins.

Deferred loading lets the model see only the tools needed for the current task.

Better prompt caching

OpenAI and Anthropic append discovered tools later in the context instead of changing the cached prompt prefix. This preserves cache reuse as tools are discovered.

Larger tool catalogs

Applications could register a broad catalog of WordPress abilities without manually choosing a small subset before every prompt.

A portable API

Both OpenAI and Anthropic use the defer_loading concept, although their discovery protocols differ. Representing the intent in PHP AI Client would prevent applications from depending on provider-specific request options.

Providers without native support would work as they always have by including all tools in the system prompt without the benefits of deferred loading and support. Alternatively we could implement the behavior client side with a dedicated search_tools tool but this would probably be best in a follow up issue.

Provider behavior

OpenAI

OpenAI supports tool search in the Responses API on GPT-5.4 and later models.

To use it, a request:

  1. adds {"type": "tool_search"} to tools;
  2. marks deferred functions or MCP servers with defer_loading: true;
  3. optionally groups functions into namespaces.

OpenAI supports two execution modes:

  • hosted search, where OpenAI selects and loads tools within the same response;
  • client-executed search, where the model returns a tool_search_call and the client supplies a tool_search_output.

Hosted responses can include tool_search_call and tool_search_output items before the eventual function call. These items should not be silently lost if they are needed for conversation replay.

OpenAI doc says the hosted search would be preferred if all the available tools are known and defined so we should focus on the hosted search.

Documentation:

Anthropic

Anthropic also supports defer_loading: true. A request includes a server-side tool search implementation, such as its regex or BM25 search tool, and marks other tools as deferred.

Anthropic returns tool_reference blocks for matching tools and expands those references into full definitions. Conversation history must preserve the related server tool-use and search-result blocks.

Anthropic also supports custom client-side search, including embedding-based discovery.

Documentation:

Provider follow-ups

Provider repositories would then map the common configuration:

  • WordPress/ai-provider-for-openai
    • serialize tool_search, namespaces, and defer_loading;
    • parse and preserve discovery output items;
    • limit support to compatible models.
  • WordPress/ai-provider-for-anthropic
    • serialize the selected search tool and defer_loading;
    • preserve tool_reference and server tool-use blocks.

Backwards compatibility

  • Existing FunctionDeclaration construction must remain valid.
  • Deferred loading must default to false.
  • Existing prompts must continue sending all function declarations eagerly.
  • Providers that do not implement tool search must behave as they do today unless the caller explicitly requires deferred loading.
  • DTO toArray() and fromArray() behavior must remain compatible with previously serialized configuration.

Open to feedback, but it seems a pretty simple feature that belongs in the client to provide a common interface that would be useable by any provider. When using a provider that does not have native support for deferred tools it will just work the way it is now.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions