deepset-ai/haystack · error · ValueError
No tools were configured for the Agent at initialization.
Error message
No tools were configured for the Agent at initialization.
What it means
_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.
Source
Thrown at haystack/components/agents/utils.py:126
return spawned if spawned is not item else None
def _select_tools_by_name(configured_tools: ToolsType, names: list[str]) -> list[Tool | Toolset]:
"""
Select configured tools by name for a single run.
Standalone Tools are kept when their name is requested. A Toolset with run-scoped state (one overriding
`spawn()`, such as SearchableToolset) is replaced by a per-run copy carrying the requested names, so its
dynamic behavior (search/lazy-loading) is preserved without mutating the shared, configured Toolset. Any
other Toolset is warmed up and reduced to the matching Tools.
:param configured_tools: The tools configured on the Agent.
:param names: The requested tool names.
:returns: The selected Tools and/or selection-scoped Toolset copies.
:raises ValueError: If no tools were configured, or if any requested name is not a valid tool name.
"""
if configured_tools is None:
raise ValueError("No tools were configured for the Agent at initialization.")
requested_names = set(names)
items: list[Tool | Toolset] = (
[configured_tools] if isinstance(configured_tools, Toolset) else list(configured_tools)
)
# Resolve the tools each item offers for selection
selectable_per_item: list[tuple[Tool | Toolset, list[Tool]]] = []
for item in items:
selectable = item.get_selectable_tools() if isinstance(item, Toolset) else [item]
selectable_per_item.append((item, selectable))
valid_tool_names = {tool.name for _, selectable in selectable_per_item for tool in selectable}
# A dynamic Toolset may look empty before its catalog is resolved, so emptiness is checked here.
if not valid_tool_names:
raise ValueError("No tools were configured for the Agent at initialization.")
invalid_tool_names = requested_names - valid_tool_namesView on GitHub (pinned to e318778c9b)
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
Example fix
// before agent = Agent(chat_generator=llm) # tools defaults to None agent.run(msgs, tools=["search"]) // after agent = Agent(chat_generator=llm, tools=[search_tool]) agent.run(msgs, tools=["search"])
Defensive patterns
Strategy: validation
Validate before calling
def names_resolvable(names, agent_tools):
if agent_tools is None and all(isinstance(n, str) for n in names):
raise ValueError("Agent has no configured tools; pass Tool objects instead of names") Type guard
def can_select_by_name(agent) -> bool:
return agent.tools is not None Try / catch
try:
agent.run(messages, tools=["search"])
except ValueError as e:
if "No tools were configured" in str(e):
agent.run(messages, tools=[search_tool])
else:
raise Prevention
- 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
When it happens
Trigger: Agent(tools=None) followed by run(messages, tools=["tool_name"]); passing tool-name strings when no configured tools exist to match them against.
Common situations: Switching an Agent to name-based tool selection after initializing it without tools, or dynamically building Agents where the tools argument is conditionally omitted.
Related errors
- tools must be a list of Tool and/or Toolset objects, a Tools
- Tool execution requires at least one tool.
- Tool '{tool.name}': failed to merge outputs into state. {e}
- `max_total_tokens` must be a positive number of tokens, got
- StateSchema: Key '{param}' is missing a 'type' entry.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/38238cb810065655.
Report an issue: GitHub.