deepset-ai/haystack · warning · FutureWarning
Adding a Toolset to another Toolset is deprecated and will b
Error message
Adding a Toolset to another Toolset is deprecated and will be removed in Haystack 3.2.0. Pass Toolsets as a list wherever tools are accepted instead, e.g. Agent(tools=[toolset_a, toolset_b]).
What it means
Toolset.add(tool) in haystack/tools/toolset.py emits this FutureWarning when the object being added is itself a Toolset. Nesting one Toolset inside another via add() is deprecated in favor of passing toolsets as a flat list to any API that accepts tools (removed in Haystack 3.2.0).
Source
Thrown at haystack/tools/toolset.py:213
Note: adding a Toolset flattens it into its individual tools, so this is only recommended
for Toolsets that don't manage shared resources in their `warm_up()` (or `__init__`).
For example, combining with an `MCPToolset`, which owns a shared connection, is not
recommended: the connection's lifecycle would no longer be managed by the original
Toolset.
Adding a Toolset is deprecated and will be removed in Haystack 3.2.0: pass Toolsets as a
list wherever tools are accepted instead, e.g. `Agent(tools=[toolset_a, toolset_b])`.
:param tool: A Tool instance or another Toolset to add
:raises ValueError: If adding the tool would result in duplicate tool names
:raises TypeError: If the provided object is not a Tool or Toolset
"""
if not isinstance(tool, (Tool, Toolset)):
raise TypeError(f"Expected Tool or Toolset, got {type(tool).__name__}")
if isinstance(tool, Toolset):
warnings.warn(
"Adding a Toolset to another Toolset is deprecated and will be removed in Haystack 3.2.0. "
"Pass Toolsets as a list wherever tools are accepted instead, "
"e.g. Agent(tools=[toolset_a, toolset_b]).",
FutureWarning,
stacklevel=2,
)
new_tools = [tool] if isinstance(tool, Tool) else list(tool)
# Check for duplicates before adding
_check_duplicate_tool_names(self.tools + new_tools)
self.tools.extend(new_tools)
def to_dict(self) -> dict[str, Any]:
"""
Serialize the Toolset to a dictionary.
:returns: A dictionary representation of the ToolsetView on GitHub (pinned to e318778c9b)
Solutions
- Stop calling .add() with a Toolset; pass toolsets directly as a list where tools are accepted, e.g. Agent(tools=[toolset_a, toolset_b])
- If a single flat collection is required, iterate and add individual Tools: for t in toolset_b: toolset_a.add(t)
- Combine with list concatenation of Toolsets: Toolset(toolsets=[toolset_a, toolset_b]) or use a plain list [toolset_a, toolset_b]
- Suppress with warnings.filterwarnings('ignore', category=FutureWarning, module='haystack') only as a temporary measure before Haystack 3.2.0
Example fix
# before
catalog = Toolset(tools=[])
catalog.add(toolset_a)
catalog.add(toolset_b)
agent = Agent(chat_generator=gen, tools=[catalog])
# after
agent = Agent(chat_generator=gen, tools=[toolset_a, toolset_b])
# or, if a flat Toolset is required:
for t in toolset_a:
catalog.add(t)
for t in toolset_b:
catalog.add(t) Defensive patterns
Strategy: type-guard
Validate before calling
from haystack.tools import Tool, Toolset
def safe_add(target: Toolset, item) -> None:
if isinstance(item, Toolset):
raise ValueError("Pass toolsets as a list to consumers, not via .add()")
if not isinstance(item, Tool):
raise TypeError(f"Expected Tool, got {type(item).__name__}")
target.add(item) Type guard
from haystack.tools import Tool, Toolset
def is_tool(item) -> bool:
return isinstance(item, Tool) and not isinstance(item, Toolset)
def is_toolset(item) -> bool:
return isinstance(item, Toolset) Try / catch
import warnings
from haystack.tools import Toolset
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always", FutureWarning)
target.add(maybe_toolset)
if any(issubclass(w.category, FutureWarning) for w in caught):
# a Toolset was passed; refactor to pass it as a list instead
pass Prevention
- Type helper functions as Tool | Toolset and branch on isinstance before calling .add()
- Never call toolset.add(other_toolset); keep toolsets separate in lists
- Search codebases for '.add(' on Toolset variables during Haystack upgrades
- Migrate to Agent(tools=[toolset_a, toolset_b]) style before Haystack 3.2.0
When it happens
Trigger: Calling toolset_a.add(toolset_b) where toolset_b is an instance of Toolset (or subclass); the TypeError check passes because Toolset is an allowed type, then the warning fires.
Common situations: Building a combined tool catalog by incrementally adding toolsets into a master Toolset; refactors where a variable that used to be a Tool became a Toolset; utility functions typed to accept Tool that now receive Toolset instances.
Related errors
- Combining Toolsets and Tools with '+' is deprecated and will
- Warning: In an upcoming release, this method will require ke
- '{cls.__name__}' is an experimental component and may change
- tools must be a list of Tool and/or Toolset objects, a Tools
- StateSchema: Key '{param}' is missing a 'type' entry.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/4dab95fb68d699af.
Report an issue: GitHub.