swarms 7.7.1__py3-none-any.whl → 7.7.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. swarms/prompts/ag_prompt.py +51 -19
  2. swarms/prompts/agent_system_prompts.py +13 -4
  3. swarms/prompts/multi_agent_collab_prompt.py +18 -0
  4. swarms/prompts/prompt.py +6 -10
  5. swarms/schemas/__init__.py +0 -3
  6. swarms/structs/__init__.py +3 -8
  7. swarms/structs/agent.py +211 -163
  8. swarms/structs/aop.py +8 -1
  9. swarms/structs/auto_swarm_builder.py +271 -210
  10. swarms/structs/conversation.py +23 -56
  11. swarms/structs/hiearchical_swarm.py +93 -122
  12. swarms/structs/ma_utils.py +96 -0
  13. swarms/structs/mixture_of_agents.py +20 -103
  14. swarms/structs/{multi_agent_orchestrator.py → multi_agent_router.py} +32 -95
  15. swarms/structs/output_types.py +3 -16
  16. swarms/structs/stopping_conditions.py +30 -0
  17. swarms/structs/swarm_router.py +57 -5
  18. swarms/structs/swarming_architectures.py +576 -185
  19. swarms/telemetry/main.py +6 -2
  20. swarms/tools/mcp_client.py +209 -53
  21. swarms/tools/mcp_integration.py +1 -53
  22. swarms/utils/formatter.py +15 -1
  23. swarms/utils/generate_keys.py +64 -0
  24. swarms/utils/history_output_formatter.py +2 -0
  25. {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/METADATA +98 -263
  26. {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/RECORD +29 -38
  27. swarms/schemas/agent_input_schema.py +0 -149
  28. swarms/structs/agents_available.py +0 -87
  29. swarms/structs/async_workflow.py +0 -818
  30. swarms/structs/graph_swarm.py +0 -612
  31. swarms/structs/octotools.py +0 -844
  32. swarms/structs/pulsar_swarm.py +0 -469
  33. swarms/structs/queue_swarm.py +0 -193
  34. swarms/structs/swarm_builder.py +0 -395
  35. swarms/structs/swarm_load_balancer.py +0 -344
  36. swarms/structs/swarm_output_type.py +0 -23
  37. swarms/structs/talk_hier.py +0 -729
  38. {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/LICENSE +0 -0
  39. {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/WHEEL +0 -0
  40. {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/entry_points.txt +0 -0
@@ -1,59 +1,20 @@
1
1
  import asyncio
2
2
  import os
3
- import time
4
- from typing import Any, Dict, List, Optional
3
+ from typing import List, Optional
5
4
 
6
- from pydantic import BaseModel, Field
7
5
 
8
6
  from swarms.structs.agent import Agent
9
- from swarms.telemetry.main import log_agent_data
10
- from swarms.schemas.agent_step_schemas import ManySteps
11
- from swarms.prompts.ag_prompt import aggregator_system_prompt
7
+ from swarms.prompts.ag_prompt import aggregator_system_prompt_main
12
8
  from swarms.utils.loguru_logger import initialize_logger
13
9
  import concurrent.futures
14
10
  from swarms.structs.output_types import OutputType
15
11
  from swarms.structs.conversation import Conversation
12
+ from swarms.utils.history_output_formatter import (
13
+ history_output_formatter,
14
+ )
16
15
 
17
16
  logger = initialize_logger(log_folder="mixture_of_agents")
18
17
 
19
- time_stamp = time.strftime("%Y-%m-%d %H:%M:%S")
20
-
21
-
22
- class MixtureOfAgentsInput(BaseModel):
23
- name: str = "MixtureOfAgents"
24
- description: str = (
25
- "A class to run a mixture of agents and aggregate their responses."
26
- )
27
- agents: List[Dict[str, Any]]
28
- aggregator_agent: Any = Field(
29
- ...,
30
- description="An aggregator agent to be used in the mixture.",
31
- )
32
- aggregator_system_prompt: str = Field(
33
- default=aggregator_system_prompt.get_prompt(),
34
- description=aggregator_system_prompt.description,
35
- )
36
- layers: int = 3
37
- time_created: str = Field(
38
- time_stamp,
39
- description="The time the mixture of agents was created.",
40
- )
41
-
42
-
43
- class MixtureOfAgentsOutput(BaseModel):
44
- id: str = Field(
45
- ..., description="The ID of the mixture of agents."
46
- )
47
- task: str = Field(..., description="None")
48
- InputConfig: MixtureOfAgentsInput
49
- # output: List[ManySteps]
50
- normal_agent_outputs: List[ManySteps]
51
- aggregator_agent_summary: str
52
- time_completed: str = Field(
53
- time_stamp,
54
- description="The time the mixture of agents was completed.",
55
- )
56
-
57
18
 
58
19
  class MixtureOfAgents:
59
20
  """
@@ -66,7 +27,7 @@ class MixtureOfAgents:
66
27
  description: str = "A class to run a mixture of agents and aggregate their responses.",
67
28
  agents: List[Agent] = [],
68
29
  aggregator_agent: Agent = None,
69
- aggregator_system_prompt: str = "",
30
+ aggregator_system_prompt: str = aggregator_system_prompt_main,
70
31
  layers: int = 3,
71
32
  max_loops: int = 1,
72
33
  return_str_on: bool = False,
@@ -85,31 +46,13 @@ class MixtureOfAgents:
85
46
  """
86
47
  self.name = name
87
48
  self.description = description
88
- self.agents: List[Agent] = agents
89
- self.aggregator_agent: Agent = aggregator_agent
90
- self.aggregator_system_prompt: str = aggregator_system_prompt
91
- self.layers: int = layers
92
- self.max_loops: int = max_loops
93
- self.return_str_on: bool = return_str_on
94
- self.output_type: OutputType = output_type
95
-
96
- self.input_schema = MixtureOfAgentsInput(
97
- name=name,
98
- description=description,
99
- agents=[agent.to_dict() for agent in self.agents],
100
- aggregator_agent=aggregator_agent.to_dict(),
101
- aggregator_system_prompt=self.aggregator_system_prompt,
102
- layers=self.layers,
103
- time_created=time_stamp,
104
- )
105
-
106
- self.output_schema = MixtureOfAgentsOutput(
107
- id="MixtureOfAgents",
108
- InputConfig=self.input_schema.model_dump(),
109
- normal_agent_outputs=[],
110
- aggregator_agent_summary="",
111
- task="",
112
- )
49
+ self.agents = agents
50
+ self.aggregator_agent = aggregator_agent
51
+ self.aggregator_system_prompt = aggregator_system_prompt_main
52
+ self.layers = layers
53
+ self.max_loops = max_loops
54
+ self.return_str_on = return_str_on
55
+ self.output_type = output_type
113
56
 
114
57
  self.reliability_check()
115
58
 
@@ -182,9 +125,6 @@ class MixtureOfAgents:
182
125
  Returns:
183
126
  str: The response from the agent.
184
127
  """
185
- # Update the task in the output schema
186
- self.output_schema.task = task
187
-
188
128
  # If there are previous responses, update the agent's system prompt
189
129
  if prev_responses:
190
130
  system_prompt_with_responses = (
@@ -197,9 +137,7 @@ class MixtureOfAgents:
197
137
  # Run the agent asynchronously
198
138
  response = await asyncio.to_thread(agent.run, task)
199
139
 
200
- self.output_schema.normal_agent_outputs.append(
201
- agent.agent_output
202
- )
140
+ self.conversation.add(agent.agent_name, response)
203
141
 
204
142
  # Log the agent's response
205
143
  print(f"Agent {agent.agent_name} response: {response}")
@@ -235,7 +173,6 @@ class MixtureOfAgents:
235
173
  final_result = await self._run_agent_async(
236
174
  self.aggregator_agent, task, prev_responses=results
237
175
  )
238
- self.output_schema.aggregator_agent_summary = final_result
239
176
 
240
177
  print(f"Final Aggregated Response: {final_result}")
241
178
 
@@ -248,38 +185,18 @@ class MixtureOfAgents:
248
185
  """
249
186
  try:
250
187
  self.conversation.add("user", task)
251
- prev_context = None
252
188
 
253
189
  for _ in range(self.max_loops):
254
190
  # Add previous context to task if available
255
- current_task = (
256
- f"{task}\n\nPrevious context:\n{prev_context}"
257
- if prev_context
258
- else task
259
- )
191
+ prompt = f"History: {self.conversation.get_str()}\n\nTask: {task}"
260
192
 
261
193
  # Run async process
262
- asyncio.run(self._run_async(current_task))
194
+ asyncio.run(self._run_async(prompt))
263
195
 
264
- # Store current results as context for next loop
265
- prev_context = (
266
- self.output_schema.aggregator_agent_summary
267
- )
268
-
269
- self.output_schema.task = task
270
-
271
- log_agent_data(self.output_schema.model_dump())
272
-
273
- if self.return_str_on or self.output_type == "str":
274
- return self.conversation.get_str()
275
- elif self.output_type == "dict":
276
- return (
277
- self.conversation.return_messages_as_dictionary()
278
- )
279
- elif self.output_type == "list":
280
- return self.conversation.return_messages_as_list()
281
- else:
282
- return self.output_schema.model_dump_json(indent=4)
196
+ return history_output_formatter(
197
+ conversation=self.conversation,
198
+ type=self.output_type,
199
+ )
283
200
 
284
201
  except Exception as e:
285
202
  logger.error(f"Error running mixture of agents: {str(e)}")
@@ -9,8 +9,6 @@ Todo:
9
9
  """
10
10
 
11
11
  import os
12
- import uuid
13
- from datetime import datetime
14
12
  from typing import List, Optional
15
13
 
16
14
  from loguru import logger
@@ -20,6 +18,10 @@ from swarms.structs.agent import Agent
20
18
  from swarms.structs.conversation import Conversation
21
19
  from swarms.structs.output_types import OutputType
22
20
  from swarms.utils.any_to_str import any_to_str
21
+ from swarms.utils.history_output_formatter import (
22
+ history_output_formatter,
23
+ )
24
+ from swarms.utils.formatter import formatter
23
25
 
24
26
 
25
27
  class AgentResponse(BaseModel):
@@ -62,7 +64,7 @@ class MultiAgentRouter:
62
64
  temperature: float = 0.1,
63
65
  shared_memory_system: callable = None,
64
66
  output_type: OutputType = "dict",
65
- execute_task: bool = True,
67
+ if_print: bool = True,
66
68
  ):
67
69
  """
68
70
  Initializes the MultiAgentRouter with a list of agents and configuration options.
@@ -80,15 +82,15 @@ class MultiAgentRouter:
80
82
  self.description = description
81
83
  self.shared_memory_system = shared_memory_system
82
84
  self.output_type = output_type
83
- self.execute_task = execute_task
84
85
  self.model = model
85
86
  self.temperature = temperature
86
-
87
+ self.if_print = if_print
87
88
  # Initialize Agents
88
89
  self.agents = {agent.name: agent for agent in agents}
89
90
  self.conversation = Conversation()
90
91
 
91
92
  self.api_key = os.getenv("OPENAI_API_KEY")
93
+
92
94
  if not self.api_key:
93
95
  raise ValueError("OpenAI API key must be provided")
94
96
 
@@ -99,6 +101,7 @@ class MultiAgentRouter:
99
101
  system_prompt=self.boss_system_prompt,
100
102
  api_key=self.api_key,
101
103
  temperature=temperature,
104
+ base_model=AgentResponse,
102
105
  )
103
106
 
104
107
  def __repr__(self):
@@ -140,21 +143,6 @@ class MultiAgentRouter:
140
143
  Always select exactly one agent that best matches the task requirements.
141
144
  """
142
145
 
143
- def find_agent_in_list(self, agent_name: str) -> Optional[Agent]:
144
- """
145
- Find an agent by name in a list of agents.
146
-
147
- Args:
148
- agent_name (str): The name of the agent to find.
149
-
150
- Returns:
151
- Optional[Agent]: The agent object if found, otherwise None.
152
- """
153
- for agent in self.agent_list:
154
- if agent.name == agent_name:
155
- return agent
156
- return None
157
-
158
146
  def route_task(self, task: str) -> dict:
159
147
  """
160
148
  Routes a task to the appropriate agent and returns their response.
@@ -167,15 +155,21 @@ class MultiAgentRouter:
167
155
  """
168
156
  try:
169
157
  self.conversation.add(role="user", content=task)
170
- start_time = datetime.now()
171
158
 
172
159
  # Get boss decision using function calling
173
- boss_response = self.function_caller.get_completion(task)
174
-
160
+ boss_response = self.function_caller.run(task)
175
161
  boss_response_str = any_to_str(boss_response)
176
162
 
163
+ if self.if_print:
164
+ formatter.print_panel(
165
+ boss_response_str,
166
+ title="Multi-Agent Router Decision",
167
+ )
168
+ else:
169
+ pass
170
+
177
171
  self.conversation.add(
178
- role="assistant", content=boss_response_str
172
+ role="Agent Router", content=boss_response_str
179
173
  )
180
174
 
181
175
  # Validate that the selected agent exists
@@ -190,60 +184,16 @@ class MultiAgentRouter:
190
184
  # Use the modified task if provided, otherwise use original task
191
185
  final_task = boss_response.modified_task or task
192
186
 
193
- # Execute the task with the selected agent if enabled
194
- execution_start = datetime.now()
195
- agent_response = None
196
- execution_time = 0
187
+ # Use the agent's run method directly
188
+ agent_response = selected_agent.run(final_task)
197
189
 
198
- if self.execute_task:
199
- # Use the agent's run method directly
200
- agent_response = selected_agent.run(final_task)
201
- self.conversation.add(
202
- role=selected_agent.name, content=agent_response
203
- )
204
- execution_time = (
205
- datetime.now() - execution_start
206
- ).total_seconds()
207
- else:
208
- logger.info(
209
- "Task execution skipped (execute_task=False)"
210
- )
190
+ self.conversation.add(
191
+ role=selected_agent.name, content=agent_response
192
+ )
211
193
 
212
- total_time = (datetime.now() - start_time).total_seconds()
213
-
214
- result = {
215
- "id": str(uuid.uuid4()),
216
- "timestamp": datetime.now().isoformat(),
217
- "task": {
218
- "original": task,
219
- "modified": (
220
- final_task
221
- if boss_response.modified_task
222
- else None
223
- ),
224
- },
225
- "boss_decision": {
226
- "selected_agent": boss_response.selected_agent,
227
- "reasoning": boss_response.reasoning,
228
- },
229
- "execution": {
230
- "agent_name": selected_agent.name,
231
- "agent_id": selected_agent.id,
232
- "was_executed": self.execute_task,
233
- "response": (
234
- agent_response if self.execute_task else None
235
- ),
236
- "execution_time": (
237
- execution_time if self.execute_task else None
238
- ),
239
- },
240
- "total_time": total_time,
241
- }
242
-
243
- logger.info(
244
- f"Successfully routed task to {selected_agent.name}"
194
+ return history_output_formatter(
195
+ conversation=self.conversation, type=self.output_type
245
196
  )
246
- return result
247
197
 
248
198
  except Exception as e:
249
199
  logger.error(f"Error routing task: {str(e)}")
@@ -312,31 +262,18 @@ class MultiAgentRouter:
312
262
  # ),
313
263
  # ]
314
264
 
315
- # # Initialize routers with different configurations
316
- # router_execute = MultiAgentRouter(agents=agents, execute_task=True)
317
- # # router_no_execute = MultiAgentRouter(agents=agents, execute_task=False)
265
+ # # Initialize router
266
+ # router = MultiAgentRouter(agents=agents)
318
267
 
319
268
  # # Example task
320
269
  # task = "Write a Python function to calculate fibonacci numbers"
321
270
 
322
271
  # try:
323
- # # Process the task with execution
324
- # print("\nWith task execution:")
325
- # result_execute = router_execute.route_task(task)
326
- # print(
327
- # f"Selected Agent: {result_execute['boss_decision']['selected_agent']}"
328
- # )
329
- # print(
330
- # f"Reasoning: {result_execute['boss_decision']['reasoning']}"
331
- # )
332
- # if result_execute["execution"]["response"]:
333
- # print(
334
- # f"Response Preview: {result_execute['execution']['response'][:200]}..."
335
- # )
336
- # print(
337
- # f"Execution Time: {result_execute['execution']['execution_time']:.2f}s"
338
- # )
339
- # print(f"Total Time: {result_execute['total_time']:.2f}s")
272
+ # # Process the task
273
+ # result = router.route_task(task)
274
+ # print(f"Selected Agent: {result['boss_decision']['selected_agent']}")
275
+ # print(f"Reasoning: {result['boss_decision']['reasoning']}")
276
+ # print(f"Total Time: {result['total_time']:.2f}s")
340
277
 
341
278
  # except Exception as e:
342
279
  # print(f"Error occurred: {str(e)}")
@@ -1,19 +1,6 @@
1
- from typing import Literal
2
-
3
- # Literal of output types
4
- OutputType = Literal[
5
- "all",
6
- "final",
7
- "list",
8
- "dict",
9
- ".json",
10
- ".md",
11
- ".txt",
12
- ".yaml",
13
- ".toml",
14
- "string",
15
- "str",
16
- ]
1
+ from swarms.utils.history_output_formatter import (
2
+ HistoryOutputType as OutputType,
3
+ )
17
4
 
18
5
  # Use the OutputType for type annotations
19
6
  output_type: OutputType
@@ -36,3 +36,33 @@ def check_exit(s):
36
36
 
37
37
  def check_end(s):
38
38
  return "end" in s
39
+
40
+
41
+ def check_stopping_conditions(input: str) -> str:
42
+ """
43
+ Checks a string against all stopping conditions and returns an appropriate message.
44
+
45
+ Args:
46
+ s (str): The input string to check
47
+
48
+ Returns:
49
+ str: A message indicating which stopping condition was met, or None if no condition was met
50
+ """
51
+ conditions = [
52
+ (check_done, "Task is done"),
53
+ (check_finished, "Task is finished"),
54
+ (check_complete, "Task is complete"),
55
+ (check_success, "Task succeeded"),
56
+ (check_failure, "Task failed"),
57
+ (check_error, "Task encountered an error"),
58
+ (check_stopped, "Task was stopped"),
59
+ (check_cancelled, "Task was cancelled"),
60
+ (check_exit, "Task exited"),
61
+ (check_end, "Task ended"),
62
+ ]
63
+
64
+ for check_func, message in conditions:
65
+ if check_func(input):
66
+ return message
67
+
68
+ return None
@@ -5,7 +5,9 @@ from typing import Any, Callable, Dict, List, Literal, Optional, Union
5
5
 
6
6
  from pydantic import BaseModel, Field
7
7
 
8
- from swarms.prompts.ag_prompt import aggregator_system_prompt
8
+ from swarms.prompts.multi_agent_collab_prompt import (
9
+ MULTI_AGENT_COLLAB_PROMPT_TWO,
10
+ )
9
11
  from swarms.structs.agent import Agent
10
12
  from swarms.structs.concurrent_workflow import ConcurrentWorkflow
11
13
  from swarms.structs.csv_to_agent import AgentLoader
@@ -13,7 +15,7 @@ from swarms.structs.groupchat import GroupChat
13
15
  from swarms.structs.hiearchical_swarm import HierarchicalSwarm
14
16
  from swarms.structs.majority_voting import MajorityVoting
15
17
  from swarms.structs.mixture_of_agents import MixtureOfAgents
16
- from swarms.structs.multi_agent_orchestrator import MultiAgentRouter
18
+ from swarms.structs.multi_agent_router import MultiAgentRouter
17
19
  from swarms.structs.rearrange import AgentRearrange
18
20
  from swarms.structs.sequential_workflow import SequentialWorkflow
19
21
  from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm
@@ -66,6 +68,38 @@ class SwarmLog(BaseModel):
66
68
  documents: List[Document] = []
67
69
 
68
70
 
71
+ class SwarmRouterConfig(BaseModel):
72
+ """Configuration model for SwarmRouter."""
73
+
74
+ name: str = Field(
75
+ description="Name identifier for the SwarmRouter instance",
76
+ )
77
+ description: str = Field(
78
+ description="Description of the SwarmRouter's purpose",
79
+ )
80
+ # max_loops: int = Field(
81
+ # description="Maximum number of execution loops"
82
+ # )
83
+ swarm_type: SwarmType = Field(
84
+ description="Type of swarm to use",
85
+ )
86
+ rearrange_flow: Optional[str] = Field(
87
+ description="Flow configuration string"
88
+ )
89
+ rules: Optional[str] = Field(
90
+ description="Rules to inject into every agent"
91
+ )
92
+ multi_agent_collab_prompt: bool = Field(
93
+ description="Whether to enable multi-agent collaboration prompts",
94
+ )
95
+ task: str = Field(
96
+ description="The task to be executed by the swarm",
97
+ )
98
+
99
+ class Config:
100
+ arbitrary_types_allowed = True
101
+
102
+
69
103
  class SwarmRouter:
70
104
  """
71
105
  A class that dynamically routes tasks to different swarm types based on user selection or automatic matching.
@@ -157,6 +191,7 @@ class SwarmRouter:
157
191
  load_agents_from_csv: bool = False,
158
192
  csv_file_path: str = None,
159
193
  return_entire_history: bool = True,
194
+ multi_agent_collab_prompt: bool = True,
160
195
  *args,
161
196
  **kwargs,
162
197
  ):
@@ -179,14 +214,18 @@ class SwarmRouter:
179
214
  self.load_agents_from_csv = load_agents_from_csv
180
215
  self.csv_file_path = csv_file_path
181
216
  self.return_entire_history = return_entire_history
217
+ self.multi_agent_collab_prompt = multi_agent_collab_prompt
182
218
 
219
+ # Reliability check
220
+ self.reliability_check()
221
+
222
+ # Load agents from CSV
183
223
  if self.load_agents_from_csv:
184
224
  self.agents = AgentLoader(
185
225
  csv_path=self.csv_file_path
186
226
  ).load_agents()
187
227
 
188
- self.reliability_check()
189
-
228
+ # Log initialization
190
229
  self._log(
191
230
  "info",
192
231
  f"SwarmRouter initialized with swarm type: {swarm_type}",
@@ -345,7 +384,6 @@ class SwarmRouter:
345
384
  name=self.name,
346
385
  description=self.description,
347
386
  agents=self.agents,
348
- aggregator_system_prompt=aggregator_system_prompt.get_prompt(),
349
387
  aggregator_agent=self.agents[-1],
350
388
  layers=self.max_loops,
351
389
  output_type=self.output_type,
@@ -421,6 +459,17 @@ class SwarmRouter:
421
459
  f"Invalid swarm type: {self.swarm_type} try again with a valid swarm type such as 'SequentialWorkflow' or 'ConcurrentWorkflow' or 'auto' or 'AgentRearrange' or 'MixtureOfAgents' or 'SpreadSheetSwarm'"
422
460
  )
423
461
 
462
+ def update_system_prompt_for_agent_in_swarm(self):
463
+ # Use list comprehension for faster iteration
464
+ [
465
+ setattr(
466
+ agent,
467
+ "system_prompt",
468
+ agent.system_prompt + MULTI_AGENT_COLLAB_PROMPT_TWO,
469
+ )
470
+ for agent in self.agents
471
+ ]
472
+
424
473
  def _log(
425
474
  self,
426
475
  level: str,
@@ -464,6 +513,9 @@ class SwarmRouter:
464
513
  """
465
514
  self.swarm = self._create_swarm(task, *args, **kwargs)
466
515
 
516
+ if self.multi_agent_collab_prompt is True:
517
+ self.update_system_prompt_for_agent_in_swarm()
518
+
467
519
  try:
468
520
  logger.info(
469
521
  f"Running task on {self.swarm_type} swarm with task: {task}"