#2298·swarms

[BUG][AutonomousAgentLoop][tool_search returns irrelevant tools and the subtask stalls instead of continuing]

Author: kyegomezCreated Sep 17, 2026Updated Sep 17, 2026

Summary

With max_loops="auto", the autonomous loop stalls on its first subtask. dynamic_tools defaults to True (swarms/structs/agent.py:399), so this needs no opt-in. The agent calls tool_search, gets back tools that have nothing to do with what it asked for, and then tells the user it is blocked "because tool loading only takes effect on the next turn" — instead of continuing the subtask with the next request, which is exactly when the loaded schemas do become available.

Reproduction

python
from dotenv import load_dotenv
from swarms import Agent

load_dotenv()

agent = Agent(
    agent_name="Quantitative-Trading-Agent",
    agent_description="Advanced quantitative trading and algorithmic analysis agent",
    system_prompt="You are Quantitative-Trading-Agent ...",
    model_name="gpt-5.4",
    max_loops="auto",
    persistent_memory=False,
)

agent.run(
    task=(
        "Analyze the best semiconductor ETFs and provide a detailed comparison. "
        "Include metrics such as performance, expense ratio, holdings, and any "
        "notable strategies."
    )
)

Observed

Planning succeeds — a 7-step plan is produced. Execution then reaches the first subtask and:

Agent: Quantitative-Trading-Agent  Function Call: tool_search
  query: web search browser fetch webpage financial market data ETF fund
         profile holdings performance quote screener table extraction
  max_results: 10

Message to User [WARNING]
  I'm blocked from completing the subtask in this same turn because tool
  loading only takes effect on the next turn, and no web/data retrieval
  tools were available immediately. I have loaded the availab...

The subtask does not proceed.

What is actually happening

Two separate problems compound.

1. tool_search answers an unsatisfiable query with irrelevant tools.

There are no web/market-data tools in the catalog at all, but the search does not say so — it returns its two best lexical matches. Reproduced offline, no model involved, by doing what AutonomousAgentLoop._run_autonomous_loop does at swarms/agents/autonomous_loop.py:314-320:

python
from unittest.mock import patch
from swarms.structs.agent import Agent
from swarms.agents.autonomous_loop import ALWAYS_LOADED_TOOLS
from swarms.structs.autonomous_loop_utils import get_autonomous_planning_tools

with patch("swarms.structs.agent.LiteLLM"):
    a = Agent(agent_name="Q", max_loops="auto", dynamic_tools=True)

pt = get_autonomous_planning_tools()
control = [t for t in pt if t["function"]["name"] in ALWAYS_LOADED_TOOLS]
a.setup_dynamic_tools(always_loaded=control)
a.defer_tool_schemas([t for t in pt if t not in control])

print(a.tool_loader.run_search(
    query="web search browser fetch webpage financial market data ETF holdings quote",
    max_results=10,
))
glob: Find files by name pattern, newest first. ...
grep: Search for a pattern in files. ...

Loaded 2: glob, grep. They are callable from your next turn.

The full deferred catalog for an auto agent with no user tools is:

assign_task, cancel_sub_agent_tasks, check_sub_agent_status, create_file,
create_sub_agent, delete_file, glob, grep, list_directory, read_file,
run_bash, update_file

Nothing there can fetch an ETF quote. A query that matches nothing relevant should report a miss, not hand back glob and grep as though they answer it.

2. The "next turn" wording reads as "you are blocked".

DYNAMIC_TOOLS_NOTICE (swarms/tools/dynamic_tool_loader.py:92) says:

  1. The loaded tools become callable on your NEXT turn.

and every successful search result ends with They are callable from your next turn. The model in the transcript quoted this back almost verbatim as its reason for stopping and warning the user.

Mechanically the tools are ready immediately: Agent._tool_search_tool rebuilds the LLM in place after loading (swarms/structs/agent.py:2150-2152, "Loading changes the tool list, so the LLM is rebuilt here"), so the very next request in the same subtask carries the new schemas. The instruction is technically true and pragmatically misread — "next turn" is the next request, not a reason to hand control back to the user.

The notice already tries to guard against this ("Never say a task cannot be done ..."), but respond_to_user is in ALWAYS_LOADED_TOOLS (swarms/agents/autonomous_loop.py:82-91), so surrendering the turn is always one call away.

Expected

  • A tool_search that matches nothing useful says so plainly, rather than loading the highest-scoring unrelated tools.
  • After a tool_search inside a subtask, the loop continues that subtask on the next request instead of the agent treating the load as a blocking event.
  • Ideally the loop notices a subtask that requires a capability the catalog does not contain, and fails or replans rather than burning iterations.

Possible directions

  1. Apply a minimum relevance floor in run_search so a query with no real match returns a miss plus the catalog listing (the miss path already exists — it is just not reached when weak matches score above zero).
  2. Reword DYNAMIC_TOOLS_NOTICE step 2 and the search result footer: "these are callable from your next tool call — continue the subtask now", rather than "your NEXT turn".
  3. Have the execution loop treat a turn whose only tool call was tool_search as a non-iteration, so loading never costs the subtask its budget.

Environment

  • swarms master @ a4366d8d1
  • Python 3.12, macOS
  • model_name="gpt-5.4", max_loops="auto", no user-supplied tools, dynamic_tools left at its default of True