Skip to content

Commit 00e8318

Browse files
committed
[feat] Sub-Agent Status & Cancel Tools Added check_sub_agent_status and cancel_sub_agent_tasks as new autonomous planning tools with full schema definitions and registry-backed handler implementations, wired into Agent's
tool dispatch map [feat] Async Sub-Agent Registry Refactor Replaced raw asyncio dispatching in assign_task_tool with SubagentRegistry-based spawning for consistent task tracking, retries, and cancellation; added _find_registry and _resolve_sub_agents_by_name helpers [feat] Sub-Agent Print Visibility Enabled print_on=True for sub-agents created via create_sub_agent_tool to surface their output during execution [improvement] LiteLLM Empty System Prompt Fix Fixed Anthropic API rejections by stripping whitespace-only system prompt blocks and normalizing orchestrator-style System:/Human: prompts before message construction [improvement] PDF Utility Removal Removed pdf_to_text as a core utility from utils/__init__.py and data_to_text.py, inlining a local implementation directly in the mem0 example script [improvement] Agent Class Cleanup Removed duplicated async sub-agent methods from Agent class body now superseded by registry integration [improvement] top_p Default Fix Removed hardcoded top_p=None from auto_chat_agent and set Agent.top_p default to None to avoid unintended sampling parameter injection [improvement] Model & Version Update Bumped swarms to 9.0.3 and updated default model references from gpt-4.1/claude-sonnet-4-5 to gpt-5.4/gpt-5.1 across example files and CLI
1 parent edafdad commit 00e8318

File tree

13 files changed

+840
-297
lines changed

13 files changed

+840
-297
lines changed

example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
agent_name="Quantitative-Trading-Agent",
66
agent_description="Advanced quantitative trading and algorithmic analysis agent",
77
system_prompt="You are a helpful assistant that can answer questions and help with tasks and your name is Quantitative-Trading-Agent",
8-
model_name="gpt-4.1",
8+
model_name="gpt-5.4",
99
dynamic_temperature_enabled=True,
1010
max_loops=2,
1111
dynamic_context_window=True,

examples/guides/mem0/mem0_and_swarms.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
from mem0 import MemoryClient
55
from swarms import Agent
6-
from swarms.utils.pdf_to_text import pdf_to_text
76
from swarms.utils.data_to_text import csv_to_text
87
from dotenv import load_dotenv
98

