UI-related note: this touches the Settings/UI path and may be lower priority during the ongoing frontend refactor.
Summary
The web search runtime can read provider API keys from environment variables, but the Settings Test button and /api/config/test-web-search require an inline key in the request body.
Why it matters
Production deployments commonly keep secrets in environment variables or custom env instead of writing them into config files. The actual agent runtime can use TAVILY_API_KEY, CUSTOM_WEB_SEARCH_API_KEY, GLM_WEB_SEARCH_API_KEY, or ZAI_API_KEY, but Settings cannot test that valid runtime configuration. This can push users toward copying secrets back into the UI/config just to make the test button work.
Evidence
src/tool/builtin/webSearch.ts:140 resolves the runtime key through resolveApiKey(...).
src/tool/builtin/webSearch.ts:142 only fails when no key is available and the provider is not custom with auth: none.
src/tool/builtin/webSearch.ts:203 to src/tool/builtin/webSearch.ts:215 defines resolveApiKey(...) and reads TAVILY_API_KEY, CUSTOM_WEB_SEARCH_API_KEY, GLM_WEB_SEARCH_API_KEY, and ZAI_API_KEY from runtime context/env.
src/tool/builtin/webSearch.ts:497 to src/tool/builtin/webSearch.ts:507 injects the resolved key into bearer, query, or body auth modes.
ui/src/components/settings/view/tabs/PilotDeckConfigTab.tsx:2002 to ui/src/components/settings/view/tabs/PilotDeckConfigTab.tsx:2008 computes trimmedKey only from the inline apiKey field and returns before testing when it is empty.
ui/src/components/settings/view/tabs/PilotDeckConfigTab.tsx:2170 disables the Test button when !hasUsableSecret(apiKey).
ui/server/routes/config.js:322 to ui/server/routes/config.js:324 computes trimmedKey from req.body.apiKey and returns API key is required. unless the provider is custom with auth: none.
Validation
Validation level: dynamic runtime reproduction plus UI/server source control-flow confirmation.
Reproduction used a mocked custom bearer web-search provider with no inline key and env.CUSTOM_WEB_SEARCH_API_KEY = "env-secret".
Key output: the runtime request included Authorization: Bearer env-secret, proving the actual tool path accepts env-provided keys. In contrast, the Settings route checks only body/input apiKey and returns API key is required. before reaching equivalent runtime key resolution.
Boundary: this did not launch the full browser UI. The disabled-button behavior and early return are confirmed from the Settings component source, and the server rejection is confirmed from the route source.
Expected behavior
Settings Test should be able to validate the same web search configuration that the runtime can execute. If a provider key is available from env/customEnv, the UI/server test path should allow testing without requiring the secret to be pasted inline.
Existing coverage checked
No existing issue or PR was found that fixes env-key support for the Settings Test path. PR #182 handles friendlier behavior for unconfigured web search, but it does not make /api/config/test-web-search use runtime-equivalent key resolution. Issue #68 is related background for custom env propagation, but it does not cover this Settings Test/runtime mismatch.
Coverage checked by searching for TAVILY_API_KEY test-web-search, CUSTOM_WEB_SEARCH_API_KEY, hasUsableSecret webSearch, and API key is required.
Suggested fix
Make the backend test route use the same key-resolution semantics as the runtime. The frontend should allow testing when an env/customEnv key is available and make the key source clear to the user.
The route should still reject missing credentials when neither inline config nor env/customEnv provides a key, except for custom with auth: none.
Suggested tests
- Tavily test succeeds with
TAVILY_API_KEY and no inline key.
- Custom bearer test succeeds with
CUSTOM_WEB_SEARCH_API_KEY and no inline key.
- GLM/ZAI test succeeds with
GLM_WEB_SEARCH_API_KEY or ZAI_API_KEY and no inline key.
- Missing inline key and missing env key still fails with a clear error.
custom with auth: none continues to allow an empty key.
Submitted with Codex.
UI-related note: this touches the Settings/UI path and may be lower priority during the ongoing frontend refactor.
Summary
The web search runtime can read provider API keys from environment variables, but the Settings Test button and
/api/config/test-web-searchrequire an inline key in the request body.Why it matters
Production deployments commonly keep secrets in environment variables or custom env instead of writing them into config files. The actual agent runtime can use
TAVILY_API_KEY,CUSTOM_WEB_SEARCH_API_KEY,GLM_WEB_SEARCH_API_KEY, orZAI_API_KEY, but Settings cannot test that valid runtime configuration. This can push users toward copying secrets back into the UI/config just to make the test button work.Evidence
src/tool/builtin/webSearch.ts:140resolves the runtime key throughresolveApiKey(...).src/tool/builtin/webSearch.ts:142only fails when no key is available and the provider is notcustomwithauth: none.src/tool/builtin/webSearch.ts:203tosrc/tool/builtin/webSearch.ts:215definesresolveApiKey(...)and readsTAVILY_API_KEY,CUSTOM_WEB_SEARCH_API_KEY,GLM_WEB_SEARCH_API_KEY, andZAI_API_KEYfrom runtime context/env.src/tool/builtin/webSearch.ts:497tosrc/tool/builtin/webSearch.ts:507injects the resolved key into bearer, query, or body auth modes.ui/src/components/settings/view/tabs/PilotDeckConfigTab.tsx:2002toui/src/components/settings/view/tabs/PilotDeckConfigTab.tsx:2008computestrimmedKeyonly from the inlineapiKeyfield and returns before testing when it is empty.ui/src/components/settings/view/tabs/PilotDeckConfigTab.tsx:2170disables the Test button when!hasUsableSecret(apiKey).ui/server/routes/config.js:322toui/server/routes/config.js:324computestrimmedKeyfromreq.body.apiKeyand returnsAPI key is required.unless the provider iscustomwithauth: none.Validation
Validation level: dynamic runtime reproduction plus UI/server source control-flow confirmation.
Reproduction used a mocked custom bearer web-search provider with no inline key and
env.CUSTOM_WEB_SEARCH_API_KEY = "env-secret".Key output: the runtime request included
Authorization: Bearer env-secret, proving the actual tool path accepts env-provided keys. In contrast, the Settings route checks only body/inputapiKeyand returnsAPI key is required.before reaching equivalent runtime key resolution.Boundary: this did not launch the full browser UI. The disabled-button behavior and early return are confirmed from the Settings component source, and the server rejection is confirmed from the route source.
Expected behavior
Settings Test should be able to validate the same web search configuration that the runtime can execute. If a provider key is available from env/customEnv, the UI/server test path should allow testing without requiring the secret to be pasted inline.
Existing coverage checked
No existing issue or PR was found that fixes env-key support for the Settings Test path. PR #182 handles friendlier behavior for unconfigured web search, but it does not make
/api/config/test-web-searchuse runtime-equivalent key resolution. Issue #68 is related background for custom env propagation, but it does not cover this Settings Test/runtime mismatch.Coverage checked by searching for
TAVILY_API_KEY test-web-search,CUSTOM_WEB_SEARCH_API_KEY,hasUsableSecret webSearch, andAPI key is required.Suggested fix
Make the backend test route use the same key-resolution semantics as the runtime. The frontend should allow testing when an env/customEnv key is available and make the key source clear to the user.
The route should still reject missing credentials when neither inline config nor env/customEnv provides a key, except for
customwithauth: none.Suggested tests
TAVILY_API_KEYand no inline key.CUSTOM_WEB_SEARCH_API_KEYand no inline key.GLM_WEB_SEARCH_API_KEYorZAI_API_KEYand no inline key.customwithauth: nonecontinues to allow an empty key.Submitted with Codex.