Skip to content

fix(availability): apply modelIdResolutions to tool sub-agent model configs#28406

Open
vedhakoushik wants to merge 1 commit into
google-gemini:mainfrom
vedhakoushik:fix/web-tool-model-resolution
Open

fix(availability): apply modelIdResolutions to tool sub-agent model configs#28406
vedhakoushik wants to merge 1 commit into
google-gemini:mainfrom
vedhakoushik:fix/web-tool-model-resolution

Conversation

@vedhakoushik

Copy link
Copy Markdown

Problem

Fixes #28390

web-search, web-fetch, and other utility tool configs extend gemini-3-flash-base which hardcodes gemini-3-flash-preview. This model ID was never run through modelIdResolutions, so API-key users without preview access (hasAccessToPreview: false) hit INVALID_MODEL on every web tool call — completely breaking web search and URL fetching for these users.

Affected aliases (all inherit from gemini-3-flash-base):

  • web-search
  • web-fetch
  • web-fetch-fallback
  • loop-detection
  • llm-edit-fixer
  • next-speaker-checker
  • context-snapshotter

Root Cause

applyModelSelection calls getResolvedConfig to walk the alias chain:

web-search → gemini-3-flash-base → (base) → model: gemini-3-flash-preview

The resolved model string (gemini-3-flash-preview) is returned directly and used as-is. It is never passed through resolveModelId, which already has the correct fallback contexts defined in defaultModelConfigs.ts:

'gemini-3-flash-preview': {
  default: 'gemini-3-flash-preview',
  contexts: [
    { condition: { hasAccessToPreview: false, useGemini3_5Flash: true }, target: 'gemini-3.5-flash' },
    { condition: { hasAccessToPreview: false, useGemini3_5Flash: false }, target: 'gemini-2.5-flash' },
  ],
},

The fix logic exists — it just was not applied to non-chat-model calls.

For comparison, the main chat model goes through ModelRouterService which does call resolveModelId. Tool/utility model calls go directly through applyModelSelection and skip that step entirely.

Fix

In applyModelSelection (packages/core/src/availability/policyHelpers.ts), for non-chat-model requests, run the alias-resolved model through resolveModelId with the current session context before proceeding with availability selection:

if (!modelConfigKey.isChatModel) {
  const resolvedModelId = config.modelConfigService.resolveModelId(model, {
    hasAccessToPreview: config.getHasAccessToPreviewModel(),
    useGemini3_1: config.getGemini31LaunchedSync(),
    useGemini3_5Flash: config.hasGemini35FlashGAAccess(),
  });
  if (resolvedModelId !== model) {
    model = resolvedModelId;
    // Re-fetch generateContentConfig for the resolved model
    const refetchedResolved = config.modelConfigService.getResolvedConfig({
      ...modelConfigKey,
      model,
    });
    resolvedGenerateContentConfig = refetchedResolved.generateContentConfig;
  }
}

Chat model calls are explicitly excluded — the router already handles resolution for those.

Result

User type Before After
OAuth / preview access gemini-3-flash-preview gemini-3-flash-preview ✓ (unchanged)
API key, no preview, no Gemini 3.5 GA INVALID_MODEL gemini-2.5-flash
API key, no preview, Gemini 3.5 GA INVALID_MODEL gemini-3.5-flash

Testing

  • Added applies modelIdResolutions for non-chat tool configs (web-search/web-fetch preview fallback) — asserts gemini-3-flash-previewgemini-2.5-flash when hasAccessToPreview: false
  • Added does not apply modelIdResolutions for chat model calls (already routed) — asserts resolveModelId is NOT called for chat model path
  • Updated 3 partial mock configs in policyHelpers.test.ts, fallbackIntegration.test.ts, and baseLlmClient.test.ts that were missing the new config methods
  • 208 tests pass across all affected packages

Checklist

  • I have read the CONTRIBUTING guide
  • Tests pass locally (npx vitest run packages/core/src/availability/ packages/core/src/core/baseLlmClient.test.ts packages/core/src/tools/web-search.test.ts packages/core/src/tools/web-fetch.test.ts)
  • Linting passes (pre-commit hook: prettier + eslint)
  • My commits are signed off

@vedhakoushik
vedhakoushik requested a review from a team as a code owner July 15, 2026 14:08
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where utility tool configurations were failing for API-key users who lacked preview access. By applying model ID resolution logic to non-chat model requests, the system now correctly maps restricted models to their available GA counterparts, preventing service disruptions for web-based tools.

Highlights

  • Model Resolution Fix: Implemented model ID resolution for non-chat tool configurations to ensure they correctly fall back to GA models for users without preview access.
  • Bug Resolution: Resolved the INVALID_MODEL error occurring in utility tools like web-search and web-fetch by ensuring they respect model availability policies.
  • Testing: Added comprehensive test cases to verify that preview-gated models correctly resolve to appropriate alternatives and that chat models remain unaffected.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added the size/m A medium sized PR label Jul 15, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/M

  • Lines changed: 106
  • Additions: +103
  • Deletions: -3
  • Files changed: 4

@google-cla

google-cla Bot commented Jul 15, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an issue where API-key users without preview access encountered INVALID_MODEL errors when using tool sub-agents (such as web-search or web-fetch). It resolves this by applying modelIdResolutions to non-chat-model calls within applyModelSelection, allowing preview-gated sub-agent models to fall back to appropriate GA models. The reviewer suggested using optional chaining and nullish coalescing when calling configuration methods on the config object to prevent potential runtime crashes when the configuration is partially mocked in tests or other contexts.

Comment on lines +300 to +302
hasAccessToPreview: config.getHasAccessToPreviewModel(),
useGemini3_1: config.getGemini31LaunchedSync(),
useGemini3_5Flash: config.hasGemini35FlashGAAccess(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To prevent potential runtime crashes and maintain consistency with the rest of this file (such as in resolvePolicyChain), please use optional chaining and nullish coalescing when calling these configuration methods. This is especially important because config is frequently mocked or partially implemented in tests and other contexts, and calling these methods directly without guards can lead to TypeError exceptions.

Suggested change
hasAccessToPreview: config.getHasAccessToPreviewModel(),
useGemini3_1: config.getGemini31LaunchedSync(),
useGemini3_5Flash: config.hasGemini35FlashGAAccess(),
hasAccessToPreview: config.getHasAccessToPreviewModel?.() ?? false,
useGemini3_1: config.getGemini31LaunchedSync?.() ?? false,
useGemini3_5Flash: config.hasGemini35FlashGAAccess?.() ?? false,
References
  1. When consuming an object, if a property is optional in its type definition (interface), callers must handle the undefined case (e.g., by providing a default with ??). Do not rely on the implementation details of the function that creates the object to always provide a value, as this can change. Code against the interface contract.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — applied optional chaining and nullish coalescing on all three config method calls, consistent with the existing pattern at lines 54-57 of the same file. Force-pushed in the latest commit.

…onfigs

web-search, web-fetch, loop-detection and other utility tools extend
gemini-3-flash-base which hardcodes gemini-3-flash-preview. This model
ID was never run through modelIdResolutions, so API-key users without
preview access hit INVALID_MODEL on every web tool call.

applyModelSelection now calls resolveModelId on the alias-resolved model
for non-chat-model requests, mirroring the fallback logic that already
exists for the main chat model router. Users without preview access are
transparently downgraded to gemini-2.5-flash (or gemini-3.5-flash if
Gemini 3.5 GA access is available).

Fixes: google-gemini#28390
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality priority/p1 Important and should be addressed in the near term. size/m A medium sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Browser agent and web search tools not working

1 participant