Skip to content

Silent failure when web_search is in toolsAllow but no search provider plugin is enabled #97654

Description

@riazrahaman

Summary

When a cron job has web_search in its toolsAllow list but every web search provider plugin is disabled, openclaw silently makes the tool unavailable at runtime. The model then either fails to call it or explains it cannot search, and delivers an apology as the output. The run completes with status: ok and lastDeliveryStatus: delivered — so the operator has no signal that anything is wrong.

Behaviour

Given a cron job with:

"payload": {
  "kind": "agentTurn",
  "message": "Use the 'web_search' tool to find today's weather for Abu Dhabi...",
  "toolsAllow": ["web_search"]
}

And all search provider plugins disabled (duckduckgo, exa, firecrawl, tavily, searxng all enabled: false):

  • The cron job fires and runs to completion
  • status: ok, lastDeliveryStatus: delivered are recorded
  • The delivered content is the model apologising: "I'm sorry, but I'm currently unable to perform the web search required..."
  • No warning appears in cron_run_logs.diagnostics_summary
  • openclaw logs shows nothing actionable

Expected Behaviour

One or more of:

  1. At run start: a preflight check detects that web_search is in toolsAllow but listWebSearchProviders() returns an empty list, and either fails fast with a clear error or adds a diagnostic warning:

    ⚠️ web_search tool requested (toolsAllow) but no web search provider plugin is enabled.
    Enable one with: openclaw plugins enable duckduckgo
    
  2. In run diagnostics: diagnostics_summary includes the above when the model's tool call to web_search receives no registered handler.

  3. At job creation / openclaw cron add: warn if a tool in toolsAllow has no registered provider at the time the job is created.

Why It's a Silent Failure

bundled-capability-runtime-D0Uof9U-.js builds webSearchProviders = [] when no plugin fulfils the webSearchProviders contract. The empty array is passed through to the tool registry without any warning. toolsAllow only gates whether a registered tool is permitted — it does not validate whether the tool is registered. There is no cross-check between the two.

The run therefore reaches status: ok because the agent session itself completed without a system-level error; the apology from the model is a valid text response, not an exception.

Reproduction

  1. Ensure all search plugins are disabled:
    openclaw plugins list   # duckduckgo, exa, firecrawl, tavily, searxng all show "disabled"
    
  2. Create (or have) a cron job with toolsAllow: ["web_search"] and a prompt that instructs the model to use web_search.
  3. Trigger the job: openclaw cron run <job-id>.
  4. Observe: status: ok, delivered: true, content is a "cannot search" apology. No warning anywhere.

Fix Suggestion

In the preflight path of cron/agent execution (e.g. attempt-execution-B_ltmss6.js or the cron runner), before the turn is dispatched:

const requestedWebSearch = toolsAllow?.includes("web_search");
const hasSearchProvider = registry.webSearchProviders.length > 0;
if (requestedWebSearch && !hasSearchProvider) {
  diagnostics.warn(
    'web_search is in toolsAllow but no search provider plugin is enabled. ' +
    'Run: openclaw plugins enable duckduckgo'
  );
}

The same pattern applies to web_fetch and browser tools.

Environment

  • openclaw version: 2026.6.10
  • Platform: macOS (darwin)
  • Affected job types: any cron job with toolsAllow: ["web_search"]

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.no-staleExclude from stale automation

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions