Skip to content

Web search domain constraints are accepted and silently discarded by providers that cannot honour them #293

Description

@saarnilauri

WebSearch carries allowedDomains and disallowedDomains. Anthropic honours them. The other two first-party providers accept the configuration, emit a bare search tool, and discard the domains — with no error, no warning, and no way for the caller to find out.

Evidence

ai-provider-for-openai, src/Models/OpenAiTextGenerationModel.php:417-421:

if ($webSearch) {
    $webSearchTool = ['type' => 'web_search'];
    // Note: The OpenAI Responses API web_search tool may have different filtering options.
    // For now, we use the basic form.
    $tools[] = $webSearchTool;
}

ai-provider-for-google, src/Models/GoogleTextGenerationModel.php:224-227:

$webSearch = $config->getWebSearch();
if ($webSearch) {
    // Filtering by allowed or disallowed domains is not supported by the Google AI API.
    $tools[] = ['googleSearch' => new \stdClass()];
}

Both declare the option as supported — OpenAiModelMetadataDirectory.php:90 and GoogleModelMetadataDirectory.php:144 both contain new SupportedOption(OptionEnum::webSearch()) — so ModelResolver routes to them happily.

For contrast, ai-provider-for-anthropic passes them through (AnthropicTextGenerationModel.php:593-594).

Why this is worth changing

A caller who restricts a search to a domain is usually doing it for correctness or safety — grounding an assistant in a site's own content, keeping a regulated product away from sources it may not cite. Dropping that constraint does not degrade the feature, it inverts it: the request that was meant to be narrower than an unrestricted search silently becomes an unrestricted one. A caller cannot detect it from the result, because a plausible answer comes back either way.

The Google comment is the interesting part. It shows the limitation is known and deliberately not signalled — the provider is aware it cannot honour the constraint and has no way to say so. That is the argument for fixing this in the SDK rather than in either plugin: a provider that knows it cannot satisfy a requested constraint currently has nowhere to report that.

Possible directions

  1. Make domain filtering separately declarable. A required option distinct from webSearch itself, so a provider that supports search but not domain filtering does not advertise it and ModelResolver never routes there. Fails at resolution time, which is the earliest and cheapest point.
  2. Throw at request time in providers that cannot honour a populated domain list. Simpler, but fails later and per-request.
  3. Status quo, documented. Cheapest, and leaves the sharp edge in place.

1 seems right to me, with the caveat that OptionEnum synthesises its cases by reflecting over ModelConfig's KEY_* constants (only INPUT_MODALITIES is declared literally), so a new option needs a home in ModelConfig or an explicit constant alongside INPUT_MODALITIES — worth deciding deliberately rather than as a side effect.

I am raising it here rather than on the two provider repos because neither can fix it alone: the OpenAI and Google APIs do not offer domain filtering at all, so there is no provider-side implementation to write. The only available fix is an SDK-level mechanism for declining to route, or for reporting the constraint as unmet. Happy to open provider-side issues and a PR once there is a direction.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    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