feat: add Brave Search LLM Context API mode for web_search#33383
feat: add Brave Search LLM Context API mode for web_search#33383thirumaleshp wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR adds a new Key changes:
Issue found:
Confidence Score: 3/5
Last reviewed commit: 6bdc347 |
src/agents/tools/web-search.ts
Outdated
| const cacheKey = normalizeCacheKey( | ||
| params.provider === "brave" | ||
| ? `${params.provider}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}:${params.freshness || "default"}` | ||
| ? `${params.provider}:${effectiveBraveMode}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}:${params.freshness || "default"}` |
There was a problem hiding this comment.
Cache key includes unused parameters for llm-context mode
The Brave cache key (line 1229) unconditionally includes ${params.count} and ${params.ui_lang}, but runBraveLlmContextSearch does not accept or forward either of these parameters to the API (lines 1359–1366). This means two llm-context requests with the same query but differing count or ui_lang values will always miss each other's cache and trigger redundant API calls, even though the Brave LLM Context endpoint would return identical results for both.
The llm-context cache key should only include the parameters that are actually forwarded to the API: country, search_lang, and freshness. Consider branching the cache key expression based on effectiveBraveMode to exclude count and ui_lang when mode is "llm-context".
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/tools/web-search.ts
Line: 1229
Comment:
**Cache key includes unused parameters for `llm-context` mode**
The Brave cache key (line 1229) unconditionally includes `${params.count}` and `${params.ui_lang}`, but `runBraveLlmContextSearch` does not accept or forward either of these parameters to the API (lines 1359–1366). This means two `llm-context` requests with the same query but differing `count` or `ui_lang` values will always miss each other's cache and trigger redundant API calls, even though the Brave LLM Context endpoint would return identical results for both.
The `llm-context` cache key should only include the parameters that are actually forwarded to the API: `country`, `search_lang`, and `freshness`. Consider branching the cache key expression based on `effectiveBraveMode` to exclude `count` and `ui_lang` when mode is `"llm-context"`.
How can I resolve this? If you propose a fix, please make it concise.
src/agents/tools/web-search.ts
Outdated
| const cacheKey = normalizeCacheKey( | ||
| params.provider === "brave" | ||
| ? `${params.provider}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}:${params.freshness || "default"}` | ||
| ? `${params.provider}:${effectiveBraveMode}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}:${params.freshness || "default"}` |
There was a problem hiding this comment.
Cache key includes unused parameters for llm-context mode
The Brave cache key (line 1229) unconditionally includes ${params.count} and ${params.ui_lang}, but runBraveLlmContextSearch does not accept or forward either of these parameters to the API (lines 1359–1366). This means two llm-context requests with the same query but differing count or ui_lang values will always miss each other's cache and trigger redundant API calls, even though the Brave LLM Context endpoint would return identical results for both.
The llm-context cache key should only include the parameters that are actually forwarded to the API: country, search_lang, and freshness. Consider branching the cache key expression based on effectiveBraveMode to exclude count and ui_lang when mode is "llm-context".
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/tools/web-search.ts
Line: 1229
Comment:
**Cache key includes unused parameters for `llm-context` mode**
The Brave cache key (line 1229) unconditionally includes `${params.count}` and `${params.ui_lang}`, but `runBraveLlmContextSearch` does not accept or forward either of these parameters to the API (lines 1359–1366). This means two `llm-context` requests with the same query but differing `count` or `ui_lang` values will always miss each other's cache and trigger redundant API calls, even though the Brave LLM Context endpoint would return identical results for both.
The `llm-context` cache key should only include the parameters that are actually forwarded to the API: `country`, `search_lang`, and `freshness`. Consider branching the cache key expression based on `effectiveBraveMode` to exclude `count` and `ui_lang` when mode is `"llm-context"`.
How can I resolve this? If you propose a fix, please make it concise.
Additional Comments (1)
The Brave cache key (line 1229) unconditionally includes The |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa1fbb98da
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const { results: llmResults, sources } = await runBraveLlmContextSearch({ | ||
| query: params.query, | ||
| apiKey: params.apiKey, | ||
| timeoutSeconds: params.timeoutSeconds, | ||
| country: params.country, |
There was a problem hiding this comment.
Honor count limit in Brave llm-context mode
When tools.web.search.brave.mode is set to "llm-context", this branch calls runBraveLlmContextSearch without passing the requested count, and the returned llmResults are not truncated before being returned/cached. In that mode, web_search can return more results/snippets than the caller asked for, which breaks the documented count (1-10) contract and can materially increase response size/token cost for callers trying to constrain output.
Useful? React with 👍 / 👎.
Add support for Brave's LLM Context API endpoint (/res/v1/llm/context) as an optional mode for the web_search tool. When configured with tools.web.search.brave.mode set to llm-context, the tool returns pre-extracted page content optimized for LLM grounding instead of standard URL/snippet results. The llm-context cache key excludes count and ui_lang parameters that the LLM Context API does not accept, preventing unnecessary cache misses. Closes openclaw#14992 Co-Authored-By: Claude Opus 4.6 <[email protected]>
aa1fbb9 to
ade890a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ade890a8a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| timeoutSeconds: params.timeoutSeconds, | ||
| country: params.country, | ||
| search_lang: params.search_lang, | ||
| freshness: params.freshness, |
There was a problem hiding this comment.
Preserve date range filters in llm-context requests
In Brave llm-context mode, this call forwards only params.freshness and never translates date_after/date_before into a freshness range, unlike the standard Brave branch. As a result, queries that specify date filters are accepted but executed without any date constraint, so users can get stale/unbounded results while believing the filter was applied. Please either derive freshness from dateAfter/dateBefore here as well, or reject date filters in this mode.
Useful? React with 👍 / 👎.
This comment was marked as spam.
This comment was marked as spam.
* main: (70 commits) Refactor release hardening follow-ups (openclaw#39959) docs: clarify bot review conversation ownership (openclaw#39942) fix: harden talk silence timeout parsing (openclaw#39607) (thanks @danodoesdesign) talk: add configurable silence timeout transcript-policy: use named Set for anthropic signature-excluded providers transcript-policy: don't preserve thinking signatures for kimi-coding (openclaw#39798) fix: land mac universal release defaults (openclaw#33891) (thanks @cgdusek) Docs: clarify notarization handoff in mac release flow Docs: mark basic mac dist example as non-notarized Docs: clarify release build arch defaults for mac packaging macOS: default release app builds to universal binaries fix(issue-39839): address tool-call extra params parsing for kimi anthropic-messages docs: use alphabetical provider ordering fix: follow up openclaw#39321 and openclaw#38445 landings docs: note /landpr merge process fix: land Brave llm-context gaps (openclaw#33383) (thanks @thirumaleshp) feat: add Brave Search LLM Context API mode for web_search fix(feishu): restore @larksuiteoapi/node-sdk in root dependencies refactor: tighten codex inline api fallback follow-up macOS: set speech recognition taskHint for Talk Mode mic capture ...
上游更新摘要(abb8f6310 → bda63c3,164 commits): ### 新功能 - ACP: 新增 resumeSessionId 支持 ACP session 恢复(openclaw#41847) - CLI: 新增 openclaw backup create/verify 本地状态归档命令(openclaw#40163) - Talk: 新增 talk.silenceTimeoutMs 配置项,可自定义静默超时(openclaw#39607) - ACP Provenance: 新增 ACP 入站溯源元数据和回执注入(openclaw#40473) - Brave 搜索: 新增 llm-context 模式,返回 AI 精炼摘要(openclaw#33383) - browser.relayBindHost: Chrome relay 可绑定非 loopback 地址(WSL2 支持)(openclaw#39364) - node-pending-work: 新增 node.pending.pull/ack RPC 接口 - Telegram: 新增 exec-approvals 处理器,支持 Telegram 内命令执行审批 - Mattermost: 新增 target-resolution,修复 markdown 保留和 DM media 上传 - MS Teams: 修复 Bot Framework General channel 对话 ID 兼容性(openclaw#41838) - secrets/runtime-web-tools: 全新 web runtime secrets 工具模块 - cron: 新增 store-migration,isolated-agent 直送核心通道,delivery failure notify - TUI: 自动检测浅色终端主题(COLORFGBG),支持 OPENCLAW_THEME 覆盖(openclaw#38636) ### 修复 - macOS: launchd 重启前重启已禁用服务,修复 openclaw update 卡死问题 - Telegram DM: 按 agent 去重入站 DM,防止同一条消息触发重复回复(openclaw#40519) - Matrix DM: 修复 m.direct homeserver 检测,保留房间绑定优先级(openclaw#19736) - 飞书: 清理插件发现缓存,修复 onboarding 安装后重复弹窗(openclaw#39642) - config/runtime snapshots: 修复 config 写入后 secret 快照丢失问题(openclaw#37313) - browser/CDP: 修复 ws:// CDP URL 反向代理和 wildcard 地址重写 - agents/failover: 识别 Bedrock tokens per day 限额为 rate limit ### 版本 - ACPX 0.1.16 - iOS/macOS 版本号更新 - Android: 精简后台权限 构建验证:待执行
Add support for Brave's LLM Context API endpoint (
/res/v1/llm/context) as an optional mode for theweb_searchtool. When configured withtools.web.search.brave.mode: "llm-context", the tool returns pre-extracted page content (text chunks, tables, code blocks) optimized for LLM grounding instead of standard URL/snippet results.Closes #14992
Summary
brave.modeconfig option ("web"or"llm-context"), new response types,runBraveLlmContextSearch()function, mode dispatch inrunWebSearch(), Zod schema validation, help text, and 5 unit tests."web"mode. No changes to other providers (perplexity, grok, gemini, kimi).Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
tools.web.search.brave.modeaccepts"web"(default) or"llm-context""llm-context"is set,web_searchtool description changes to mention LLM Context APIsnippets[](extracted text) instead ofdescription(short snippet), plussourcesmetadata and amode: "llm-context"fieldSecurity Impact (required)
NoNo— reuses existingX-Subscription-Token/BRAVE_API_KEYYes— new endpointhttps://api.search.brave.com/res/v1/llm/contextNoNoapi.search.brave.com), uses the same auth header, and all response content is wrapped throughwrapWebContent()withexternalContent.untrusted: true— same security posture as existing Brave search. Request goes throughwithTrustedWebSearchEndpoint().Repro + Verification
Environment
{ "tools": { "web": { "search": { "provider": "brave", "brave": { "mode": "llm-context" } } } } }Steps
tools.web.search.brave.mode: "llm-context"in configBRAVE_API_KEYenvironment variableweb_searchtool with a queryExpected
mode: "llm-context",results[].snippets[]with extracted text content, andsources[]metadataActual
Evidence
All tests pass: 42/42 web-search, 29/29 config-misc, 29/29 web-tools enabled-defaults. Build succeeds. Formatting passes (oxfmt).
Human Verification (required)
resolveBraveModehandles default/undefined/explicit/invalid values correctly, config Zod validation accepts the newbraveblock, build compiles cleanly"web"), invalid mode value (falls back to"web"), cache key differentiation between modesCompatibility / Migration
YesYes— new optionaltools.web.search.brave.modefieldNo— no config = existing behaviorFailure Recovery (if this breaks)
brave.modefrom config or set it to"web"— falls back to standard searchtools.web.search.braveconfig block needs removalgrounding.genericextraction returns empty results gracefullyRisks and Mitigations
entry.url ?? "",entry.snippets ?? []), so unexpected shapes degrade gracefully to empty results rather than crashes.