openclaw - ✅(Solved) Fix Runtime drops plugin web tools after config write [3 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#77826Fetched 2026-05-06 06:20:42
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
2
Author
Timeline (top)
cross-referenced ×3commented ×1referenced ×1

Fix Action

Fix / Workaround

Workaround:

  • Set tools.web.search.openaiCodex.enabled: true in ~/.openclaw/openclaw.json. The patchCodexNativeWebSearchPayload at dist/codex-native-web-search-*.js injects web_search at API-payload time, masking the bug for web search but not for the other plugin tools (web_fetch, lobster, memory_*, etc.).
  • Restart gateway after the bug fires to reset state.

PR fix notes

PR #77859: fix(runtime): prevent fast-path snapshot refresh from clobbering active web tool metadata

Description (problem / solution / changelog)

Summary

  • Problem: After any config write (doctor --fix, plugins registry --refresh, or any concurrent agent config write), web_search, web_fetch, image_generate, memory_*, and other plugin-provided tools silently disappear from every subsequent tool list. The bug fires reliably on first config write post-startup and persists until gateway restart.

  • Root Cause: prepareSecretsRuntimeSnapshot in src/secrets/runtime.ts has a fast path (canUseSecretsRuntimeFastPath) that returns webTools: createEmptyRuntimeWebToolsMetadata() when the source config has no web surface and no SecretRef candidates. finalizeRuntimeSnapshotWrite in src/config/runtime-snapshot.ts passes nextSourceConfig — a potentially stripped or partial slice from the config writer — to the refresh handler registered by activateSecretsRuntimeSnapshot. If that slice lacks a web surface, the fast path fires, and activateSecretsRuntimeSnapshot previously called setActiveRuntimeWebToolsMetadata(next.webTools) unconditionally, treating "fast-path unknown" the same as "resolver-confirmed absent." A naïve guard keying off activeSnapshot.sourceConfig is insufficient: that field is overwritten on every activation including fast-path ones, so after the first stripped-config refresh it no longer reflects the web surface from the last full-resolver run, and a second consecutive partial refresh bypasses the guard and clobbers the metadata anyway.

  • Fix: Introduce a module-level lastFullResolverSourceConfig variable that is only updated when the full resolver actually runs (!next.webToolsFromFastPath), and reset alongside other runtime state in clearActiveSecretsRuntimeState. In activateSecretsRuntimeSnapshot, compute shouldPreserveWebTools = next.webToolsFromFastPath && lastFullResolverSourceConfig !== null && hasRuntimeWebToolConfigSurface(lastFullResolverSourceConfig) before any state mutations, then skip setActiveRuntimeWebToolsMetadata when shouldPreserveWebTools is true. Because lastFullResolverSourceConfig is never overwritten by fast-path activations, the preservation signal is durable across any number of successive partial refreshes. A full-resolver run always updates the variable and unconditionally overwrites the metadata, so authoritative no-web configs are still cleared correctly.

  • What changed:

    • src/secrets/runtime.ts: added webToolsFromFastPath: boolean to PreparedSecretsRuntimeSnapshot type and cloneSnapshot; set the field in both branches of prepareSecretsRuntimeSnapshot; added lastFullResolverSourceConfig module-level variable and its reset in clearActiveSecretsRuntimeState; replaced the unconditional setActiveRuntimeWebToolsMetadata call in activateSecretsRuntimeSnapshot with a shouldPreserveWebTools guard backed by lastFullResolverSourceConfig.
    • src/secrets/runtime-web-tools-state.test.ts: three new integration tests — single fast-path refresh preserves metadata; full-resolver run with no web surface clears metadata; two successive fast-path refreshes both preserve metadata (regression for the durability fix).
    • src/secrets/runtime.fast-path.test.ts: two new unit tests asserting webToolsFromFastPath is true on the fast path and false when the full resolver runs.
    • CHANGELOG.md: entry added under ## Unreleased.
  • What did NOT change (scope boundary): canUseSecretsRuntimeFastPath and hasRuntimeWebToolConfigSurface logic are untouched. runtime-web-tools-state.ts, runtime-snapshot.ts, io.ts, and mutate.ts are untouched. The public contract of getActiveRuntimeWebToolsMetadata and all its consumers are unchanged. The fast path continues to skip the heavy resolver import for clean startup paths.


Reproduction

  1. Configure the gateway with tools.web.search.provider: gemini and a valid API key under plugins.entries.google.config.webSearch.apiKey.
  2. Start the gateway. Open a chat session and confirm web_search appears in the tool list.
  3. Trigger any config write — e.g. openclaw plugins registry --refresh, openclaw doctor --fix, or write any unrelated config key via the API.
  4. Open a new chat session and inspect the tool list.

Before fix: web_search, web_fetch, image_generate, memory_*, lobster all absent after step 3. After fix: tool list is identical to step 2 regardless of how many config writes occur.


Risk / Mitigation

  • Risk: If a user intentionally removes all web configuration via a full-resolver-triggering write (one that includes a SecretRef or a web surface entry), lastFullResolverSourceConfig is updated and metadata is cleared correctly. If the removal is done via a write that produces no SecretRefs and no web surface (fast-path path), the metadata is preserved until a full-resolver run occurs (e.g. gateway restart). This is the same tradeoff identified in the linked issue under option (a).
  • Mitigation: The three new integration tests directly exercise the preservation path (single and double fast-path refresh) and the authoritative-clear path (full resolver, no web surface). The lastFullResolverSourceConfig variable is module-scoped, reset with the rest of runtime state, and not exposed externally, limiting the blast radius of the change.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Fixes #77826

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/secrets/runtime-web-tools-state.test.ts (modified, +152/-0)
  • src/secrets/runtime.fast-path.test.ts (modified, +39/-0)
  • src/secrets/runtime.ts (modified, +28/-1)

PR #78067: fix: preserve web tool metadata across config refresh

Description (problem / solution / changelog)

Summary

Prevents stripped config-write refreshes from dropping active runtime web tool metadata. When a refresh source config omits web tool surface paths that were present in the active source snapshot, the secrets runtime now preserves those previous web surface paths before preparing the refreshed snapshot, so the fast path cannot overwrite populated web metadata with an empty struct just because a writer had a partial source view.

Changes

  • Preserves omitted tools.web.search, tools.web.x_search, and tools.web.fetch paths from the active source snapshot during runtime refresh.
  • Preserves omitted plugin config.webSearch / config.webFetch paths for plugin-provided web tools.
  • Adds regression coverage for a stripped refresh source preserving an active Brave web search provider instead of taking the empty fast path.

Testing

  • PATH="/tmp/openclaw-pnpm-shim:$PATH" pnpm vitest run src/secrets/runtime.fast-path.test.ts — passed, 6 tests.
  • git diff --check — passed.
  • PATH="/tmp/openclaw-pnpm-shim:$PATH" node scripts/check-changed.mjs — all gates passed through the final pairing-account guard; process was SIGKILLed at final exit as observed on this host. Standalone PATH="/tmp/openclaw-pnpm-shim:$PATH" node scripts/check-pairing-account-scope.mjs passed.

Fixes #77826

Changed files

  • src/secrets/runtime.fast-path.test.ts (modified, +63/-1)
  • src/secrets/runtime.ts (modified, +72/-2)

PR #78268: fix(secrets): preserve web tools on stripped refresh

Description (problem / solution / changelog)

Summary

  • preserve active resolved runtime web-tool metadata when a config refresh receives a stripped source view with no web/plugin containers
  • keep explicit empty web/plugin containers authoritative so deliberate removals still clear web tools
  • add regression coverage for stripped refresh preservation and explicit empty web config clearing
  • update model fallback test fixture for the current plugin metadata snapshot env requirement

Fixes #77826.

Verification

  • pnpm test src/secrets/runtime.fast-path.test.ts src/secrets/runtime-web-tools-state.test.ts src/config/runtime-snapshot.test.ts
  • pnpm check:changed

Changed files

  • src/agents/model-fallback.test.ts (modified, +3/-1)
  • src/secrets/runtime.fast-path.test.ts (modified, +114/-5)
  • src/secrets/runtime.ts (modified, +54/-1)
RAW_BUFFERClick to expand / collapse

Repro:

  1. OpenClaw 2026.5.2 (likely affects 2026.4.x as well)
  2. Start gateway with tools.web.search.provider: "brave" (and/or openaiCodex.enabled: true); confirm web tools registered.
  3. Trigger one or more config writes (doctor --fix, plugins registry --refresh, third-party agent writing config concurrently).
  4. Open a fresh chat session: web_search, web_fetch, memory_*, lobster, image/music/video_generate are all missing from the tool list.

Cause:

  • dist/runtime-Dg2ko22y.js:161 canUseSecretsRuntimeFastPath returns true when source config has no tools.web.{search,x_search,fetch} AND no plugin entry with webSearch/webFetch config AND no secret-ref candidates.
  • When fast-path returns true, prepareSecretsRuntimeSnapshot returns webTools: createEmptyRuntimeWebToolsMetadata() (line 188).
  • finalizeRuntimeSnapshotWrite (in dist/runtime-snapshot-Bgtbceve.js:139) invokes the refresh handler with nextSourceConfig, which can be a stripped or rewritten config from a writer.
  • The refresh handler (registered at runtime-Dg2ko22y.js:267) calls prepareSecretsRuntimeSnapshot with that nextSourceConfig. If the writer's source config view lacks tools.web, fast-path triggers, and setActiveRuntimeWebToolsMetadata overwrites the working metadata with the empty struct.

Suggested fix:

  • The fast-path optimization should not be allowed to OVERWRITE a populated active webTools metadata with an empty one. Either: (a) prepareSecretsRuntimeSnapshot should require an explicit "I know there's no web surface" assertion before returning empty metadata, and otherwise preserve the prior populated state; or (b) The refresh handler should diff nextSourceConfig against activeSnapshot.sourceConfig and skip the fast-path branch if nextSourceConfig is not strictly a superset of the prior config's web surface; or (c) Writers that produce a nextSourceConfig should never elide tools.web if it was present in the prior source — i.e. the spread-write shape ({...sourceConfig, ...overrides}) needs a guard rail.

Workaround:

  • Set tools.web.search.openaiCodex.enabled: true in ~/.openclaw/openclaw.json. The patchCodexNativeWebSearchPayload at dist/codex-native-web-search-*.js injects web_search at API-payload time, masking the bug for web search but not for the other plugin tools (web_fetch, lobster, memory_*, etc.).
  • Restart gateway after the bug fires to reset state.

Filer notes:

  • Investigation artifact: local workspace research/infra/2026-05-04_plugin-tool-drop-investigation.md
  • Original repro session 2026-04-25 by Mr. Grayden user; auto-memory entry project_grayden_web_tool_probe.
  • File hashes will rotate; quote function names + line numbers, not file paths.

extent analysis

TL;DR

The most likely fix is to modify the prepareSecretsRuntimeSnapshot function to preserve the prior populated webTools metadata when the fast-path optimization is triggered.

Guidance

  • Review the prepareSecretsRuntimeSnapshot function to ensure it does not overwrite the active webTools metadata with an empty one when the fast-path optimization is triggered.
  • Consider implementing a diff check between nextSourceConfig and activeSnapshot.sourceConfig to skip the fast-path branch if nextSourceConfig is not a superset of the prior config's web surface.
  • Writers that produce a nextSourceConfig should be modified to never elide tools.web if it was present in the prior source.
  • As a temporary workaround, setting tools.web.search.openaiCodex.enabled: true in ~/.openclaw/openclaw.json can mask the bug for web search.

Example

No code snippet is provided as the issue does not contain sufficient information to create a concrete example.

Notes

The provided workaround only masks the bug for web search and does not fix the issue for other plugin tools. A more comprehensive solution is required to address the root cause.

Recommendation

Apply the workaround by setting tools.web.search.openaiCodex.enabled: true in ~/.openclaw/openclaw.json to temporarily mitigate the issue, and prioritize implementing a permanent fix to the prepareSecretsRuntimeSnapshot function.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Runtime drops plugin web tools after config write [3 pull requests, 1 comments, 2 participants]