Skip to content

fix(web-search): keep first-class web_search runtime providers visible#77074

Merged
steipete merged 3 commits intoopenclaw:mainfrom
joeykrug:fix/brave-web-search-first-class
May 4, 2026
Merged

fix(web-search): keep first-class web_search runtime providers visible#77074
steipete merged 3 commits intoopenclaw:mainfrom
joeykrug:fix/brave-web-search-first-class

Conversation

@joeykrug
Copy link
Copy Markdown
Contributor

@joeykrug joeykrug commented May 4, 2026

Summary

Fixes #77073 — first-class assistant web_search reported web_search is disabled or no provider is available even when openclaw capability web search and direct runtime provider execution succeeded against the same configured Brave plugin.

Two source-only fixes:

  • src/agents/tools/web-search.ts — when lateBindRuntimeConfig: true:
    • runtimeWebSearch falls back to options?.runtimeWebSearch when getActiveRuntimeWebToolsMetadata()?.search is null (in agent contexts that do not share the gateway in-process runtime snapshot).
    • config falls back to options?.config when getActiveSecretsRuntimeSnapshot() is null.
    • Derives configuredProviderId from config.tools.web.search.provider and uses runtimeProviderId || configuredProviderId to decide preferRuntimeProviders, so an explicit Brave/Perplexity selection still routes through runtime provider discovery when the runtime metadata is unbound.
  • src/plugins/web-provider-runtime-shared.ts — when getLoadedRuntimePluginRegistry(...) returns a registry that maps to zero web providers, fall through to a scoped plugin load instead of treating that empty active registry as authoritative. Explicit onlyPluginIds: [] still short-circuits to [] to preserve the empty-scope contract for both resolvePluginWebProviders and resolveRuntimeWebProviders.

Why

The active gateway plugin registry is intentionally scoped to channels, memory, harnesses, and sidecars on startup. It can be otherwise compatible with the active OpenClaw config while contributing zero web-provider entries (e.g. when Brave/web providers live in a separately-loaded plugin set). Without a fall-through, the assistant's first-class web_search tool sees that empty active result as authoritative and reports "no provider available" — even though openclaw capability web search and the direct runtime path use a scoped load and find the configured provider just fine.

Late-binding compounded the problem: in agent contexts where the active-runtime/active-secrets globals are not set, the late-bound execute lambda lost both runtimeWebSearch and config, leaving preferRuntimeProviders unable to route to the configured plugin.

Test plan

  • node scripts/run-vitest.mjs run --config test/vitest/vitest.plugins.config.ts src/plugins/web-provider-runtime-shared.test.ts — 13 / 13 passed (4 new fall-through cases added).
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-tools.config.ts src/agents/tools/web-search.late-bind.test.ts — 6 / 6 passed (new file, covers both ?? fallbacks, configured-provider routing, no-selection guard, bundled manifest owner precedence, and active-runtime priority).
  • Re-ran adjacent web-search.test.ts and web-search.signal.test.ts to confirm no regression.
  • pnpm exec oxfmt --check --threads=1 on the four touched files — clean.

Notes

  • Diff is source-only. No dist bundle edits, no backup files, no shell patch scripts.
  • Pre-existing failures in 7 unrelated plugins/web-provider* test files were observed identically with and without this branch (manifest-registry mock and source-checkout-runtime fixture issues). They are not affected by this change.

🤖 Generated with Claude Code

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M labels May 4, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 4, 2026

Codex review: needs maintainer review before merge.

Summary
The PR updates first-class web_search late-binding and web-provider runtime resolution so configured runtime providers remain visible when active runtime metadata or the active plugin registry is incomplete.

Reproducibility: yes. at source level: current main can drop captured runtime metadata in late-bound web_search and can treat an empty active runtime registry as authoritative. I did not establish a live Gateway reproduction in this read-only pass.

Next step before merge
No automated repair lane is needed because I found no actionable review finding; the remaining action is normal maintainer validation and merge decision.

Security
Cleared: The PR touches source, tests, and changelog only, with no dependency, workflow, package, credential, or artifact execution changes.

Review details

Best possible solution:

Land this narrow source/test/changelog fix after normal maintainer validation so first-class web_search can use configured runtime providers in late-bound agent contexts.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main can drop captured runtime metadata in late-bound web_search and can treat an empty active runtime registry as authoritative. I did not establish a live Gateway reproduction in this read-only pass.

Is this the best way to solve the issue?

Yes. The PR keeps active runtime state precedence, adds captured runtime/config fallback, and falls through only from empty active registries while preserving explicit empty scopes.

