datawhalechina/hello-agents · error · ValueError

TAVILY_API_KEY is required for TavilySearchTool

Error message

TAVILY_API_KEY is required for TavilySearchTool

What it means

ValueError raised by TavilySearchTool.__init__ when the api_key argument is falsy (empty string or None). It is a constructor guard before TavilyClient is even imported, so the failure happens at agent/tool wiring time, not at search time — the game backend cannot start its search-capable agent without a key.

Source

Thrown at Co-creation-projects/afei-GuessWhoAmI/backend/tools/tavily_search_tool.py:24

from hello_agents.tools.base import Tool, ToolParameter

logger = logging.getLogger("game.tools")


class TavilySearchTool(Tool):
    """Tavily web search tool - search-only, no AI answer generation"""

    def __init__(self, api_key: str):
        super().__init__(
            name="tavily_search",
            description=(
                "Search the web for information about a historical figure. "
                "Input the figure's name to retrieve relevant biographical information."
            )
        )
        if not api_key:
            raise ValueError("TAVILY_API_KEY is required for TavilySearchTool")

        from tavily import TavilyClient
        self._client = TavilyClient(api_key=api_key)
        logger.info("[TOOL] TavilySearchTool initialized")

    def run(self, parameters: Dict[str, Any]) -> str:
        """
        Execute web search

        Args:
            parameters: dict with key 'query' - the search query string

        Returns:
            Concatenated search result snippets as a single string
        """
        query = parameters.get("query", "").strip()
        if not query:
            return "Error: search query cannot be empty"

View on GitHub (pinned to 606a07d341)

Solutions

  1. Obtain a Tavily API key (app.tavily.com free tier) and set TAVILY_API_KEY in backend/.env
  2. Ensure .env loading happens before tool construction (load_dotenv() at entrypoint or pydantic-settings env_file)
  3. For docker/systemd, pass the variable explicitly (env_file / EnvironmentFile=
  4. In tests, inject a sentinel key or mock the tool so the constructor guard does not fire

Example fix

# before
tool = TavilySearchTool(api_key=os.environ.get("TAVILY_API_KEY"))
# crashes at import/startup when unset

# after
from dotenv import load_dotenv
load_dotenv()  # at process entry
_api_key = os.environ.get("TAVILY_API_KEY")
if not _api_key:
    raise RuntimeError(
        "缺少 TAVILY_API_KEY:请复制 .env.example 为 .env 并填入 key"
    )
tool = TavilySearchTool(api_key=_api_key)
Defensive patterns

Strategy: validation

Validate before calling

import os

def tavily_key_present() -> bool:
    return bool(os.environ.get('TAVILY_API_KEY'))

Type guard

def has_api_key(key: str | None) -> bool:
    return isinstance(key, str) and key.strip() != ''

Try / catch

try:
    tool = TavilySearchTool(api_key=os.environ['TAVILY_API_KEY'])
except (KeyError, ValueError) as e:
    logger.warning('tavily unavailable (%s); building agent without web search', e)
    tools = [t for t in tools if t is not tavily_tool]  # degrade gracefully

Prevention

When it happens

Trigger: Instantiating TavilySearchTool(os.environ.get('TAVILY_API_KEY')) when the env var is unset (get returns None); key set to '' in .env; .env not loaded because the process starts in the wrong cwd or python-dotenv was never invoked; key present in the shell but not passed to docker/systemd.

Common situations: Cloning the repo without creating .env from .env.example; docker compose service missing environment/env_file entries; systemd unit without EnvironmentFile; CI tests constructing the tool without injecting a dummy key.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/5cf529ec791a2dfe. Report an issue: GitHub.