@@ -45,6 +44,32 @@ def chunk_text(
4544
return chunks
4645

4746

47+
def pdf_to_text(pdf_path: str) -> str:
48+
"""
49+
Extract text from a PDF file for this example script.
50+
51+
Args:
52+
pdf_path (str): Path to the PDF file.
53+
54+
Returns:
55+
str: Extracted text from all PDF pages.
56+
"""
57+
try:
58+
import pypdf
59+
except ImportError as exc:
60+
raise ImportError(
61+
"pypdf is required for PDF support in this example. "
62+
"Install it with `pip install pypdf`."
63+
) from exc
64+
65+
with open(pdf_path, "rb") as file:
66+
reader = pypdf.PdfReader(file)
67+
pages = []
68+
for page in reader.pages:
69+
pages.append(page.extract_text() or "")
70+
return "\n".join(pages)
71+
72+
4873
def read_pdf(pdf_path: str) -> str:
4974
"""
5075
Read and extract text content from a PDF file.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
55

66
[tool.poetry]
77
name = "swarms"
8-
version = "9.0.2"
8+
version = "9.0.3"
99
description = "Swarms - TGSC"
1010
license = "MIT"
1111
authors = ["Kye Gomez <[email protected]>"]

sub_agent_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from swarms import Agent
2+
3+
# Initialize the agent
4+
agent = Agent(
5+
agent_name="Quantitative-Trading-Agent",
6+
agent_description="Advanced quantitative trading and algorithmic analysis agent",
7+
system_prompt="You are a helpful assistant that can answer questions and help with tasks and your name is Quantitative-Trading-Agent",
8+
model_name="gpt-5.4",
9+
max_loops="auto",
10+
dynamic_context_window=True,
11+
reasoning_effort=None,
12+
)
13+
14+
out = agent.run(
15+
"Create 2 simple sub agents that just say hello and nothing else"
16+
)
17+
18+
print(out)

swarms/agents/auto_chat_agent.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def auto_chat_agent(
2929
dynamic_temperature_enabled=True,
3030
max_loops="auto",
3131
temperature=temperature,
32-
top_p=None,
3332
)
3433

3534
current_task = task

swarms/cli/main.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ def __call__(
837837
print()
838838
print("Examples:")
839839
print(f" {prog_name} chat")
840-
print(f" {prog_name} chat --model-name claude-sonnet-4-5")
840+
print(f" {prog_name} chat --model-name gpt-5.4")
841841
print(f" {prog_name} chat --model-name claude-opus-4-6")
842842
print(f" {prog_name} chat --model-name gpt-4o")
843843
print(
@@ -950,7 +950,7 @@ def setup_argument_parser() -> argparse.ArgumentParser:
950950
"--model-name",
951951
type=str,
952952
default=None,
953-
help="Model name to use (e.g. claude-sonnet-4-5, gpt-4o, claude-opus-4-6). Defaults to claude-sonnet-4-5 for chat, gpt-4 for agent.",
953+
help="Model name to use (e.g. gpt-5.4, gpt-4o, claude-opus-4-6). Defaults to gpt-5.4 for chat, gpt-4 for agent.",
954954
)
955955
parser.add_argument(
956956
"--task",
@@ -1526,16 +1526,14 @@ def handle_chat(args: argparse.Namespace) -> Optional[Agent]:
15261526
or "A Swarms agent that can chat with the user."
15271527
)
15281528
system_prompt = getattr(args, "system_prompt", None)
1529-
model_name = (
1530-
getattr(args, "model_name", None) or "claude-sonnet-4-5"
1531-
)
1529+
model_name = getattr(args, "model_name", None) or "gpt-5.1"
15321530
task = getattr(args, "task", None)
15331531

15341532
console.print(
15351533
f"\n[bold white]{name}[/bold white] [dim white]({model_name})[/dim white]"
15361534
)
15371535
console.print(
1538-
"[dim white] Switch model: [/dim white][white]swarms chat --model-name claude-sonnet-4-5[/white]"
1536+
"[dim white] Switch model: [/dim white][white]swarms chat --model-name gpt-5.4[/white]"
15391537
"[dim white] · other options: claude-opus-4-6, gpt-4o, gemini/gemini-2.0-flash[/dim white]\n"
15401538
)
15411539

swarms/structs/agent.py

Lines changed: 10 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
MAX_SUBTASK_ITERATIONS,
6868
MAX_SUBTASK_LOOPS,
6969
assign_task_tool,
70+
check_sub_agent_status_tool,
71+
cancel_sub_agent_tasks_tool,
7072
create_file_tool,
7173
create_sub_agent_tool,
7274
delete_file_tool,
@@ -82,6 +84,7 @@
8284
update_file_tool,
8385
)
8486
from swarms.structs.conversation import Conversation
87+
from swarms.structs.dynamic_skills_loader import DynamicSkillsLoader
8588
from swarms.structs.ma_utils import set_random_models_for_agents
8689
from swarms.structs.safe_loading import (
8790
SafeLoaderUtils,
@@ -126,7 +129,6 @@
126129
add_prompt_to_marketplace,
127130
)
128131
from swarms.utils.workspace_utils import get_workspace_dir
129-
from swarms.structs.dynamic_skills_loader import DynamicSkillsLoader
130132

131133

132134
def stop_when_repeats(response: str) -> bool:
@@ -426,7 +428,7 @@ def __init__(
426428
random_models_on: bool = False,
427429
mcp_config: Optional[MCPConnection] = None,
428430
mcp_configs: Optional[MultipleMCPConnections] = None,
429-
top_p: Optional[float] = 0.90,
431+
top_p: Optional[float] = None,
430432
llm_base_url: Optional[str] = None,
431433
llm_api_key: Optional[str] = None,
432434
tool_call_summary: bool = True,
@@ -2324,6 +2326,12 @@ def _run_autonomous_loop(
23242326
"assign_task": lambda **kwargs: assign_task_tool(
23252327
self, **kwargs
23262328
),
2329+
"check_sub_agent_status": lambda **kwargs: check_sub_agent_status_tool(
2330+
self, **kwargs
2331+
),
2332+
"cancel_sub_agent_tasks": lambda **kwargs: cancel_sub_agent_tasks_tool(
2333+
self, **kwargs
2334+
),
23272335
}
23282336

23292337
# Filter tool handlers if selected_tools is not "all"
@@ -3119,83 +3127,6 @@ async def arun(
31193127
error
31203128
) # Ensure this is also async if needed
31213129

3122-
# ── Async Subagent Methods ──────────────────────────────
3123-
3124-
def _get_registry(self):
3125-
"""Lazy-init and return the SubagentRegistry."""
3126-
if self._subagent_registry is None:
3127-
from swarms.structs.async_subagent import (
3128-
SubagentRegistry,
3129-
)
3130-
3131-
self._subagent_registry = SubagentRegistry(
3132-
max_depth=self.max_subagent_depth
3133-
)
3134-
return self._subagent_registry
3135-
3136-
def run_async(self, task: str):
3137-
"""
3138-
Run this agent's task in the background, returning a Future.
3139-
"""
3140-
registry = self._get_registry()
3141-
return registry._executor.submit(self.run, task)
3142-
3143-
def spawn_async(
3144-
self,
3145-
agent,
3146-
task: str,
3147-
max_retries: int = 0,
3148-
retry_on=None,
3149-
fail_fast: bool = True,
3150-
) -> str:
3151-
"""
3152-
Spawn a subagent to run a task in the background.
3153-
3154-
Returns task_id for tracking via get_subagent_results() / gather_results().
3155-
"""
3156-
registry = self._get_registry()
3157-
return registry.spawn(
3158-
agent=agent,
3159-
task=task,
3160-
parent_id=self.id,
3161-
depth=0,
3162-
max_retries=max_retries,
3163-
retry_on=retry_on,
3164-
fail_fast=fail_fast,
3165-
)
3166-
3167-
def run_in_background(self, task: str) -> str:
3168-
"""
3169-
Convenience: spawn self as a background task, return task_id.
3170-
"""
3171-
registry = self._get_registry()
3172-
return registry.spawn(
3173-
agent=self,
3174-
task=task,
3175-
parent_id=None,
3176-
depth=0,
3177-
)
3178-
3179-
def gather_results(
3180-
self,
3181-
strategy: str = "wait_all",
3182-
timeout: float = None,
3183-
):
3184-
"""Wait for spawned subagents and return their results."""
3185-
return self._get_registry().gather(
3186-
strategy=strategy, timeout=timeout
3187-
)
3188-
3189-
def get_subagent_results(self):
3190-
"""Collect results from all completed subagent tasks."""
3191-
return self._get_registry().get_results()
3192-
3193-
def cancel_subagent(self, task_id: str) -> bool:
3194-
"""Cancel a spawned subagent task."""
3195-
return self._get_registry().cancel(task_id)
3196-
3197-
# ── End Async Subagent Methods ──────────────────────────
3198-
31993130
def __call__(
32003131
self,
32013132
task: Optional[str] = None,

0 commit comments

Comments
 (0)