Skip to content

[Bug]: web_search fails in sub-agent sessions with bundled providers (Brave) after 2026.4.29 → 2026.5.2 #76416

@marktran

Description

@marktran

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

After upgrading from 2026.4.29 to 2026.5.2, the web_search tool fails in sub-agent sessions with web_search is disabled or no provider is available, even though the bundled Brave plugin loads, the tool appears in the sub-agent's tool list, and the same call from a main-agent session succeeds.

Steps to reproduce

  1. Run OpenClaw 2026.5.2 with the bundled Brave plugin enabled and tools.web.search.provider = "brave". Configure plugins.entries.brave.config.webSearch.apiKey (any source — SecretRef via 1Password CLI, plain string, or env-var fallback). Verify web_search works in a main-agent session.
  2. From the main agent, spawn a sub-agent (e.g. via the subagents runner) whose tool allowlist narrows the active plugin registry — so the sub-agent's loaded registry does not include the brave plugin.
  3. Have the sub-agent call web_search.
  4. The call returns the error below; the equivalent main-agent call still succeeds.

Expected behavior

web_search resolves the bundled Brave provider in sub-agent sessions, as it did on 2026.4.29 — the bundled-provider lookup is config-driven, not session-registry-scoped.

Actual behavior

Sub-agent receives:

{ "status": "error", "tool": "web_search", "error": "web_search is disabled or no provider is available." }

A direct curl to https://api.search.brave.com/res/v1/web/search with the same credential succeeds, confirming the credential and network path are healthy.

OpenClaw version

2026.5.2

Operating system

Ubuntu 24.04.4 LTS (Linux 6.12.67 x86_64)

Install method

npm global (Node v24.14.1, mise-managed)

Model

anthropic/claude-sonnet-4-6 (sub-agent); main agent on anthropic/claude-opus-4-6

Provider / routing chain

openclaw -> brave-plugin -> api.search.brave.com

Additional provider/model setup details

The Brave plugin manifest declares contracts.webSearchProviders: ["brave"] but no contracts.tools. In a sub-agent session, resolvePluginToolRuntimePluginIds derives onlyPluginIds from the tool allowlist intersected with each plugin's contracts.tools — so brave is excluded from the sub-agent's onlyPluginIds and not loaded into its active registry.

Logs, screenshots, and evidence

Sub-agent trajectory excerpt (2026.5.2, claude-sonnet-4-6, sessionKey agent:main:subagent:<uuid>):

assistant -> toolCall: { "name": "web_search", "arguments": { "query": "..." } }
toolResult: {
  "status": "error",
  "tool": "web_search",
  "error": "web_search is disabled or no provider is available."
}

Impact and severity

  • Affected: any sub-agent task using native web_search against a bundled provider (Brave, Perplexity, etc.). The same code path is shared.
  • Severity: blocks workflow — sub-agents must fall back to exec + curl to reach the search API directly.
  • Frequency: 100% of sub-agent web_search attempts observed across multiple runs on 2026-05-02 / 2026-05-03.
  • Consequence: native web_search is unavailable inside sub-agents on 2026.5.2.

Root cause (from a source dive)

Between v2026.4.29 and v2026.5.2, createWebSearchTool in src/agents/tools/web-search.ts was rewritten to always use lateBindRuntimeConfig: true (src/agents/openclaw-tools.ts:424). In that path, line 95 sets config = undefined and the same undefined is passed to resolveManifestContractOwnerPluginId on line 102:

const config = options?.lateBindRuntimeConfig === true ? undefined : options?.config;
const preferRuntimeProviders =
  Boolean(runtimeProviderId) &&
  !resolveManifestContractOwnerPluginId({
    contract: "webSearchProviders",
    value: runtimeProviderId,
    origin: "bundled",
    config,            // <-- undefined when late-binding
  });

resolveManifestContractOwnerPluginId needs config context to discover the bundled-plugin manifest on disk. Without it, the lookup returns undefined for brave, so preferRuntimeProviders flips from false (the correct value for a bundled provider) to true. runWebSearch then routes through resolveRuntimeWebSearchProviders, which only consults the active runtime plugin registry — narrowed to the sub-agent's tool allowlist, which excludes brave (no contracts.tools). mapRegistryProviders returns [], candidates is empty, and runtime.ts:339 throws "web_search is disabled or no provider is available.".

In a main-agent session, the active registry still contains the bundled providers, so even with preferRuntimeProviders = true the candidate list is non-empty and the call succeeds.

Additional information

  • First known bad: 2026.5.2 (also reproduced against current origin/main).
  • Last known good: 2026.4.29.
  • Workaround for users: sub-agents call exec + curl against https://api.search.brave.com/res/v1/web/search with the same credential. Removing plugins.entries.brave.config.webSearch.apiKey and exporting BRAVE_API_KEY does not fix the sub-agent path — the runtime-registry lookup still misses brave regardless of credential source.
  • Patch in flight: PR will be opened with a regression test in src/agents/tools/web-tools.enabled-defaults.test.ts (fails on origin/main, passes after the fix) and a 6-line change in src/agents/tools/web-search.ts that late-binds the bundled-owner-lookup config to the active runtime snapshot.
  • Distinct from [Bug]: Brave plugin enabled in config but not loaded at runtime — web_search tool unavailable #68249 (plugin not loading at all on 2026.4.15) and [Bug]: 5.2 brave plugin install fails — missing openclaw.extensions, no @beta available #76373 (2026.5.2 install failure).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions