swarms 7.8.4__py3-none-any.whl → 7.8.7__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 (58) hide show
  1. swarms/agents/ape_agent.py +5 -22
  2. swarms/agents/consistency_agent.py +1 -1
  3. swarms/agents/i_agent.py +1 -1
  4. swarms/agents/reasoning_agents.py +99 -3
  5. swarms/agents/reasoning_duo.py +1 -1
  6. swarms/cli/main.py +1 -1
  7. swarms/communication/__init__.py +1 -0
  8. swarms/communication/duckdb_wrap.py +32 -2
  9. swarms/communication/pulsar_struct.py +45 -19
  10. swarms/communication/redis_wrap.py +56 -11
  11. swarms/communication/supabase_wrap.py +1659 -0
  12. swarms/prompts/prompt.py +0 -3
  13. swarms/schemas/agent_completion_response.py +71 -0
  14. swarms/schemas/agent_rag_schema.py +7 -0
  15. swarms/schemas/conversation_schema.py +9 -0
  16. swarms/schemas/llm_agent_schema.py +99 -81
  17. swarms/schemas/swarms_api_schemas.py +164 -0
  18. swarms/structs/__init__.py +14 -11
  19. swarms/structs/agent.py +219 -199
  20. swarms/structs/agent_rag_handler.py +685 -0
  21. swarms/structs/base_swarm.py +2 -1
  22. swarms/structs/conversation.py +608 -87
  23. swarms/structs/csv_to_agent.py +153 -100
  24. swarms/structs/deep_research_swarm.py +197 -193
  25. swarms/structs/dynamic_conversational_swarm.py +18 -7
  26. swarms/structs/hiearchical_swarm.py +1 -1
  27. swarms/structs/hybrid_hiearchical_peer_swarm.py +2 -18
  28. swarms/structs/image_batch_processor.py +261 -0
  29. swarms/structs/interactive_groupchat.py +356 -0
  30. swarms/structs/ma_blocks.py +75 -0
  31. swarms/structs/majority_voting.py +1 -1
  32. swarms/structs/mixture_of_agents.py +1 -1
  33. swarms/structs/multi_agent_router.py +3 -2
  34. swarms/structs/rearrange.py +3 -3
  35. swarms/structs/sequential_workflow.py +3 -3
  36. swarms/structs/swarm_matcher.py +500 -411
  37. swarms/structs/swarm_router.py +15 -97
  38. swarms/structs/swarming_architectures.py +1 -1
  39. swarms/tools/mcp_client_call.py +3 -0
  40. swarms/utils/__init__.py +10 -2
  41. swarms/utils/check_all_model_max_tokens.py +43 -0
  42. swarms/utils/generate_keys.py +0 -27
  43. swarms/utils/history_output_formatter.py +5 -20
  44. swarms/utils/litellm_wrapper.py +208 -60
  45. swarms/utils/output_types.py +24 -0
  46. swarms/utils/vllm_wrapper.py +5 -6
  47. swarms/utils/xml_utils.py +37 -2
  48. {swarms-7.8.4.dist-info → swarms-7.8.7.dist-info}/METADATA +31 -55
  49. {swarms-7.8.4.dist-info → swarms-7.8.7.dist-info}/RECORD +53 -48
  50. swarms/structs/multi_agent_collab.py +0 -242
  51. swarms/structs/output_types.py +0 -6
  52. swarms/utils/markdown_message.py +0 -21
  53. swarms/utils/visualizer.py +0 -510
  54. swarms/utils/wrapper_clusterop.py +0 -127
  55. /swarms/{tools → schemas}/tool_schema_base_model.py +0 -0
  56. {swarms-7.8.4.dist-info → swarms-7.8.7.dist-info}/LICENSE +0 -0
  57. {swarms-7.8.4.dist-info → swarms-7.8.7.dist-info}/WHEEL +0 -0
  58. {swarms-7.8.4.dist-info → swarms-7.8.7.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,261 @@
1
+ import os
2
+ import time
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4
+ from pathlib import Path
5
+ from typing import Any, Callable, Dict, List, Optional, Union
6
+
7
+ from loguru import logger
8
+
9
+ from swarms.structs import Agent
10
+
11
+
12
+ class ImageProcessingError(Exception):
13
+ """Custom exception for image processing errors."""
14
+
15
+ pass
16
+
17
+
18
+ class InvalidAgentError(Exception):
19
+ """Custom exception for invalid agent configurations."""
20
+
21
+ pass
22
+
23
+
24
+ class ImageAgentBatchProcessor:
25
+ """
26
+ A class for processing multiple images in parallel using one or more agents.
27
+
28
+ This processor can:
29
+ - Handle multiple images from a directory
30
+ - Process images with single or multiple agents
31
+ - Execute tasks in parallel
32
+ - Provide detailed logging and error handling
33
+
34
+ Attributes:
35
+ agents (List[Agent]): List of agents to process images
36
+ max_workers (int): Maximum number of parallel workers
37
+ supported_formats (set): Set of supported image formats
38
+ """
39
+
40
+ def __init__(
41
+ self,
42
+ agents: Union[Agent, List[Agent], Callable, List[Callable]],
43
+ max_workers: int = None,
44
+ supported_formats: Optional[List[str]] = None,
45
+ ):
46
+ """
47
+ Initialize the ImageBatchProcessor.
48
+
49
+ Args:
50
+ agents: Single agent or list of agents to process images
51
+ max_workers: Maximum number of parallel workers (default: 4)
52
+ supported_formats: List of supported image formats (default: ['.jpg', '.jpeg', '.png'])
53
+
54
+ Raises:
55
+ InvalidAgentError: If agents parameter is invalid
56
+ """
57
+ self.agents = agents
58
+ self.max_workers = max_workers
59
+ self.supported_formats = supported_formats
60
+
61
+ self.agents = (
62
+ [agents] if isinstance(agents, Agent) else agents
63
+ )
64
+ if not self.agents:
65
+ raise InvalidAgentError(
66
+ "At least one agent must be provided"
67
+ )
68
+
69
+ # Get 95% of the total number of cores
70
+ self.max_workers = int(os.cpu_count() * 0.95)
71
+
72
+ self.supported_formats = set(
73
+ supported_formats or [".jpg", ".jpeg", ".png"]
74
+ )
75
+
76
+ # Setup logging
77
+ logger.add(
78
+ "image_processor.log",
79
+ rotation="100 MB",
80
+ retention="10 days",
81
+ level="INFO",
82
+ )
83
+
84
+ def _validate_image_path(
85
+ self, image_path: Union[str, Path]
86
+ ) -> Path:
87
+ """
88
+ Validate if the image path exists and has supported format.
89
+
90
+ Args:
91
+ image_path: Path to the image file
92
+
93
+ Returns:
94
+ Path: Validated Path object
95
+
96
+ Raises:
97
+ ImageProcessingError: If path is invalid or format not supported
98
+ """
99
+ path = Path(image_path)
100
+ if not path.exists():
101
+ raise ImageProcessingError(
102
+ f"Image path does not exist: {path}"
103
+ )
104
+ if path.suffix.lower() not in self.supported_formats:
105
+ raise ImageProcessingError(
106
+ f"Unsupported image format {path.suffix}. Supported formats: {self.supported_formats}"
107
+ )
108
+ return path
109
+
110
+ def _process_single_image(
111
+ self,
112
+ image_path: Path,
113
+ tasks: Union[str, List[str]],
114
+ agent: Agent,
115
+ ) -> Dict[str, Any]:
116
+ """
117
+ Process a single image with one agent and one or more tasks.
118
+
119
+ Args:
120
+ image_path: Path to the image
121
+ tasks: Single task or list of tasks to perform
122
+ agent: Agent to process the image
123
+
124
+ Returns:
125
+ Dict containing results for each task
126
+ """
127
+ try:
128
+ tasks_list = [tasks] if isinstance(tasks, str) else tasks
129
+ results = {}
130
+
131
+ logger.info(
132
+ f"Processing image {image_path} with agent {agent.__class__.__name__}"
133
+ )
134
+ start_time = time.time()
135
+
136
+ for task in tasks_list:
137
+ try:
138
+ result = agent.run(task=task, img=str(image_path))
139
+ results[task] = result
140
+ except Exception as e:
141
+ logger.error(
142
+ f"Error processing task '{task}' for image {image_path}: {str(e)}"
143
+ )
144
+ results[task] = f"Error: {str(e)}"
145
+
146
+ processing_time = time.time() - start_time
147
+ logger.info(
148
+ f"Completed processing {image_path} in {processing_time:.2f} seconds"
149
+ )
150
+
151
+ return {
152
+ "image_path": str(image_path),
153
+ "results": results,
154
+ "processing_time": processing_time,
155
+ }
156
+
157
+ except Exception as e:
158
+ logger.error(
159
+ f"Failed to process image {image_path}: {str(e)}"
160
+ )
161
+ raise ImageProcessingError(
162
+ f"Failed to process image {image_path}: {str(e)}"
163
+ )
164
+
165
+ def run(
166
+ self,
167
+ image_paths: Union[str, List[str], Path],
168
+ tasks: Union[str, List[str]],
169
+ ) -> List[Dict[str, Any]]:
170
+ """
171
+ Process multiple images in parallel with the configured agents.
172
+
173
+ Args:
174
+ image_paths: Single image path or list of image paths or directory path
175
+ tasks: Single task or list of tasks to perform on each image
176
+
177
+ Returns:
178
+ List of dictionaries containing results for each image
179
+
180
+ Raises:
181
+ ImageProcessingError: If any image processing fails
182
+ """
183
+ # Handle directory input
184
+ if (
185
+ isinstance(image_paths, (str, Path))
186
+ and Path(image_paths).is_dir()
187
+ ):
188
+ image_paths = [
189
+ os.path.join(image_paths, f)
190
+ for f in os.listdir(image_paths)
191
+ if Path(os.path.join(image_paths, f)).suffix.lower()
192
+ in self.supported_formats
193
+ ]
194
+ elif isinstance(image_paths, (str, Path)):
195
+ image_paths = [image_paths]
196
+
197
+ # Validate all paths
198
+ validated_paths = [
199
+ self._validate_image_path(path) for path in image_paths
200
+ ]
201
+
202
+ if not validated_paths:
203
+ logger.warning("No valid images found to process")
204
+ return []
205
+
206
+ logger.info(
207
+ f"Starting batch processing of {len(validated_paths)} images"
208
+ )
209
+ results = []
210
+
211
+ with ThreadPoolExecutor(
212
+ max_workers=self.max_workers
213
+ ) as executor:
214
+ future_to_path = {}
215
+
216
+ # Submit all tasks
217
+ for path in validated_paths:
218
+ for agent in self.agents:
219
+ future = executor.submit(
220
+ self._process_single_image, path, tasks, agent
221
+ )
222
+ future_to_path[future] = (path, agent)
223
+
224
+ # Collect results as they complete
225
+ for future in as_completed(future_to_path):
226
+ path, agent = future_to_path[future]
227
+ try:
228
+ result = future.result()
229
+ results.append(result)
230
+ except Exception as e:
231
+ logger.error(
232
+ f"Failed to process {path} with {agent.__class__.__name__}: {str(e)}"
233
+ )
234
+ results.append(
235
+ {
236
+ "image_path": str(path),
237
+ "error": str(e),
238
+ "agent": agent.__class__.__name__,
239
+ }
240
+ )
241
+
242
+ logger.info(
243
+ f"Completed batch processing of {len(validated_paths)} images"
244
+ )
245
+ return results
246
+
247
+ def __call__(self, *args, **kwargs):
248
+ """
249
+ Make the ImageAgentBatchProcessor callable like a function.
250
+
251
+ This allows the processor to be used directly as a function, which will
252
+ call the run() method with the provided arguments.
253
+
254
+ Args:
255
+ *args: Variable length argument list to pass to run()
256
+ **kwargs: Arbitrary keyword arguments to pass to run()
257
+
258
+ Returns:
259
+ The result of calling run() with the provided arguments
260
+ """
261
+ return self.run(*args, **kwargs)
@@ -0,0 +1,356 @@
1
+ import re
2
+ from typing import Callable, List, Union
3
+
4
+ from loguru import logger
5
+
6
+ from swarms.structs.agent import Agent
7
+ from swarms.structs.conversation import Conversation
8
+ from swarms.utils.generate_keys import generate_api_key
9
+ from swarms.utils.history_output_formatter import (
10
+ history_output_formatter,
11
+ )
12
+
13
+
14
+ class InteractiveGroupChatError(Exception):
15
+ """Base exception class for InteractiveGroupChat errors"""
16
+
17
+ pass
18
+
19
+
20
+ class AgentNotFoundError(InteractiveGroupChatError):
21
+ """Raised when a mentioned agent is not found in the group"""
22
+
23
+ pass
24
+
25
+
26
+ class NoMentionedAgentsError(InteractiveGroupChatError):
27
+ """Raised when no agents are mentioned in the task"""
28
+
29
+ pass
30
+
31
+
32
+ class InvalidTaskFormatError(InteractiveGroupChatError):
33
+ """Raised when the task format is invalid"""
34
+
35
+ pass
36
+
37
+
38
+ class InteractiveGroupChat:
39
+ """
40
+ An interactive group chat system that enables conversations with multiple agents using @mentions.
41
+
42
+ This class allows users to interact with multiple agents by mentioning them using @agent_name syntax.
43
+ When multiple agents are mentioned, they can see and respond to each other's tasks.
44
+
45
+ Attributes:
46
+ name (str): Name of the group chat
47
+ description (str): Description of the group chat's purpose
48
+ agents (List[Union[Agent, Callable]]): List of Agent instances or callable functions
49
+ max_loops (int): Maximum number of conversation turns
50
+ conversation (Conversation): Stores the chat history
51
+ agent_map (Dict[str, Union[Agent, Callable]]): Mapping of agent names to their instances
52
+
53
+ Args:
54
+ name (str, optional): Name of the group chat. Defaults to "InteractiveGroupChat".
55
+ description (str, optional): Description of the chat. Defaults to "An interactive group chat for multiple agents".
56
+ agents (List[Union[Agent, Callable]], optional): List of participating agents or callables. Defaults to empty list.
57
+ max_loops (int, optional): Maximum conversation turns. Defaults to 1.
58
+ output_type (str, optional): Type of output format. Defaults to "string".
59
+ interactive (bool, optional): Whether to enable interactive terminal mode. Defaults to False.
60
+
61
+ Raises:
62
+ ValueError: If invalid initialization parameters are provided
63
+ """
64
+
65
+ def __init__(
66
+ self,
67
+ id: str = generate_api_key(prefix="swarms-"),
68
+ name: str = "InteractiveGroupChat",
69
+ description: str = "An interactive group chat for multiple agents",
70
+ agents: List[Union[Agent, Callable]] = [],
71
+ max_loops: int = 1,
72
+ output_type: str = "string",
73
+ interactive: bool = False,
74
+ ):
75
+ self.id = id
76
+ self.name = name
77
+ self.description = description
78
+ self.agents = agents
79
+ self.max_loops = max_loops
80
+ self.output_type = output_type
81
+ self.interactive = interactive
82
+
83
+ # Initialize conversation history
84
+ self.conversation = Conversation(time_enabled=True)
85
+
86
+ # Create a mapping of agent names to agents for easy lookup
87
+ self.agent_map = {}
88
+ for agent in agents:
89
+ if isinstance(agent, Agent):
90
+ self.agent_map[agent.agent_name] = agent
91
+ elif callable(agent):
92
+ # For callable functions, use the function name as the agent name
93
+ self.agent_map[agent.__name__] = agent
94
+
95
+ self._validate_initialization()
96
+ self._setup_conversation_context()
97
+ self._update_agent_prompts()
98
+
99
+ def _validate_initialization(self) -> None:
100
+ """
101
+ Validates the group chat configuration.
102
+
103
+ Raises:
104
+ ValueError: If any required components are missing or invalid
105
+ """
106
+ if len(self.agents) < 1:
107
+ raise ValueError(
108
+ "At least one agent is required for the group chat"
109
+ )
110
+
111
+ if self.max_loops <= 0:
112
+ raise ValueError("Max loops must be greater than 0")
113
+
114
+ def _setup_conversation_context(self) -> None:
115
+ """Sets up the initial conversation context with group chat information."""
116
+ agent_info = []
117
+ for agent in self.agents:
118
+ if isinstance(agent, Agent):
119
+ agent_info.append(
120
+ f"- {agent.agent_name}: {agent.system_prompt}"
121
+ )
122
+ elif callable(agent):
123
+ agent_info.append(
124
+ f"- {agent.__name__}: Custom callable function"
125
+ )
126
+
127
+ context = (
128
+ f"Group Chat Name: {self.name}\n"
129
+ f"Description: {self.description}\n"
130
+ f"Available Agents:\n" + "\n".join(agent_info)
131
+ )
132
+ self.conversation.add(role="System", content=context)
133
+
134
+ def _update_agent_prompts(self) -> None:
135
+ """Updates each agent's system prompt with information about other agents and the group chat."""
136
+ agent_info = []
137
+ for agent in self.agents:
138
+ if isinstance(agent, Agent):
139
+ agent_info.append(
140
+ {
141
+ "name": agent.agent_name,
142
+ "description": agent.system_prompt,
143
+ }
144
+ )
145
+ elif callable(agent):
146
+ agent_info.append(
147
+ {
148
+ "name": agent.__name__,
149
+ "description": "Custom callable function",
150
+ }
151
+ )
152
+
153
+ group_context = (
154
+ f"\n\nYou are part of a group chat named '{self.name}' with the following description: {self.description}\n"
155
+ f"Other participants in this chat:\n"
156
+ )
157
+
158
+ for agent in self.agents:
159
+ if isinstance(agent, Agent):
160
+ # Create context excluding the current agent
161
+ other_agents = [
162
+ info
163
+ for info in agent_info
164
+ if info["name"] != agent.agent_name
165
+ ]
166
+ agent_context = group_context
167
+ for other in other_agents:
168
+ agent_context += (
169
+ f"- {other['name']}: {other['description']}\n"
170
+ )
171
+
172
+ # Update the agent's system prompt
173
+ agent.system_prompt = (
174
+ agent.system_prompt + agent_context
175
+ )
176
+ logger.info(
177
+ f"Updated system prompt for agent: {agent.agent_name}"
178
+ )
179
+
180
+ def _extract_mentions(self, task: str) -> List[str]:
181
+ """
182
+ Extracts @mentions from the task.
183
+
184
+ Args:
185
+ task (str): The input task
186
+
187
+ Returns:
188
+ List[str]: List of mentioned agent names
189
+
190
+ Raises:
191
+ InvalidtaskFormatError: If the task format is invalid
192
+ """
193
+ try:
194
+ # Find all @mentions using regex
195
+ mentions = re.findall(r"@(\w+)", task)
196
+ return [
197
+ mention
198
+ for mention in mentions
199
+ if mention in self.agent_map
200
+ ]
201
+ except Exception as e:
202
+ logger.error(f"Error extracting mentions: {e}")
203
+ raise InvalidTaskFormatError(f"Invalid task format: {e}")
204
+
205
+ def start_interactive_session(self):
206
+ """
207
+ Start an interactive terminal session for chatting with agents.
208
+
209
+ This method creates a REPL (Read-Eval-Print Loop) that allows users to:
210
+ - Chat with agents using @mentions
211
+ - See available agents and their descriptions
212
+ - Exit the session using 'exit' or 'quit'
213
+ - Get help using 'help' or '?'
214
+ """
215
+ if not self.interactive:
216
+ raise InteractiveGroupChatError(
217
+ "Interactive mode is not enabled. Initialize with interactive=True"
218
+ )
219
+
220
+ print(f"\nWelcome to {self.name}!")
221
+ print(f"Description: {self.description}")
222
+ print("\nAvailable agents:")
223
+ for name, agent in self.agent_map.items():
224
+ if isinstance(agent, Agent):
225
+ print(
226
+ f"- @{name}: {agent.system_prompt.splitlines()[0]}"
227
+ )
228
+ else:
229
+ print(f"- @{name}: Custom callable function")
230
+
231
+ print("\nCommands:")
232
+ print("- Type 'help' or '?' for help")
233
+ print("- Type 'exit' or 'quit' to end the session")
234
+ print("- Use @agent_name to mention agents")
235
+ print("\nStart chatting:")
236
+
237
+ while True:
238
+ try:
239
+ # Get user input
240
+ user_input = input("\nYou: ").strip()
241
+
242
+ # Handle special commands
243
+ if user_input.lower() in ["exit", "quit"]:
244
+ print("Goodbye!")
245
+ break
246
+
247
+ if user_input.lower() in ["help", "?"]:
248
+ print("\nHelp:")
249
+ print("1. Mention agents using @agent_name")
250
+ print(
251
+ "2. You can mention multiple agents in one task"
252
+ )
253
+ print("3. Available agents:")
254
+ for name in self.agent_map:
255
+ print(f" - @{name}")
256
+ print(
257
+ "4. Type 'exit' or 'quit' to end the session"
258
+ )
259
+ continue
260
+
261
+ if not user_input:
262
+ continue
263
+
264
+ # Process the task and get responses
265
+ try:
266
+ response = self.run(user_input)
267
+ print("\nChat:")
268
+ print(response)
269
+
270
+ except NoMentionedAgentsError:
271
+ print(
272
+ "\nError: Please mention at least one agent using @agent_name"
273
+ )
274
+ except AgentNotFoundError as e:
275
+ print(f"\nError: {str(e)}")
276
+ except Exception as e:
277
+ print(f"\nAn error occurred: {str(e)}")
278
+
279
+ except KeyboardInterrupt:
280
+ print("\nSession terminated by user. Goodbye!")
281
+ break
282
+ except Exception as e:
283
+ print(f"\nAn unexpected error occurred: {str(e)}")
284
+ print(
285
+ "The session will continue. You can type 'exit' to end it."
286
+ )
287
+
288
+ def run(self, task: str) -> str:
289
+ """
290
+ Process a task and get responses from mentioned agents.
291
+ If interactive mode is enabled, this will be called by start_interactive_session().
292
+ Otherwise, it can be called directly for single task processing.
293
+ """
294
+ try:
295
+ # Extract mentioned agents
296
+ mentioned_agents = self._extract_mentions(task)
297
+
298
+ if not mentioned_agents:
299
+ raise NoMentionedAgentsError(
300
+ "No valid agents mentioned in the task"
301
+ )
302
+
303
+ # Add user task to conversation
304
+ self.conversation.add(role="User", content=task)
305
+
306
+ # Get responses from mentioned agents
307
+ for agent_name in mentioned_agents:
308
+ agent = self.agent_map.get(agent_name)
309
+ if not agent:
310
+ raise AgentNotFoundError(
311
+ f"Agent '{agent_name}' not found"
312
+ )
313
+
314
+ try:
315
+ # Get the complete conversation history
316
+ context = (
317
+ self.conversation.return_history_as_string()
318
+ )
319
+
320
+ # Get response from agent
321
+ if isinstance(agent, Agent):
322
+ response = agent.run(
323
+ task=f"{context}\nPlease respond to the latest task as {agent_name}."
324
+ )
325
+ else:
326
+ # For callable functions
327
+ response = agent(context)
328
+
329
+ # Add response to conversation
330
+ if response and not response.isspace():
331
+ self.conversation.add(
332
+ role=agent_name, content=response
333
+ )
334
+ logger.info(f"Agent {agent_name} responded")
335
+
336
+ except Exception as e:
337
+ logger.error(
338
+ f"Error getting response from {agent_name}: {e}"
339
+ )
340
+ self.conversation.add(
341
+ role=agent_name,
342
+ content=f"Error: Unable to generate response - {str(e)}",
343
+ )
344
+
345
+ return history_output_formatter(
346
+ self.conversation, self.output_type
347
+ )
348
+
349
+ except InteractiveGroupChatError as e:
350
+ logger.error(f"GroupChat error: {e}")
351
+ raise
352
+ except Exception as e:
353
+ logger.error(f"Unexpected error: {e}")
354
+ raise InteractiveGroupChatError(
355
+ f"Unexpected error occurred: {str(e)}"
356
+ )
@@ -1,3 +1,4 @@
1
+ from typing import Union
1
2
  from swarms.structs.agent import Agent
2
3
  from typing import List, Callable
3
4
  from swarms.structs.conversation import Conversation
@@ -82,3 +83,77 @@ def aggregate(
82
83
  return history_output_formatter(
83
84
  conversation=conversation, type=type
84
85
  )
86
+
87
+
88
+ def run_agent(
89
+ agent: Agent,
90
+ task: str,
91
+ type: HistoryOutputType = "all",
92
+ *args,
93
+ **kwargs,
94
+ ):
95
+ """
96
+ Run an agent on a task.
97
+
98
+ Args:
99
+ agent (Agent): The agent to run
100
+ task (str): The task to run the agent on
101
+ type (HistoryOutputType, optional): The type of history output. Defaults to "all".
102
+ *args: Variable length argument list
103
+ **kwargs: Arbitrary keyword arguments
104
+
105
+ Returns:
106
+ Any: The result of running the agent
107
+
108
+ Raises:
109
+ ValueError: If agent or task is None
110
+ TypeError: If agent is not an instance of Agent
111
+ """
112
+ if agent is None:
113
+ raise ValueError("Agent cannot be None")
114
+
115
+ if task is None:
116
+ raise ValueError("Task cannot be None")
117
+
118
+ if not isinstance(agent, Agent):
119
+ raise TypeError("Agent must be an instance of Agent")
120
+
121
+ try:
122
+ return agent.run(task=task, *args, **kwargs)
123
+ except Exception as e:
124
+ raise RuntimeError(f"Error running agent: {str(e)}")
125
+
126
+
127
+ def find_agent_by_name(
128
+ agents: List[Union[Agent, Callable]], agent_name: str
129
+ ) -> Agent:
130
+ """
131
+ Find an agent by its name in a list of agents.
132
+
133
+ Args:
134
+ agents (List[Union[Agent, Callable]]): List of agents to search through
135
+ agent_name (str): Name of the agent to find
136
+
137
+ Returns:
138
+ Agent: The found agent
139
+
140
+ Raises:
141
+ ValueError: If agents list is empty or agent not found
142
+ TypeError: If agent_name is not a string
143
+ """
144
+ if not agents:
145
+ raise ValueError("Agents list cannot be empty")
146
+
147
+ if not isinstance(agent_name, str):
148
+ raise TypeError("Agent name must be a string")
149
+
150
+ if not agent_name.strip():
151
+ raise ValueError("Agent name cannot be empty or whitespace")
152
+
153
+ try:
154
+ for agent in agents:
155
+ if hasattr(agent, "name") and agent.name == agent_name:
156
+ return agent
157
+ raise ValueError(f"Agent with name '{agent_name}' not found")
158
+ except Exception as e:
159
+ raise RuntimeError(f"Error finding agent: {str(e)}")
@@ -9,7 +9,7 @@ from typing import Any, Callable, List, Optional
9
9
  from swarms.structs.agent import Agent
10
10
  from swarms.structs.conversation import Conversation
11
11
  from swarms.structs.multi_agent_exec import run_agents_concurrently
12
- from swarms.structs.output_types import OutputType
12
+ from swarms.utils.output_types import OutputType
13
13
  from swarms.utils.formatter import formatter
14
14
  from swarms.utils.loguru_logger import initialize_logger
15
15