Skip to content

feat: add Tavily search support with Brave-compatible config#661

Closed
akirose wants to merge 2 commits intoHKUDS:mainfrom
akirose:main
Closed

feat: add Tavily search support with Brave-compatible config#661
akirose wants to merge 2 commits intoHKUDS:mainfrom
akirose:main

Conversation

@akirose
Copy link
Copy Markdown

@akirose akirose commented Feb 15, 2026

Summary

This PR expands web_search from Brave-only to a multi-provider setup by adding first-class Tavily support.
It centralizes search configuration through WebSearchConfig and wires the same config through both the main agent and subagents so they share identical search behavior.

It also preserves backward compatibility for legacy Brave config (tools.web.search.apiKey) and adds stronger validation/normalization plus regression tests.

Changed files

File Change
.gitignore Removed tests/ ignore rule
README.md Added Tavily setup examples, option docs, and compatibility notes
nanobot/config/schema.py Extended WebSearchConfig (provider, brave_api_key, tavily_api_key, tavily_search_depth) with normalization helpers
nanobot/agent/tools/web.py Refactored WebSearchTool to support both Brave and Tavily, with provider-specific request/error handling
nanobot/agent/loop.py Added web_search_config injection and passed it to tool setup + SubagentManager
nanobot/agent/subagent.py Added web_search_config support so subagents use the same search settings
nanobot/cli/commands.py Passed full web_search_config into both AgentLoop construction paths
tests/test_web_search.py Added end-to-end behavior tests for Brave/Tavily success and failure cases
tests/test_web_search_tool.py Added provider key forwarding and Tavily depth validation tests
tests/test_web_search_config.py Added schema normalization/validation and legacy key fallback tests
tests/test_search_injection_path.py Verified agent/subagent share the same injected search config
tests/test_config_search_schema.py Verified camelCase config key conversion and schema mapping

Config example

{
  "tools": {
    "web": {
      "search": {
        "provider": "tavily",
        "tavilyApiKey": "tvly-xxx",
        "maxResults": 5,
        "tavilySearchDepth": "advanced"
      }
    }
  }
}

Brave example:

{
  "tools": {
    "web": {
      "search": {
        "provider": "brave",
        "braveApiKey": "BSA-xxx",
        "maxResults": 5
      }
    }
  }
}

Test plan

  • Verify WebSearchConfig normalizes provider and tavilySearchDepth (trim + lowercase)
  • Verify invalid provider / tavilySearchDepth raises validation errors
  • Verify Brave mode uses braveApiKey and still supports legacy apiKey fallback
  • Verify Tavily mode forwards tavilyApiKey, search_depth, and max_results correctly
  • Verify config propagation path AgentLoop -> SubagentManager -> WebSearchTool shares the same config object
  • Verify timeout/missing-key/unsupported-provider paths return clear user-facing errors

@Athemis
Copy link
Copy Markdown
Contributor

Athemis commented Feb 15, 2026

There's another PR which implements support for multiple search engines including Tavily #398

@chengyongru
Copy link
Copy Markdown
Collaborator

Because this issue has been inactive for a long time, I will close it. If there are any other problems, please feel free to open a new issue.

WTHDonghai pushed a commit to WTHDonghai/nanobot that referenced this pull request Mar 22, 2026
…KUDS#661)

When tiktoken is unavailable, the fallback `len(text) // 3` severely
underestimates tokens for CJK text (Chinese/Japanese/Korean characters
are ~1-2 tokens each, not 0.33). This causes text exceeding the 8192-token
API limit to bypass chunking, resulting in BadRequestError.

Use `max(len(text) // 3, len(text.encode("utf-8")) // 4)` instead, which
picks the more conservative estimate. For ASCII-heavy text the char-based
estimate still wins; for CJK text the byte-based estimate correctly
produces ~0.75 tokens per character.

Fixes HKUDS#616, fixes HKUDS#634

Signed-off-by: JiangNan <1394485448@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants