{"record":{"id":"38238cb810065655","repo":"deepset-ai/haystack","slug":"no-tools-were-configured-for-the-agent-at-initiali","errorCode":null,"errorMessage":"No tools were configured for the Agent at initialization.","messagePattern":"No tools were configured for the Agent at initialization\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/agents/utils.py","lineNumber":126,"sourceCode":"    return spawned if spawned is not item else None\n\n\ndef _select_tools_by_name(configured_tools: ToolsType, names: list[str]) -> list[Tool | Toolset]:\n    \"\"\"\n    Select configured tools by name for a single run.\n\n    Standalone Tools are kept when their name is requested. A Toolset with run-scoped state (one overriding\n    `spawn()`, such as SearchableToolset) is replaced by a per-run copy carrying the requested names, so its\n    dynamic behavior (search/lazy-loading) is preserved without mutating the shared, configured Toolset. Any\n    other Toolset is warmed up and reduced to the matching Tools.\n\n    :param configured_tools: The tools configured on the Agent.\n    :param names: The requested tool names.\n    :returns: The selected Tools and/or selection-scoped Toolset copies.\n    :raises ValueError: If no tools were configured, or if any requested name is not a valid tool name.\n    \"\"\"\n    if configured_tools is None:\n        raise ValueError(\"No tools were configured for the Agent at initialization.\")\n\n    requested_names = set(names)\n    items: list[Tool | Toolset] = (\n        [configured_tools] if isinstance(configured_tools, Toolset) else list(configured_tools)\n    )\n\n    # Resolve the tools each item offers for selection\n    selectable_per_item: list[tuple[Tool | Toolset, list[Tool]]] = []\n    for item in items:\n        selectable = item.get_selectable_tools() if isinstance(item, Toolset) else [item]\n        selectable_per_item.append((item, selectable))\n\n    valid_tool_names = {tool.name for _, selectable in selectable_per_item for tool in selectable}\n    # A dynamic Toolset may look empty before its catalog is resolved, so emptiness is checked here.\n    if not valid_tool_names:\n        raise ValueError(\"No tools were configured for the Agent at initialization.\")\n\n    invalid_tool_names = requested_names - valid_tool_names","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/agents/utils.py#L108-L144","documentation":"_select_tools_by_name raises this ValueError when the Agent was initialized with tools=None (or equivalent no-tools configuration) but per-run tool selection by name is attempted. Names can only be resolved against tools configured at initialization.","triggerScenarios":"Agent(tools=None) followed by run(messages, tools=[\"tool_name\"]); passing tool-name strings when no configured tools exist to match them against.","commonSituations":"Switching an Agent to name-based tool selection after initializing it without tools, or dynamically building Agents where the tools argument is conditionally omitted.","solutions":["Initialize the Agent with tools (Tool list or Toolset) so names can be resolved","Pass concrete Tool objects instead of name strings when the Agent has no configured tools","Check the Agent constructor's tools argument for conditional code that sets it to None"],"exampleFix":"// before\nagent = Agent(chat_generator=llm)  # tools defaults to None\nagent.run(msgs, tools=[\"search\"])\n// after\nagent = Agent(chat_generator=llm, tools=[search_tool])\nagent.run(msgs, tools=[\"search\"])","handlingStrategy":"validation","validationCode":"def names_resolvable(names, agent_tools):\n    if agent_tools is None and all(isinstance(n, str) for n in names):\n        raise ValueError(\"Agent has no configured tools; pass Tool objects instead of names\")","typeGuard":"def can_select_by_name(agent) -> bool:\n    return agent.tools is not None","tryCatchPattern":"try:\n    agent.run(messages, tools=[\"search\"])\nexcept ValueError as e:\n    if \"No tools were configured\" in str(e):\n        agent.run(messages, tools=[search_tool])\n    else:\n        raise","preventionTips":["Always configure tools at Agent initialization if you plan name-based selection","Pass Tool objects instead of name strings when tools may be absent","Assert agent.tools is not None before using name-based per-run selection"],"tags":["python","agent","tools","configuration"],"backgroundTag":"missing-configuration","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}