What I checked:

  • Current-main late-bound metadata gap: With lateBindRuntimeConfig enabled, current main reads runtimeWebSearch only from getActiveRuntimeWebToolsMetadata()?.search before calling runWebSearch, so an agent context without that active global can drop the captured runtime metadata. (src/agents/tools/web-search.ts:90, dadf0005ec3a)
  • Current-main empty registry short-circuit: resolvePluginWebProviders and resolveRuntimeWebProviders return mapped providers from a compatible active/runtime registry immediately; that includes the empty-provider case that prevents scoped fallback loading. (src/plugins/web-provider-runtime-shared.ts:189, dadf0005ec3a)
  • Runtime provider selection dependency: runWebSearch resolves runtime providers only when preferRuntimeProviders is true, and throws the reported no-provider error when candidate resolution returns an empty list. (src/web-search/runtime.ts:249, dadf0005ec3a)
  • Documented configured-provider contract: The docs state that tools.web.search.provider is validated against bundled and installed plugin manifests, and the Brave docs show Brave as a web_search provider selected through tools.web.search.provider. Public docs: docs/tools/web.md. (docs/tools/web.md:200, dadf0005ec3a)
  • PR source fix: The PR falls back to captured runtime metadata/config, uses the configured provider id when deciding runtime-provider preference, and falls through from empty active/runtime registry results while preserving explicit empty scopes. (src/agents/tools/web-search.ts:89, d0cdd05dcf2d)
  • PR regression coverage: The PR adds late-bound web_search tests plus shared provider-runtime tests for empty active registry fall-through and explicit empty-scope preservation. (src/agents/tools/web-search.late-bind.test.ts:1, d0cdd05dcf2d)

Likely related people:

  • steipete: Current-main blame attributes the central web_search tool and shared web-provider resolver blocks to commit 36f8a86, which currently owns the relevant code lines in this checkout. (role: recent maintainer; confidence: high; commits: 36f8a8603d95; files: src/agents/tools/web-search.ts, src/plugins/web-provider-runtime-shared.ts, src/web-search/runtime.ts)
  • amknight: Merged PR fix(agents): keep web_search runtime providers visible #76685 addressed the same agent web_search runtime-provider visibility area immediately before this follow-up, including agent tool behavior, tests, and changelog coverage. (role: recent adjacent owner; confidence: high; commits: ccce342a2454, e7f379c68d23; files: src/agents/tools/web-search.ts, src/agents/tools/web-tools.enabled-defaults.test.ts, CHANGELOG.md)
  • vincentkoc: Recent changelog/history around official external web-search plugin installation, provider visibility, and runtime manifest/provider work repeatedly credits vincentkoc in the same Brave/external-provider area. (role: adjacent plugin/runtime owner; confidence: medium; commits: 90c0edcb61cd; files: src/plugins/web-provider-runtime-shared.ts, src/plugins/web-search-providers.runtime.ts, extensions/brave/openclaw.plugin.json)

Remaining risk / open question:

  • I did not execute targeted Vitest or formatter commands in this read-only review; validation beyond source inspection relies on the author-reported test plan.
  • I did not run a live Gateway/Brave reproduction, so the runtime proof is source-level rather than end-to-end live proof.

Codex review notes: model gpt-5.5, reasoning high; reviewed against dadf0005ec3a.

Re-review progress:

joeykrug added 3 commits May 4, 2026 00:29
When createWebSearchTool is wired with lateBindRuntimeConfig: true, the
first-class assistant tool now lives off whatever runtime is active at
execute time. That works in the gateway process where runtime metadata
and the active secrets snapshot are populated, but in agent contexts that
do not share that in-process state, both fall through to undefined and
the tool returned "web_search is disabled or no provider is available"
even though `openclaw capability web search` and direct provider runtime
execution succeeded.

Two fixes:

- src/agents/tools/web-search.ts: when late-binding, fall back to
  options.runtimeWebSearch when the active runtime web tools metadata is
  null, and fall back to options.config when getActiveSecretsRuntimeSnapshot
  is null. Derive a configured provider id from
  config.tools.web.search.provider and use it together with the runtime
  selection when deciding preferRuntimeProviders, so an explicit Brave/
  Perplexity selection still discovers the configured plugin even when
  no runtime provider id is bound.
- src/plugins/web-provider-runtime-shared.ts: the active gateway plugin
  registry may be otherwise compatible with the active config while
  contributing zero web providers (channels, memory, harnesses, and
  sidecars without Brave/web). Treating that empty active registry as
  authoritative meant first-class tools resolved to "no provider".
  Fall through to the scoped provider plugin load when the active
  registry returns no providers. Explicit `onlyPluginIds: []` still
  short-circuits to [] to preserve the empty-scope contract.

Adds regression tests for both seams.
@joeykrug joeykrug force-pushed the fix/brave-web-search-first-class branch from b37c319 to d0cdd05 Compare May 4, 2026 04:30
@byungskers

This comment was marked as low quality.

@steipete steipete merged commit bbdf1fe into openclaw:main May 4, 2026
108 checks passed
@steipete
Copy link
Copy Markdown
Contributor

steipete commented May 4, 2026

Landed via GitHub rebase merge onto main.

  • Gate: PR CI/check rollup green; local targeted pnpm test src/plugins/web-provider-runtime-shared.test.ts src/agents/tools/web-search.late-bind.test.ts src/agents/tools/web-search.test.ts src/agents/tools/web-search.signal.test.ts; local targeted pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/agents/tools/web-search.late-bind.test.ts src/agents/tools/web-search.ts src/plugins/web-provider-runtime-shared.test.ts src/plugins/web-provider-runtime-shared.ts
  • Source head: d0cdd05
  • Land commit: bbdf1fe

Thanks @joeykrug!

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

Labels

agents Agent runtime and tooling size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web_search reports 'no provider available' from first-class assistant tools when capability + runtime succeed

3 participants