fix(*): give web search its config section so maxResults takes effect - #314
Conversation
`tools.web.search.maxResults` has been declared in the schema and read by nobody. Both registration sites built the tool from the key alone, so it fell back to its own default of 5 and a deployer who set the field got no effect and no warning. The cause is that web search was the one tool handed a single field instead of its config section. Every neighbour takes a section -- media_config, exec_config, sandbox_config, context_config -- and the three CLI entry points already held `config.tools.web.search` and reached into it to pull one value out. Passing the section instead is what wires the field, and it retires the `brave_api_key` parameter name in the same move: it has named a Serper key ever since the Brave backend went away, which a reviewer flagged on the capability PR as pre-existing and misleading. `WebSearchTool` keeps its own signature. It is still constructible from a bare key, which is what its unit tests and the error-path test rely on; only the callers that have a config section now pass one. The sub-agent surface gets the same treatment, and a test of its own. A first mutation pass caught the main loop dropping `max_results` and said nothing when the sub-agent did, which is the shape this area keeps taking: two registration sites, a fix applied to one. Five mutations now, all caught. Co-authored-by: Claude (claude-opus-5) <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: one caller was missed by the brave_api_key -> web_search_config rename and now raises at construction; see the inline note.
The fix itself is right and the tests are honest. WebSearchTool.execute really does read self.max_results (n = min(max(count or self.max_results, 1), 10)), so passing the section instead of one field out of it is what makes tools.web.search.maxResults reach the request -- the PR title is accurate. Both registration sites are covered, and both new tests assert the value on the registered tool object rather than on the config that was passed in, so they would catch a regression at either site.
The subagent_run refactor is a strengthening, not a loosening: the spy still asserts runs is non-empty before appending, the collector still opens before the manager is constructed, and the existing test kept its "baselines first" guard against an empty list satisfying the not in. The three call sites in raven/cli/ and the two capability tests all pass a section whose api_key was set first, so nothing silently stopped being gated.
What I checked
- AGENTS.md: commit header (
fix(*): ..., 61 chars, ASCII, lowercase,(*)for multi-scope) and branch name both conform; the reworded comment inmain.pystays English and stays a why; no new test files, both edits land in the existingtest_agent_loop_web_tools.py, so 5.1/5.4 hold. - Callers: grepped every
AgentLoop(/SubagentManager(construction in the repo.benchmarks/pinchbench/direct/raven_executor.py,benchmarks/pinchbench/bot_runner/bot_executor.pyandbenchmarks/appworld/agent_cli.pypass no search kwarg at all;benchmarks/clawbench/stream.pyis the one that breaks. - Backward compat:
brave_api_keyand theself.brave_api_keyattribute are both gone from the public signature with no shim. In-repo that costs exactly the one call site below; if anything outside the repo constructsAgentLoopdirectly, it is a breaking change worth a line in the PR body. - Tests:
uv run pytest tests/test_agent_loop_web_tools.py tests/test_tool_capabilities.py tests/test_agent_loop_tool_search.py -q-> 42 passed, 0 skipped.
Not blocking
max_results is clamped to 10 inside execute, so a deployer who sets maxResults: 20 still gets 10 and no warning. That is pre-existing behaviour on lines this PR does not touch, and the config field is now at least honoured up to the cap -- just noting it since "maxResults takes effect" is the headline.
| max_iterations: int = 40, | ||
| context_window_tokens: int | None = None, | ||
| brave_api_key: str | None = None, | ||
| web_search_config: "WebSearchConfig | None" = None, |
There was a problem hiding this comment.
This rename misses a caller. benchmarks/clawbench/stream.py:146 still passes brave_api_key=self.config.tools.web.search.api_key or None, and AgentLoop.__init__ takes no **kwargs, so every clawbench run now dies before the first task:
$ uv run python -c "from raven.agent.loop import AgentLoop; AgentLoop(provider=None, workspace='.', brave_api_key='k')"
TypeError: AgentLoop.__init__() got an unexpected keyword argument 'brave_api_key'
Ruff will not catch it (wrong kwarg, not a lint), and no test constructs that harness, so CI stays green while the benchmark entry point is broken. The one-line fix mirrors the three CLI sites:
web_search_config=self.config.tools.web.search,Worth grepping for brave_api_key once more before merge -- that is the only remaining hit today.
Summary
Stacked on #312 -- set the base branch to
feat/tool_capability_inventory_gh,not
main. Againstmainthe diff would carry that PR's commits as well. Itcloses the naming nit raised in review there, so it is a follow-up rather than
an independent change.
tools.web.search.maxResultshas been declared in the schema and read bynobody. Both registration sites built the tool from the key alone:
so it fell back to its own default of 5, and a deployer who set the field got no
effect and no warning that the setting was inert.
One cause, two symptoms
Web search was the one tool handed a single field instead of its config section.
Every neighbour takes a section --
media_config,exec_config,sandbox_config,context_config-- and all three CLI entry points alreadyheld
config.tools.web.searchand reached into it to pull one value out:Passing the section is what wires the field. It also retires the parameter name
in the same move, which is the second symptom:
brave_api_keyhas named aSerper key ever since the Brave backend went away. That was flagged in review on
#312 as pre-existing and misleading, correctly, and it is not a separate rename
-- passing one field out of a section is exactly why the parameter ended up
named after a vendor rather than after what it configures.
WebSearchToolkeeps its own signature. It is still constructible from a barekey, which its unit tests and the error-path test rely on; only the callers that
have a config section now pass one.
The sub-agent surface
Same change there, and a test of its own. This matters more than it looks: a
first mutation pass caught the main loop dropping
max_resultsand said nothingwhen the sub-agent dropped it, because nothing was watching that call site. Two
registration sites with a fix applied to one is the shape this area keeps
taking, and it is the same gap the gate in #312 had to close by hand.
Type
The parameter rename is a refactor riding along, not a second topic: it is the
same edit that wires the field.
Verification
The one failure is
test_read_file_image.py::test_an_attachment_that_cannot_be_ read_costs_a_note_not_the_turn, which fails the same way onmainwith thesecommits absent: it makes a file unreadable with
chmod 000, which does notblock root, so it fails for anyone running the suite as root and passes in CI.
#313 is the fix. This branch touches neither that file nor the code under it.
Five mutations, each caught:
The second line is the one worth reading. Before its test existed that mutation
passed clean -- the wiring was fixed at both call sites and asserted at one.
Risk
One behaviour change, and it is the point:
tools.web.search.maxResultsnowreaches the tool. An install that set it was getting 5 results and now gets what
it asked for. An install that never set it is unaffected -- the schema default
is 5, which is also the value the tool fell back to. The per-call
countargument still wins over both, unchanged.
brave_api_keyis gone fromAgentLoopandSubagentManager. Both areconstructed inside this repo only -- the three CLI entry points and the tests --
and all were updated; no deprecation shim, since nothing external names it.
Rollback is a revert. No configuration is read differently beyond the field that
was already meant to be read.
Related Issues
N/A