NousResearch/hermes-agent

Expose limit parameter in web_search tool

Cluster 16696. Data as of

Nothing open on GitHub. Fix merged in #16934 on 28 Apr 2026. Check it covers your case.

The short answer

0open issues
0open PRs
3items grouped
Known?
Yes. 3 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #16934. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #16934. That is separate from the fix event.
Still open
Nothing open on GitHub.

These items concern adding and exposing a limit parameter for the web_search tool, along with documenting query operators. The request appears across a feature issue and two related pull requests.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #16934 feat(web): expose limit for web_search

    merged to main

    files: tests/tools/test_web_tools_config.py, tools/web_tools.py, website/docs/reference/tools-reference.md

    Show the diff
    • tests/tools/test_web_tools_config.py
      @@ -448,6 +448,54 @@ def test_singleton_returns_same_instance(self):
                   assert client1 is client2
       
       
      +class TestWebSearchSchema:
      +    """Test suite for web_search tool schema and handler wiring."""
      +
      +    def test_schema_exposes_optional_limit(self):
      +        import tools.web_tools
      +
      +        limit_schema = tools.web_tools.WEB_SEARCH_SCHEMA["parameters"]["properties"]["limit"]
      +
      +        assert limit_schema["type"] == "integer"
      +        assert limit_schema["minimum"] == 1
      +        assert limit_schema["maximum"] == 100
      +        assert limit_schema["default"] == 5
      +        assert "limit" not in tools.web_tools.WEB_SEARCH_SCHEMA["parameters"]["required"]
      +
      +    def test_registered_handler_passes_limit(self):
      +        import tools.web_tools
      +
      +        entry = tools.web_tools.registry.get_entry("web_search")
      +        with patch("tools.web_tools.web_search_tool", return_value='{"success": true}') as mock_search:
      +            result = entry.handler({"query": "site:example.com docs", "limit": 12})
      +
      +        assert result == '{"success": true}'
      +        mock_search.assert_called_once_with("site:example.com docs", limit=12)
      +
      +    def test_registered_handler_defaults_limit_to_five(self):
      +        import tools.web_tools
      +
      +        entry = tools.web_tools.registry.get_entry("web_search")
      +        with patch("tools.web_tools.web_search_tool", return_value='{"success": true}') as mock_search:
      +            result = entry.handler({"query": "docs"})
      +
      +        assert result == '{"success": true}'
      +        mock_search.assert_called_once_with("docs", limit=5)
      +
      +    def test_web_search_clamps_limit_before_backend_call(self):
      +        import tools.web_tools
      +
      +        with patch("tools.web_tools._get_backend", return_value="parallel"), \
      +             patch("tools.web_tools._parallel_search", return_value={"success": True, "data": {"web": []}}) as mock_search, \
      +             patch("tools.interrupt.is_interrupted", return_value=False), \
      +             patch.object(tools.web_tools._debug, "log_call"), \
      +             patch.object(tools.web_tools._debug, "save"):
      +            result = json.loads(tools.web_tools.web_search_tool("docs", limit=500))
      +
      +        assert result == {"success": True, "data": {"web": []}}
      +        mock_search.assert_called_once_with("docs", 100)
      +
      +
       class TestWebSearchErrorHandling:
           """Test suite for web_search_tool() error responses."""
       
    • tools/web_tools.py
      @@ -1066,6 +1066,12 @@ def web_search_tool(query: str, limit: int = 5) -> str:
           Raises:
               Exception: If search fails or API key is not set
           """
      +    try:
      +        limit = int(limit)
      +    except (TypeError, ValueError):
      +        limit = 5
      +    limit = min(max(limit, 1), 100)
      +
           debug_call_data = {
               "parameters": {
                   "query": query,
      @@ -2047,13 +2053,20 @@ def check_auxiliary_model() -> bool:
       
       WEB_SEARCH_SCHEMA = {
           "name": "web_search",
      -    "description": "Search the web for information on any topic. Returns up to 5 relevant results with titles, URLs, and descriptions.",
      +    "description": "Search the web for information. Returns up to 5 results by default with titles, URLs, and descriptions. The query is passed through to the configured backend, so operators such as site:domain, filetype:pdf, intitle:word, -term, and \"exact phrase\" may work when the backend supports them.",
           "parameters": {
               "type": "object",
               "properties": {
                   "query": {
                       "type": "string",
      -                "description": "The search query to look up on the web"
      +                "description": "The search query to look up on the web. You may include backend-supported operators such as site:example.com, filetype:pdf, intitle:word, -term, or \"exact phrase\"."
      +            },
      +            "limit": {
      +                "type": "integer",
      +                "description": "Maximum number of results to return. Defaults to 5.",
      +                "minimum": 1,
      +                "maximum": 100,
      +                "default": 5
                   }
               },
               "required": ["query"]
      @@ -2081,7 +2094,7 @@ def check_auxiliary_model() -> bool:
           name="web_search",
           toolset="web",
           schema=WEB_SEARCH_SCHEMA,
      -    handler=lambda args, **kw: web_search_tool(args.get("query", ""), limit=5),
      +    handler=lambda args, **kw: web_search_tool(args.get("query", ""), limit=args.get("limit", 5)),
           check_fn=check_web_api_key,
           requires_env=_web_requires_env(),
           emoji="🔍",
    • website/docs/reference/tools-reference.md
      @@ -179,7 +179,7 @@ Scoped to the Feishu document-comment handler. Drives comment read/write operati
       
       | Tool | Description | Requires environment |
       |------|-------------|----------------------|
      -| `web_search` | Search the web for information on any topic. Returns up to 5 relevant results with titles, URLs, and descriptions. | EXA_API_KEY or PARALLEL_API_KEY or FIRECRAWL_API_KEY or TAVILY_API_KEY |
      +| `web_search` | Search the web for information. Returns up to 5 results by default with titles, URLs, and descriptions. Accepts an optional `limit` (1-100, default 5). The query is passed through to the configured backend, so operators such as `site:domain`, `filetype:pdf`, `intitle:word`, `-term`, and `"exact phrase"` may work when the backend supports them. | EXA_API_KEY or PARALLEL_API_KEY or FIRECRAWL_API_KEY or TAVILY_API_KEY |
       | `web_extract` | Extract content from web page URLs. Returns page content in markdown format. Also works with PDF URLs — pass the PDF link directly and it converts to markdown text. Pages under 5000 chars return full markdown; larger pages are LLM-summarized. | EXA_API_KEY or PARALLEL_API_KEY or FIRECRAWL_API_KEY or TAVILY_API_KEY |
       
       ## `tts` toolset

1 PR closed without merging

From the close comments: merged via another change 1

  • #16808 feat(web): expose limit for web_search · merged via another change → #16934, #16696
Closed issues · 1
  • Closed#16696[Feature]: Expose limit parameter and document query operators in web_search tool
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Merged PRs
#16934
Closed issues
1
Attempts
1 PR closed without merging
Fix link checked
28 Apr 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.

For your agent

The same facts, typed.