Skip to content

[NemoClaw][Brave Search][Onboard] Web-search onboard still fails the image build — generate-openclaw-config.mts writes the legacy tools.web.search schema (#4955 follow-up) #5266

@zhiyanliu

Description

@zhiyanliu

[NemoClaw][Brave Search][Onboard] Web-search onboard still fails the image build — generate-openclaw-config.mts writes the legacy tools.web.search schema (#4955 follow-up)

TL;DR: Enabling Brave Web Search at onboarding still aborts the sandbox image build at the OpenClaw plugin-install step. #4955 pinned/installed the Brave plugin but left generate-openclaw-config.mts writing the legacy tools.web.search schema. openclaw plugins install validates config up front, the legacy shape fails that validation with exit 1 (under set -eu), and the build dies before doctor --fix can migrate it. One-line schema fix below; verified end-to-end. PR incoming.

Symptom nemoclaw onboard with web search enabled → build aborts at OpenClaw plugin-install RUN (Step 69/88 here). Any channel enabled in the same onboard (e.g. Slack) never installs.
Root cause generate-openclaw-config.mts writes legacy tools.web.search.apiKey (inline). openclaw plugins install pre-validates config → exit 1 on legacy shape → set -eu aborts build before doctor --fix runs.
Proof base image, OpenClaw 2026.5.27: legacy schema → plugins install EXIT=1; new schema → EXIT=0.
Fix emit current schema in generate-openclaw-config.mts (tools.web.search = {enabled, provider} + plugins.entries.brave.config.webSearch.apiKey). Verified: install 0, doctor --fix Errors: 0, config validate passes, real onboard with web search + Slack builds & works.
Regression of #4955 (merged, closed #3948) — fixed the plugin pin/install + doctor apiKey env, but not the config schema.

Root cause

#4955 added the build-time @openclaw/brave-plugin@${OPENCLAW_VERSION} install and threaded BRAVE_API_KEY into the doctor env, assuming openclaw doctor --fix would migrate the legacy tools.web.search block. But generate-openclaw-config.mts still emits the legacy schema:

// scripts/generate-openclaw-config.mts (current main)
if (env.NEMOCLAW_WEB_SEARCH_ENABLED === "1") {
  tools.web.search = {
    enabled: true,
    provider: "brave",
    apiKey: "openshell:resolve:env:BRAVE_API_KEY", // legacy: inline apiKey, rejected by OpenClaw 2026.5.x
  };
}

Build order is: generate-openclaw-config.mtsopenclaw plugins install …brave-pluginopenclaw doctor --fix. plugins install validates the existing config before installing, so on the legacy shape it exits non-zero while the plugin is not yet installed — the exact build-time state. set -eu aborts the RUN, and doctor --fix (which would migrate the schema) never runs. Ordering deadlock: the config references the brave provider before the plugin exists, and the command that installs the plugin refuses to run against that config.

Agent-visible error inside the build:

OpenClaw config is invalid
  - tools.web.search.provider: web_search provider is not available: brave (install or enable plugin "brave", then run openclaw doctor --fix)
  - tools.web.search: provider-owned config moved to plugins.entries.<plugin>.config.webSearch. Run "openclaw doctor --fix".

Reproduction

Full path: on current main (post-#4955), export COMPATIBLE_API_KEY=… BRAVE_API_KEY=…, run nemoclaw onboard --recreate-sandbox, answer Yes to Brave Web Search, enable Slack → build aborts at the plugin-install RUN.

Minimal (no onboard needed):

docker run --rm -it ghcr.io/nvidia/nemoclaw/sandbox-base:v0.0.55 bash -lc '
  npm install -g --no-audit --no-fund openclaw@2026.5.27 >/dev/null 2>&1
  mkdir -p ~/.openclaw
  echo "{\"tools\":{\"web\":{\"fetch\":{\"enabled\":true},\"search\":{\"enabled\":true,\"provider\":\"brave\",\"apiKey\":\"openshell:resolve:env:BRAVE_API_KEY\"}}}}" > ~/.openclaw/openclaw.json
  openclaw plugins install "npm:@openclaw/brave-plugin@2026.5.27" --pin; echo "EXIT=$?"
'
# → "OpenClaw config is invalid" + EXIT=1

Fix (verified, PR incoming)

if (env.NEMOCLAW_WEB_SEARCH_ENABLED === "1") {
  tools.web.search = { enabled: true, provider: "brave" };
  config.plugins.entries.brave = {
    enabled: true,
    config: { webSearch: { apiKey: "openshell:resolve:env:BRAVE_API_KEY" } },
  };
}

config.plugins.entries already exists at this point; this is exactly what doctor --fix produces after a successful install. With it: plugins install → EXIT=0, doctor --fixErrors: 0, config validate passes, and a real onboard --recreate-sandbox with web search + Slack both enabled builds cleanly and both work in the sandbox.

Environment

  • NemoClaw v0.0.63-61-gfa0962988 (tracking main, OPENCLAW_VERSION=2026.5.27)
  • OpenShell 0.0.44 · OpenClaw (sandbox) 2026.5.27 · base image ghcr.io/nvidia/nemoclaw/sandbox-base:v0.0.55
  • macOS (Darwin 25.5.0), Docker Desktop

Checklist

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: integrationsThird-party service integration behaviorarea: onboardingOnboarding FSM, provider setup, sandbox launch, or first-run flowintegration: braveBrave integration behavior

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions