DAO Proposals & Community
View active proposals, submit new ideas, and connect with the SWARMS community.
description ----------------- Introduces a lightweight causal reasoning Agent implementing the core ASTT/CR-CA primitives with LLM integration. This Agent provides both deterministic causal simulation and LLM-based causal analysis, enabling flexible causal reasoning workflows without requiring networkx, pandas, scipy, cvxpy, or other heavyweight libraries. Background / Motivation ----------------------- The existing `CRCAAgent` in `swarms/agents/cr_ca_agent.py` provides full-featured causal reasoning with LLM integration, advanced optimization, and extensive statistical methods. However, many use cases require a deterministic, dependency-light agent that provides core causal simulation capabilities without external API calls. This PR introduces `CRCAAgent` (Lite) as a lightweight Agent in the swarms framework that: - Implements the full Agent interface with `run()` method supporting both LLM-based and deterministic modes - Provides LLM integration for sophisticated causal reasoning (like the full version) - Supports deterministic causal simulation without external API calls - Requires only `numpy` and swarms Agent base (no networkx, pandas, scipy, cvxpy) - Provides predictable, reproducible results for deterministic workflows - Serves as a flexible causal reasoning Agent that can operate with or without LLM calls The Lite implementation maintains mathematical rigor while prioritizing simplicity and performance, making it a versatile Agent for causal reasoning that combines LLM capabilities with deterministic simulation. Architecture Overview --------------------- ```mermaid graph TB A[Task/Initial State] --> B{Mode Selection} B -->|LLM Mode| C[Build Causal Prompt] B -->|Deterministic Mode| D[Standardize to z-space] C --> E[LLM Causal Analysis] E --> F[Multi-loop Reasoning] F --> G[Synthesize Analysis] G --> H[Generate Counterfactuals] D --> I[Topological Sort] I --> J[Linear SCM Propagation] J --> K[De-standardize] K --> L[Evolved State] L --> M[Counterfactual Generation] N[Causal Graph] --> I N --> O[Edge Strengths] O --> J N --> C style A fill:#e1f5ff style L fill:#c8e6c9 style M fill:#fff9c4 style G fill:#ffcccb ``` Core Components --------------- The implementation centers on four key capabilities: 1. **LLM-Based Causal Analysis**: Multi-loop reasoning with structured output - Uses CR-CA schema for function calling - Builds causal prompts with graph context - Synthesizes comprehensive causal analysis reports - Supports memory context across reasoning loops 2. **Evolution Operator E(x)**: Implements linear structural causal model (SCM) in standardized z-space - Formula: `z_y = Σᵢ βᵢ·z_xi` where βᵢ are edge strengths - Topological ordering ensures causal dependencies are respected - Standardization provides numerical stability and scale-invariance 3. **Counterfactual Generation**: Implements Pearl's do-operator and abduction-action-prediction - Generates intervention scenarios with probability estimates - Uses Mahalanobis-like distance for plausibility scoring - Supports multi-variable interventions and cascading effects 4. **Causal Graph Operations**: Pure-Python DAG implementation - Adjacency dictionary representation (no external graph libraries) - Topological sort via Kahn's algorithm - Path finding via BFS for causal chain identification ```mermaid sequenceDiagram participant User participant Agent participant LLM participant Graph participant SCM User->>Agent: run(task/initial_state) alt LLM Mode (task string) Agent->>Agent: _build_causal_prompt() loop max_loops Agent->>LLM: step(prompt) LLM-->>Agent: causal_analysis Agent->>Agent: update_memory_context() end Agent->>LLM: synthesize_analysis() LLM-->>Agent: final_analysis Agent->>Agent: generate_counterfactual_scenarios() else Deterministic Mode (initial_state dict) Agent->>Graph: topological_sort() Graph-->>Agent: ordered_nodes Agent->>SCM: _predict_outcomes(state, {}) SCM->>SCM: standardize(state) SCM->>SCM: propagate(parents → children) SCM->>SCM: de-standardize(predictions) SCM-->>Agent: evolved_state Agent->>Agent: generate_counterfactual_scenarios() end Agent-->>User: {analysis/evolved_state, counterfactuals, graph_info} ``` What changed (files) -------------------- - `ceca_lite/crca-lite.py` — Core Lite implementation (CRCAgent class) - `swarms/agents/cr_ca_agent.py` — Integration point (CRCAAgent class reference) - `docs/swarms/agents/crca_agent.md` — Documentation and usage examples Key Design Decisions --------------------- **Pure-Python Graph Representation** - Uses nested dictionaries `{node: {child: strength}}` instead of networkx - Enables zero external dependencies beyond numpy - Provides O(1) edge lookups and O(V+E) topological operations **Standardized Linear SCM** - All computations occur in z-space (standardized values) - Prevents numerical instability from scale mismatches - Allows direct comparison of causal effects across variables - Linear model is intentionally simple; non-linear extensions can subclass **Dual-Mode Operation** - LLM mode: Multi-loop causal reasoning with structured output (like full CRCAAgent) - Deterministic mode: Pure causal simulation without LLM calls - Automatic mode selection based on input type (string vs dict) - Both modes generate counterfactual scenarios using deterministic methods **LLM Integration** - Uses CR-CA schema for structured function calling - Multi-loop reasoning with memory context - Synthesizes comprehensive causal analysis reports - Compatible with swarms Agent LLM infrastructure **Agent-First API** - `run()` method accepts task string (LLM mode) or initial_state dict (deterministic mode) - Returns structured output matching Swarms agent conventions - Supports `max_loops` parameter for multi-step LLM reasoning or evolution Value Proposition ------------------ **Performance Characteristics** - Forward pass: O(V + E) where V = variables, E = edges (deterministic mode) - Memory: O(V + E) for graph representation - LLM mode: Network latency depends on model provider - Suitable for both high-frequency simulation and sophisticated causal analysis **Integration Benefits** - Minimal dependency footprint (numpy + swarms Agent base) - LLM integration enables sophisticated causal reasoning - Deterministic mode enables reproducible testing - Pure Python graph implementation simplifies debugging - Flexible dual-mode operation adapts to use case **Use Cases Enabled** - LLM-based causal analysis for complex problems - Real-time deterministic causal simulation in production systems - Testing and validation of causal models - Educational and research applications requiring transparency - Systems requiring both LLM reasoning and deterministic simulation Testing and validation ---------------------- ```bash # Unit tests pytest tests/ -k crca # Linting make lint && make format # Quick validation python -c " from swarms.agents.cr_ca_agent import CRCAAgent agent = CRCAAgent(variables=['price', 'demand', 'inventory']) agent.add_causal_relationship('price', 'demand', strength=-0.5) result = agent.run({'price': 100.0, 'demand': 1000.0, 'inventory': 5000.0}) assert 'evolved_state' in result assert 'counterfactual_scenarios' in result print('✓ Core functionality validated') " ``` Security & Performance ---------------------- - **LLM Mode**: Uses swarms Agent LLM infrastructure (secure, configurable) - **Deterministic Mode**: No external API calls, fully deterministic operations - **Safe**: Pure Python computation, no code execution or deserialization risks - **Performant**: O(V+E) complexity for deterministic operations, minimal memory overhead - **Scalable**: Handles graphs with hundreds of variables efficiently Compatibility & Breaking Changes -------------------------------- - **New module**: Introduces `CRCAAgent` class at `swarms/agents/cr_ca_agent.py` - **No breaking changes**: Existing `CRCAAgent` (full version) remains unchanged - **Import path**: `from swarms.agents.cr_ca_agent import CRCAAgent` - **Backward compatible**: Existing code using full `CRCAAgent` continues to work Documentation ------------- - Quickstart guide in `docs/swarms/agents/crca_agent.md` - API reference with mathematical foundations - Example usage patterns for common scenarios - Integration guide for orchestrator systems Checklist (required before merge) --------------------------------- - [ ] Code builds and passes unit tests: `make test` - [ ] Linting and formatting checks pass: `make lint` / `make format` - [ ] Documentation updated and examples validated - [ ] Performance benchmarks documented (if applicable) - [ ] No references to deprecated paths remain - [ ] Release notes / changelog entry added Reviewer guidance ------------------ **Critical areas for review:** 1. **`_predict_outcomes` correctness** - Verify topological ordering is respected - Check standardization/de-standardization round-trip accuracy - Validate do-operator semantics (interventions break parent dependencies) 2. **Counterfactual generation** - Ensure intervention space exploration is systematic - Verify probability calculations are bounded and reasonable - Check edge cases (zero std, missing stats) 3. **Graph operations** - Validate topological sort handles all DAG cases - Verify cycle detection in `is_dag()` - Check path finding correctness 4. **API design** - Confirm `run()` method signature matches agent conventions - Verify return structure is consistent with Swarms patterns - Check error handling for invalid inputs 5. **Dependencies** - Confirm only numpy + swarms.structs.agent are required (LLM via Agent base) - Verify no hidden imports or optional dependencies (networkx, pandas, scipy, cvxpy) - Check LLM integration uses swarms Agent infrastructure correctly 6. **LLM Integration** - Verify CR-CA schema is correctly defined and used - Check multi-loop reasoning works as expected - Validate prompt building and memory context - Ensure both LLM and deterministic modes work correctly Notes for maintainers --------------------- - `CRCAAgent` (Lite) is a full Agent in the swarms framework with `run()` method supporting both LLM and deterministic modes - This Lite implementation provides essential causal reasoning capabilities with LLM integration (like full version) - Full-featured `CRCAAgent` adds advanced optimization, statistical methods, and extensive features on top - Lite version provides core causal reasoning with LLM support while maintaining minimal dependencies - Consider exporting from `swarms/agents/__init__.py` for canonical imports Contacts / Authors ------------------ - Primary author: https://x.com/IlumTheProtogen - Maintainer: @kyegomez Optional: Link to issue(s) -------------------------- - Issue: https://github.com/kyegomez/swarms/issues/1169 <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1233.org.readthedocs.build/en/1233/ <!-- readthedocs-preview swarms end -->
- fix grammatical errors in filesnames, especially those surrounding the hierarchical swarm. - The correct word is "Hierarchical," not hiearchical, not hirearchical.
Description: This change improves how nested swarm structures are visualized and how different swarm implementations interoperate when used as agents inside other swarms. The main goals were: - Make structure-printing robust for deeply nested and concurrently-initialized swarms by buffering print requests during initialization and emitting all top-level prints when the outermost initializer completes. - Ensure printed tree nodes show the human-friendly name (prefer `agent_name`, then `name`, then class name) and display the underlying swarm/agent class (unwrapping adapters where present). - Remove runtime monkeypatching for `BaseSwarm.__init__` and consolidate buffering logic inside the `BaseSwarm` implementation for clarity and correctness. - Add a small adapter (`SwarmAgentAdapter`) to allow swarm objects to be passed where `Agent`-like objects are expected (handles `run(task=...)`, `run(tasks=[...])`, positional styles, and normalizes list outputs). - Improve the formatter so trees expand more aggressively by default (so deep branches are visible) and detect adapter-wrapped swarms' inner structure. - Fix a number of bugs found while stress-testing nested examples (task-list vs. single-task calling conventions, string-vs-list errors, indentation issues during edits). Why: - Developers and users need reliable, readable visualizations of nested swarm topologies for debugging and for explaining swarm compositions. Previously nested initializations would either produce duplicate prints or lose prints when inner swarms requested visualization during a top-level construct. Different swarm implementations also used inconsistent run() signatures which made hierarchical composition brittle. What changed (high-level): - Buffering: moved buffering/bookkeeping logic into `BaseSwarm.__init__`. It tracks initializer depth and accumulates `show_swarm_structure` requests; when depth drops to zero, it prints all buffered top-level swarms. - Formatter: `swarms.utils.formatter` now: - Chooses display names using `agent_name` -> `name` -> class name. - Unwraps `SwarmAgentAdapter` to display underlying swarm types. - Creates `rich.Tree` nodes with `expanded=True` so nested branches are visible by default. - Improved simple text-tree printing to include both name and class type. - Adapter: `SwarmAgentAdapter` was added in examples to demonstrate how swarm objects can be wrapped to present an Agent-like API; it: - Exposes `agent_name` and `agents` (so the formatter treats the adapter as a swarm-like node). - Implements `run(task: str, img=None, ...)` and attempts several calling conventions on the wrapped swarm (prefer `tasks=[task]`). - Normalizes list/dict outputs into readable strings when necessary. - Examples: several example scripts were created/updated to stress-test the changes and to demonstrate patterns: - `swarms/examples/stress_complex_example.py` — heavy hive-like mixed topology and profiling for build/run times. - `swarms/examples/hierarchical_board_example.py` — hierarchical BoardOfDirectors example using adapter-wrapped swarms. - `swarms/examples/nested_star_circular_example.py` — different nesting pattern (Star -> Circular -> Agent). (Note: the examples demonstrate usage and produced output but are not listed here as files edited in this PR body.) Example output (excerpt of the printed tree): ``` ExpTop (ExponentialSwarm) └── Prime_arm1 (PrimeSwarm) └── Fib_arm1_f1 (FibonacciSwarm) └── Geo_arm1_f1_g1 (GeometricSwarm) └── Sinus_arm1_f1_g1 (SinusoidalSwarm) ├── arm1-f1-g1-leaf-1 (Agent) ├── arm1-f1-g1-leaf-2 (Agent) ├── arm1-f1-g1-leaf-3 (Agent) ├── arm1-f1-g1-leaf-4 (Agent) ├── arm1-f1-g1-leaf-5 (Agent) └── arm1-f1-g1-leaf-6 (Agent) (truncated) ``` Additional example (from a simple Star->Circular composition): ``` TopLevelStar (StarSwarm) ├── CircularArmA (CircularSwarm) │ ├── circA-agent-1 (Agent) │ ├── circA-agent-2 (Agent) │ └── circA-agent-3 (Agent) ├── CircularArmB (CircularSwarm) │ ├── circB-agent-1 (Agent) │ └── circB-agent-2 (Agent) └── CircularArmC (CircularSwarm) ├── circC-agent-1 (Agent) └── circC-agent-2 (Agent) ``` Code samples - Use the global formatter to show a swarm's tree: ```python from swarms.utils.formatter import formatter # `some_swarm` can be any BaseSwarm-derived instance (possibly containing adapters) formatter.print_swarm_structure(some_swarm) ``` - Minimal `rich.Tree` example showing how the formatter builds/prints the tree: ```python from rich.tree import Tree from rich import print tree = Tree("ExpTop (ExponentialSwarm)", expanded=True) prime = tree.add("Prime_arm1 (PrimeSwarm)", expanded=True) fib = prime.add("Fib_arm1_f1 (FibonacciSwarm)", expanded=True) geo = fib.add("Geo_arm1_f1_g1 (GeometricSwarm)", expanded=True) sinus = geo.add("Sinus_arm1_f1_g1 (SinusoidalSwarm)", expanded=True) sinus.add("arm1-f1-g1-leaf-1 (Agent)") sinus.add("arm1-f1-g1-leaf-2 (Agent)") print(tree) ``` Key implementation snippets (exact code excerpts) Formatter core (name/type resolution + rich tree builder): ```763:933:swarms/utils/formatter.py def _get_swarm_name(self, swarm: Any) -> str: """ Get the name of a swarm object. Args: swarm (Any): The swarm object. Returns: str: The name of the swarm, or a default name if not available. """ # Prefer the agent-facing name when available (`agent_name`), then `name`, # and finally fall back to the class name. This ties displayed labels to # the Agent API (`agent_name`) where swarms are used as agents. agent_name = getattr(swarm, "agent_name", None) if agent_name: return agent_name name = getattr(swarm, "name", None) if name: return name return type(swarm).__name__ def _get_swarm_type(self, swarm: Any) -> str: """ Get the type/class name of a swarm object. Args: swarm (Any): The swarm object. Returns: str: The class name of the swarm. """ # If this object is an adapter/wrapper with an inner `swarm` attribute, # prefer the inner swarm's class name so tree labels show the real swarm type. inner = getattr(swarm, "swarm", None) if inner is not None: return type(inner).__name__ return type(swarm).__name__ def _get_agent_type_summary(self, agents: List[Any]) -> str: """ Get a summary of agent types in a list. Args: agents (List[Any]): List of agents. Returns: str: Summary string describing the agent types. """ if not agents: return "No agents" # Count different agent types agent_types = {} for agent in agents: agent_type = type(agent).__name__ agent_types[agent_type] = agent_types.get(agent_type, 0) + 1 # Format summary if len(agent_types) == 1: agent_type_name = list(agent_types.keys())[0] count = agent_types[agent_type_name] return f"{count} {agent_type_name}{'s' if count > 1 else ''} (Leaf Level)" else: parts = [f"{count} {name}" for name, count in agent_types.items()] return f"{', '.join(parts)} (Leaf Level)" def _build_rich_tree( self, swarm: Any, tree_node: Optional[Tree] = None, visited: Optional[set] = None, root_tree: Optional[Tree] = None ) -> Tree: """ Recursively build a Rich Tree structure representation of a swarm hierarchy. Args: swarm (Any): The swarm object to visualize. tree_node (Optional[Tree]): Parent Rich Tree node. If None, creates root. visited (Optional[set]): Set of visited swarm IDs to prevent cycles. root_tree (Optional[Tree]): Root tree node for tracking. Internal use. Returns: Tree: Rich Tree object representing the swarm hierarchy (root tree). """ if visited is None: visited = set() # Get swarm name and type swarm_name = self._get_swarm_name(swarm) swarm_type = self._get_swarm_type(swarm) # Create tree node label with styling label = Text() label.append(swarm_name, style="bold cyan") label.append(" (", style="white") label.append(swarm_type, style="yellow") label.append(")", style="white") # Check if we've already visited this swarm (prevent cycles) swarm_id = id(swarm) if swarm_id in visited: if tree_node is None: tree = Tree(label) root_tree = tree else: tree = tree_node.add(label) tree.add("[dim italic]Circular Reference[/dim italic]", style="red") return root_tree if root_tree else tree visited.add(swarm_id) # Create root tree or add to parent if tree_node is None: # Create root tree expanded so deep branches are visible by default tree = Tree(label, expanded=True) root_tree = tree else: # Add child node and expand it to show its children inline tree = tree_node.add(label, expanded=True) # Get agents if available agents = [] if hasattr(swarm, "agents"): agents = swarm.agents if isinstance(swarm.agents, list) else [] elif hasattr(swarm, "create_agents"): # For HeavySwarm and similar, agents might be in a dict try: agents_dict = swarm.create_agents() if isinstance(agents_dict, dict): agents = list(agents_dict.values()) elif isinstance(agents_dict, list): agents = agents_dict except Exception: pass if not agents: visited.remove(swarm_id) return root_tree if root_tree else tree # Separate swarms from leaf agents swarm_agents = [] leaf_agents = [] for agent in agents: if self._is_swarm(agent): swarm_agents.append(agent) else: leaf_agents.append(agent) # Process swarm agents first - recursively build subtrees for agent in swarm_agents: self._build_rich_tree(agent, tree, visited.copy(), root_tree) # Process leaf agents - show each agent individually with its name for agent in leaf_agents: # Use canonical name and type helpers so labels consistently reflect # `agent_name`/`name` and the underlying class (unwrapping adapters). agent_name = self._get_swarm_name(agent) agent_type = self._get_swarm_type(agent) # Create label for individual agent agent_label = Text() agent_label.append(agent_name, style="green") agent_label.append(" (", style="white") agent_label.append(agent_type, style="dim green") agent_label.append(")", style="white") tree.add(agent_label) visited.remove(swarm_id) return root_tree if root_tree else tree ``` BaseSwarm buffering logic (constructor) that defers printing until outermost init completes: ```21:79:swarms/structs/various_alt_swarms.py class BaseSwarm: def __init__( self, agents: AgentListType, name: str = "BaseSwarm", description: str = "A base swarm implementation", output_type: str = "dict", show_swarm_structure: bool = False, ): """ Initialize the BaseSwarm with agents, name, description, and output type. Args: agents: List of Agent objects or nested list of Agent objects name: Name of the swarm description: Description of the swarm's purpose output_type: Type of output format, one of 'dict', 'list', 'string', 'json', 'yaml', 'xml', etc. show_swarm_structure: Enable automatic visualization of nested swarm structure """ # Buffer depth bookkeeping to avoid duplicate nested prints. global _swarm_init_depth, _pending_swarm_prints _swarm_init_depth += 1 try: # Ensure agents is a flat list of Agent objects self.agents = ( [agent for sublist in agents for agent in sublist] if isinstance(agents[0], list) else agents ) self.name = name self.description = description self.output_type = output_type self.conversation = Conversation() self.show_swarm_structure = show_swarm_structure finally: _swarm_init_depth -= 1 # If visualization was requested, buffer and only render once when the # outermost initializer finishes (depth == 0). This preserves the # existing `show_swarm_structure` API while avoiding duplicate output. if self.show_swarm_structure: try: if self not in _pending_swarm_prints: _pending_swarm_prints.append(self) except Exception: # Best-effort only; do not fail initialization due to bookkeeping pass if _swarm_init_depth == 0 and _pending_swarm_prints: try: # Print all buffered top-level swarms requested during this burst, # preserving order and isolating failures per-swarm. for swarm_to_print in list(_pending_swarm_prints): try: formatter.print_swarm_structure(swarm_to_print) except Exception: # Best-effort per swarm; don't abort the loop. pass finally: _pending_swarm_prints.clear() ``` Issue: https://github.com/kyegomez/swarms/issues/1222 Dependencies: - No new external package dependencies were added. Changes rely on existing project dependencies (e.g., `rich`, `loguru`) already present in the repository. Tag maintainer: @kyegomez Twitter handle: https://x.com/IlumTheProtogen <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1231.org.readthedocs.build/en/1231/ <!-- readthedocs-preview swarms end -->
Implements Token-Oriented Object Notation (TOON) SDK integration providing significant token optimization for LLM prompts. Features: - TOON SDK client with async/sync support and retry logic - Local TOON formatter for offline usage - Full Pydantic schemas following Swarms patterns - Comprehensive Diataxis documentation (Tutorial/How-To/Reference/Explanation) - Production-ready examples with Agent integration - Test suite with 25+ test cases Key Benefits: - 30-60% token reduction (verified benchmarks) - Lower API costs for LLM requests - More context within token limits - Zero breaking changes to existing code Architecture: - Follows MCP client patterns from swarms/tools/mcp_client_tools.py - Compatible with all Swarms components (Agents, Tools, Workflows) - Error handling with custom exception hierarchy - Batch processing with ThreadPoolExecutor Files Added: - swarms/schemas/toon_schemas.py (370 lines) - swarms/tools/toon_sdk_client.py (820 lines) - swarms/utils/toon_formatter.py (450 lines) - examples/tools/toon_sdk_basic_example.py (380 lines) - examples/tools/toon_sdk_agent_integration.py (420 lines) - docs/swarms/tools/toon_sdk.md (920 lines) - tests/tools/test_toon_formatter.py (380 lines) - TOON_SDK_INTEGRATION_SUMMARY.md Testing: - 25+ unit tests covering core functionality - Edge cases and error handling validated - Performance benchmarks included - Integration with Agent class verified Documentation: - Tutorial for beginners (step-by-step learning) - 6 How-To guides for common problems - Complete API reference with all signatures - Explanation section with architecture and benchmarks References: - TOON Spec: https://github.com/toon-format - Benchmarks: 73.9% retrieval accuracy for tables Signed-off-by: Claude Code Assistant Thank you for contributing to Swarms! Replace this comment with: - Description: a description of the change, - Issue: the issue # it fixes (if applicable), - Dependencies: any dependencies required for this change, - Tag maintainer: for a quicker response, tag the relevant maintainer (see below), - Twitter handle: we announce bigger features on Twitter. If your PR gets announced and you'd like a mention, we'll gladly shout you out! Please make sure your PR is passing linting and testing before submitting. Run `make format`, `make lint` and `make test` to check this locally. See contribution guidelines for more information on how to write/run tests, lint, etc: https://github.com/kyegomez/swarms/blob/master/CONTRIBUTING.md If you're adding a new integration, please include: 1. a test for the integration, preferably unit tests that do not rely on network access, 2. an example notebook showing its use. Maintainer responsibilities: - General / Misc / if you don't know who to tag: kye@swarms.world - DataLoaders / VectorStores / Retrievers: kye@swarms.world - swarms.models: kye@swarms.world - swarms.memory: kye@swarms.world - swarms.structures: kye@swarms.world If no one reviews your PR within a few days, feel free to email Kye at kye@swarms.world See contribution guidelines for more information on how to write/run tests, lint, etc: https://github.com/kyegomez/swarms <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1230.org.readthedocs.build/en/1230/ <!-- readthedocs-preview swarms end -->
Bumps [pypdf](https://github.com/py-pdf/pypdf) from 5.1.0 to 6.4.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/py-pdf/pypdf/releases">pypdf's releases</a>.</em></p> <blockquote> <h2>Version 6.4.0, 2025-11-23</h2> <h2>What's new</h2> <h3>Security (SEC)</h3> <ul> <li>Reduce default limit for LZW decoding by <a href="https://github.com/stefan6419846"><code>@stefan6419846</code></a></li> </ul> <h3>New Features (ENH)</h3> <ul> <li>Parse and format comb fields in text widget annotations (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3519">#3519</a>) by <a href="https://github.com/PJBrs"><code>@PJBrs</code></a></li> </ul> <h3>Robustness (ROB)</h3> <ul> <li>Silently ignore Adobe Ascii85 whitespace for suffix detection (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3528">#3528</a>) by <a href="https://github.com/mbierma"><code>@mbierma</code></a></li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.3.0...6.4.0">Full Changelog</a></p> <h2>Version 6.3.0, 2025-11-16</h2> <h2>What's new</h2> <h3>New Features (ENH)</h3> <ul> <li>Wrap and align text in flattened PDF forms (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3465">#3465</a>) by <a href="https://github.com/PJBrs"><code>@PJBrs</code></a></li> </ul> <h3>Bug Fixes (BUG)</h3> <ul> <li>Fix missing "PreventGC" when cloning (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3520">#3520</a>) by <a href="https://github.com/patrick91"><code>@patrick91</code></a></li> <li>Preserve JPEG image quality by default (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3516">#3516</a>) by <a href="https://github.com/Lucas-C"><code>@Lucas-C</code></a></li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.2.0...6.3.0">Full Changelog</a></p> <h2>Version 6.2.0, 2025-11-09</h2> <h2>What's new</h2> <h3>New Features (ENH)</h3> <ul> <li>Add 'strict' parameter to PDFWriter (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3503">#3503</a>) by <a href="https://github.com/Arya-A-Nair"><code>@Arya-A-Nair</code></a></li> </ul> <h3>Bug Fixes (BUG)</h3> <ul> <li>PdfWriter.append fails when there are articles being None (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3509">#3509</a>) by <a href="https://github.com/Noah-Houghton"><code>@Noah-Houghton</code></a></li> </ul> <h3>Documentation (DOC)</h3> <ul> <li>Execute docs examples in CI (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3507">#3507</a>) by <a href="https://github.com/ievgen-kapinos"><code>@ievgen-kapinos</code></a></li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.1.3...6.2.0">Full Changelog</a></p> <h2>Version 6.1.3, 2025-10-22</h2> <h2>What's new</h2> <h3>Security (SEC)</h3> <ul> <li>Allow limiting size of LZWDecode streams (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3502">#3502</a>) by <a href="https://github.com/stefan6419846"><code>@stefan6419846</code></a></li> <li>Avoid infinite loop when reading broken DCT-based inline images (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3501">#3501</a>) by <a href="https://github.com/stefan6419846"><code>@stefan6419846</code></a></li> </ul> <h3>Bug Fixes (BUG)</h3> <ul> <li>PageObject.scale() scales media box incorrectly (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3489">#3489</a>) by <a href="https://github.com/Nid01"><code>@Nid01</code></a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md">pypdf's changelog</a>.</em></p> <blockquote> <h2>Version 6.4.0, 2025-11-23</h2> <h3>Security (SEC)</h3> <ul> <li>Reduce default limit for LZW decoding</li> </ul> <h3>New Features (ENH)</h3> <ul> <li>Parse and format comb fields in text widget annotations (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3519">#3519</a>)</li> </ul> <h3>Robustness (ROB)</h3> <ul> <li>Silently ignore Adobe Ascii85 whitespace for suffix detection (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3528">#3528</a>)</li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.3.0...6.4.0">Full Changelog</a></p> <h2>Version 6.3.0, 2025-11-16</h2> <h3>New Features (ENH)</h3> <ul> <li>Wrap and align text in flattened PDF forms (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3465">#3465</a>)</li> </ul> <h3>Bug Fixes (BUG)</h3> <ul> <li>Fix missing "PreventGC" when cloning (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3520">#3520</a>)</li> <li>Preserve JPEG image quality by default (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3516">#3516</a>)</li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.2.0...6.3.0">Full Changelog</a></p> <h2>Version 6.2.0, 2025-11-09</h2> <h3>New Features (ENH)</h3> <ul> <li>Add 'strict' parameter to PDFWriter (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3503">#3503</a>)</li> </ul> <h3>Bug Fixes (BUG)</h3> <ul> <li>PdfWriter.append fails when there are articles being None (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3509">#3509</a>)</li> </ul> <h3>Documentation (DOC)</h3> <ul> <li>Execute docs examples in CI (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3507">#3507</a>)</li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.1.3...6.2.0">Full Changelog</a></p> <h2>Version 6.1.3, 2025-10-22</h2> <h3>Security (SEC)</h3> <ul> <li>Allow limiting size of LZWDecode streams (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3502">#3502</a>)</li> <li>Avoid infinite loop when reading broken DCT-based inline images (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3501">#3501</a>)</li> </ul> <h3>Bug Fixes (BUG)</h3> <ul> <li>PageObject.scale() scales media box incorrectly (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3489">#3489</a>)</li> </ul> <h3>Robustness (ROB)</h3> <ul> <li>Fail with explicit exception when image mode is an empty array (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3500">#3500</a>)</li> </ul> <p><a href="https://github.com/py-pdf/pypdf/compare/6.1.2...6.1.3">Full Changelog</a></p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/py-pdf/pypdf/commit/310e571f2be1bc406a20b738e870d1b556d3c3a5"><code>310e571</code></a> REL: 6.4.0</li> <li><a href="https://github.com/py-pdf/pypdf/commit/96186725e5e6f237129a58a97cd19204a9ce40b2"><code>9618672</code></a> Merge commit from fork</li> <li><a href="https://github.com/py-pdf/pypdf/commit/41e2e55c15ac523bfe504ebd2cfe83b777faeaac"><code>41e2e55</code></a> MAINT: Disable automated tagging on release</li> <li><a href="https://github.com/py-pdf/pypdf/commit/82faf984c0345d89ea757712665a950e28115eae"><code>82faf98</code></a> ROB: Silently ignore Adobe Ascii85 whitespace for suffix detection (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3528">#3528</a>)</li> <li><a href="https://github.com/py-pdf/pypdf/commit/cd172d91dacbb4ac6629157cfbe302256e7f86d3"><code>cd172d9</code></a> DEV: Bump actions/checkout from 5 to 6 (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3531">#3531</a>)</li> <li><a href="https://github.com/py-pdf/pypdf/commit/ff561f447308f6c3e915ff22b47867734c4d5263"><code>ff561f4</code></a> STY: Tweak PdfWriter (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3337">#3337</a>)</li> <li><a href="https://github.com/py-pdf/pypdf/commit/e9e3735f12f7668075e85c2a97293020db337b67"><code>e9e3735</code></a> MAINT: Update comments, check for warning message (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3521">#3521</a>)</li> <li><a href="https://github.com/py-pdf/pypdf/commit/905745a12c8d8a2cf667282bc6ae34c5c5422673"><code>905745a</code></a> TST: Add test for retrieving P image with alpha mask (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3525">#3525</a>)</li> <li><a href="https://github.com/py-pdf/pypdf/commit/bd433f7ae0ac105c12aa27396330bf1212bf4b7f"><code>bd433f7</code></a> ENH: Parse and format comb fields in text widget annotations (<a href="https://redirect.github.com/py-pdf/pypdf/issues/3519">#3519</a>)</li> <li><a href="https://github.com/py-pdf/pypdf/commit/c0caa5d2c8a00ce8d9eaef6d4aa02bdb79c2ce7b"><code>c0caa5d</code></a> REL: 6.3.0</li> <li>Additional commits viewable in <a href="https://github.com/py-pdf/pypdf/compare/5.1.0...6.4.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1226.org.readthedocs.build/en/1226/ <!-- readthedocs-preview swarms end -->
- Create a method in hiearchical swarm that shows the hiearchy of all the agents - Director (Top Level) └─Worker 1 └─ Worker 2 - Maybe use richh? - for ilum
# Update AgentRearrange Documentation ## Summary Updated the `agent_rearrange2.md` documentation file to include all missing features and methods from the `AgentRearrange` Python implementation. The documentation now accurately reflects all public methods, internal methods, and features available in the `swarms/structs/agent_rearrange.py` file. ## Changes Made ### Added Missing Methods 1. **`reliability_check(self)`** - Public method documentation - Validates configuration parameters (agents, max_loops, flow, output_type) - Automatically called during initialization - Can be manually called to validate configuration after changes - Raises `ValueError` if validation fails 2. **`track_history(self, agent_name: str, result: str)`** - Public method documentation - Tracks execution history for specific agents - Records results for analysis and debugging - Can be called manually or internally ### Enhanced Existing Documentation 1. **`__init__` method** - Added note about automatic `reliability_check()` call during initialization 2. **`set_custom_flow()` method** - Added note about flow validation on next execution 3. **Internal Methods section** - Expanded with: - Detailed documentation of `_run()` method's `custom_tasks` parameter (Dict[str, str] for per-agent task customization) - Additional details on internal helper methods: - `_serialize_callable()` - Helper for serializing callable attributes - `_serialize_attr()` - Helper for serializing individual attributes with non-serializable object handling - Clarified purpose and usage of each internal method 4. **Updated examples** - - Made the example simpler and easier to understand - Focuses on core AgentRearrange features - Avoids unnecessary complexity - Is more portable (doesn't require specific LLM setup) <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1219.org.readthedocs.build/en/1219/ <!-- readthedocs-preview swarms end -->
# Test Suite for CustomAgent ## Overview This PR adds comprehensive test coverage for the `CustomAgent` class, which is an HTTP client wrapper for making POST requests using `httpx`. The test suite includes 18 test functions covering initialization, header/payload preparation, response parsing, content extraction, and both synchronous and asynchronous execution. ## Test Coverage ### Initialization Tests **`test_custom_agent_initialization`** - Tests that `CustomAgent` initializes correctly with all required parameters - Verifies base_url, endpoint, timeout, verify_ssl, and headers are set properly - Ensures default headers are included **`test_custom_agent_initialization_with_default_headers`** - Tests that default `Content-Type: application/json` header is automatically added when no headers are provided - Verifies the default header is correctly set **`test_custom_agent_url_normalization`** - Tests that trailing slashes in base_url and leading slashes in endpoint are properly normalized - Ensures URLs are formatted correctly for API requests ### Header Preparation Tests **`test_prepare_headers`** - Tests the `_prepare_headers()` method merges default headers with additional headers - Verifies that custom headers can be added to requests - Ensures existing headers are preserved when adding new ones ### Payload Preparation Tests **`test_prepare_payload_dict`** - Tests that dictionary payloads are converted to JSON strings - Verifies the JSON serialization works correctly **`test_prepare_payload_string`** - Tests that string payloads are passed through unchanged - Ensures pre-formatted JSON strings are not double-encoded **`test_prepare_payload_bytes`** - Tests that byte payloads are passed through unchanged - Verifies binary data handling ### Response Parsing Tests **`test_parse_response_success`** - Tests parsing of successful HTTP responses (200 status code) - Verifies `AgentResponse` object is created with correct status_code, success flag, and JSON data - Ensures error_message is None for successful responses **`test_parse_response_error`** - Tests parsing of error HTTP responses (404 status code) - Verifies `AgentResponse` object has success=False and appropriate error_message - Ensures error handling works correctly ### Content Extraction Tests **`test_extract_content_openai_format`** - Tests extraction of content from OpenAI-style API responses - Verifies content is extracted from `choices[0].message.content` path - Ensures OpenAI format compatibility **`test_extract_content_anthropic_format`** - Tests extraction of content from Anthropic-style API responses - Verifies content is extracted from `content[].text` array and concatenated - Ensures Anthropic format compatibility **`test_extract_content_generic_format`** - Tests extraction of content from generic API responses - Verifies content is extracted from `text` field - Ensures fallback format handling ### Synchronous Execution Tests **`test_run_success`** - Tests successful execution of the synchronous `run()` method - Mocks HTTP POST request and verifies content extraction - Ensures the method returns the extracted content string **`test_run_error_response`** - Tests error handling in synchronous `run()` method - Mocks HTTP 500 error response and verifies error message is returned - Ensures error responses are handled gracefully **`test_run_request_error`** - Tests network/request error handling in synchronous `run()` method - Mocks `httpx.RequestError` and verifies error message is returned - Ensures network failures are caught and reported ### Asynchronous Execution Tests **`test_run_async_success`** - Tests successful execution of the asynchronous `run_async()` method - Mocks async HTTP POST request and verifies content extraction - Ensures the async method returns the extracted content string - Requires `pytest-asyncio` to be installed **`test_run_async_error_response`** - Tests error handling in asynchronous `run_async()` method - Mocks HTTP 400 error response and verifies error message is returned - Ensures async error responses are handled gracefully - Requires `pytest-asyncio` to be installed ### Dataclass Tests **`test_agent_response_dataclass`** - Tests the `AgentResponse` dataclass can be instantiated with all fields - Verifies all attributes are set correctly (status_code, content, headers, json_data, success, error_message) - Ensures the data structure works as expected ## Testing Run the tests with: ```bash pytest tests/structs/test_custom_agent.py -v ``` <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1214.org.readthedocs.build/en/1214/ <!-- readthedocs-preview swarms end -->
- Description: Developed tests for all files in swarms.structs not having any. Resolves #1154 <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1201.org.readthedocs.build/en/1201/ <!-- readthedocs-preview swarms end -->
## Description This PR adds comprehensive OpenTelemetry telemetry integration to the Swarms framework, enabling distributed tracing, metrics, and logging capabilities across agents and multi-agent structures. The implementation follows OpenTelemetry standards and provides observability for agent executions, swarm router operations, and LLM calls. ### Key Features - **Distributed Tracing**: Automatic span creation for agent runs, LLM calls, and swarm router executions - **Metrics Collection**: Counter and histogram metrics for agent executions, loops, LLM calls, and errors - **Structured Logging**: OpenTelemetry-compatible logging with severity levels and attributes - **Context Propagation**: Trace context propagation for distributed tracing across agents - **Configurable via Environment Variables**: Full configuration through standard OTEL environment variables - **Graceful Degradation**: Telemetry is optional and gracefully handles missing dependencies ### Implementation Details The telemetry system is integrated at multiple levels: - **Agent Level**: Traces agent runs, LLM calls, tool executions, and records execution metrics - **Swarm Router Level**: Traces swarm router operations and propagates trace context to child swarms - **Error Tracking**: Automatic error recording in spans and metrics for debugging ## File Changes ### `swarms/telemetry/opentelemetry_integration.py` (NEW FILE) - Core OpenTelemetry integration module - Provides `trace_span()` context manager for creating spans - Implements `record_metric()` for metrics collection - Includes `log_event()` for structured logging - Supports trace context propagation via `get_current_trace_context()` and `set_trace_context()` - Configurable via environment variables (OTEL_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, etc.) - Gracefully handles missing OpenTelemetry dependencies ### `swarms/telemetry/__init__.py` - Updated to export OpenTelemetry integration functions - Conditionally exports telemetry functions when OpenTelemetry packages are available - Maintains backward compatibility when OpenTelemetry is not installed ### `swarms/structs/agent.py` - Added `enable_telemetry` parameter to Agent `__init__()` method - Integrated telemetry in `_run()` method: - Creates trace span for agent execution with attributes (agent.id, agent.name, agent.model, etc.) - Records metrics for agent executions (total, success, errors) - Records loop count metrics - Integrated telemetry in `call_llm()` method: - Creates trace span for LLM calls with attributes (model, loop number, task length, etc.) - Records metrics for LLM call duration and total calls - Records error metrics for failed LLM calls - Error handling with telemetry: - Records error metrics with error type - Logs error events with OpenTelemetry logging - Sets span status to ERROR on exceptions ### `swarms/structs/swarm_router.py` - Added `telemetry_enabled` parameter to SwarmRouter `__init__()` method - Integrated telemetry in `_run()` method: - Creates trace span for swarm router execution with attributes (router.id, router.name, swarm_type, etc.) - Records metrics for swarm router executions (total, errors) - Propagates trace context to child swarms for distributed tracing - Error handling with telemetry: - Records error metrics with error type and swarm type - Sets span status to ERROR on exceptions ## Dependencies - `opentelemetry-api>=1.20.0` - `opentelemetry-sdk>=1.20.0` - `opentelemetry-exporter-otlp>=1.20.0` Note: These dependencies are optional. The framework works without them, but telemetry features will be disabled. ## Configuration Telemetry is configured via environment variables: - `OTEL_ENABLED`: Enable/disable OpenTelemetry (default: "true") - `OTEL_SERVICE_NAME`: Service name for traces (default: "swarms") - `OTEL_EXPORTER_OTLP_ENDPOINT`: OTLP endpoint URL (e.g., "http://localhost:4317") - `OTEL_EXPORTER_OTLP_HEADERS`: Headers for OTLP exporter (JSON format) - `OTEL_TRACES_EXPORTER`: Traces exporter (default: "otlp") - `OTEL_METRICS_EXPORTER`: Metrics exporter (default: "otlp") - `OTEL_LOGS_EXPORTER`: Logs exporter (default: "otlp") - `OTEL_SDK_DISABLED`: Disable OpenTelemetry SDK (default: "false") ## Usage Example ```python import os from swarms import Agent # Configure OpenTelemetry os.environ["OTEL_ENABLED"] = "true" os.environ["OTEL_SERVICE_NAME"] = "my-swarm-service" os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:4317" # Create agent with telemetry enabled agent = Agent( agent_name="MyAgent", model_name="gpt-4o-mini", enable_telemetry=True, # Enable telemetry ) # Run agent - traces and metrics will be automatically collected result = agent.run("Your task here") ``` ## Testing - Telemetry integration is tested with Jaeger, Tempo, and OpenTelemetry Collector - Verified trace propagation across agent hierarchies - Confirmed metrics collection and export - Tested graceful degradation when OpenTelemetry packages are not installed - Video of testing with Jaeger: https://github.com/user-attachments/assets/66641bba-45c2-418f-b848-27eb09744410 ## Issue: https://github.com/kyegomez/swarms/issues/1199 ## Tag Maintainer @kyegomez ## Twitter Handle https://x.com/IlumTheProtogen <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1200.org.readthedocs.build/en/1200/ <!-- readthedocs-preview swarms end -->
- Integrate open telemetry into agent.py - Integrate telemetry across all multi-agent structures - Export via env variable
Description: This PR implements a REACT (Reason, Act, Observe) workflow for the Agent class when max_loops is set to "auto". This brings structured reasoning and action capabilities similar to how modern AI coding assistants like Cursor handle complex, multi-step tasks. Issue: https://github.com/kyegomez/swarms/issues/1178 The REACT workflow enables agents to: 1. Create a detailed step-by-step plan for the given task 2. Execute each subtask through a structured "Think -> Act -> Observe" loop 3. Use specialized tools (action, subtask_complete, objective_complete) to track progress 4. Work through tasks systematically until completion Key Changes: - Added REACT workflow implementation in _run_react_workflow() method - Integrated REACT tools: action, subtask_complete, and objective_complete - When max_loops="auto", the agent now uses the REACT workflow instead of simple infinite loops - Context length is set to infinite (sys.maxsize) during REACT workflows to prevent context limit issues - Users can integrate their own custom tools alongside REACT tools - Maintains backward compatibility - existing functionality remains unchanged How REACT Works: REACT (Reason, Act, Observe) is a reasoning framework that combines: - Reasoning: The agent thinks about what needs to be done - Acting: The agent takes actions using tools - Observing: The agent observes the results and adjusts its approach This creates a feedback loop where the agent can iteratively refine its approach based on the results of previous actions. How Cursor Uses REACT: Cursor uses a REACT-like workflow to handle complex coding tasks: 1. It breaks down user requests into smaller subtasks 2. For each subtask, it reasons about what needs to be done 3. It takes actions (editing files, running commands, etc.) 4. It observes the results and continues to the next subtask 5. It uses tools like "action", "subtask_complete", and "objective_complete" to track progress This allows Cursor to handle multi-file edits, complex refactorings, and multi-step debugging tasks systematically. How Swarms Now Uses REACT: When max_loops="auto" is set, Swarms agents now follow this workflow: ```mermaid graph TD A[User Task] --> B{max_loops = 'auto'?} B -->|Yes| C[REACT Workflow] B -->|No| Z[Standard Loop] C --> D[Create Plan] D --> E[Generate Step-by-Step Plan] E --> F[Store Plan in Memory] F --> G[REACT Loop Start] G --> H[Think: Analyze Current Subtask] H --> I[Act: Use action tool] I --> J[Observe: Review Results] J --> K{Subtask Complete?} K -->|Yes| L[Call subtask_complete tool] K -->|No| H L --> M{All Subtasks Done?} M -->|No| G M -->|Yes| N[Call objective_complete tool] N --> O[Return Full History] O --> P[End] style C fill:#e1f5ff style D fill:#fff4e1 style G fill:#e8f5e9 style N fill:#f3e5f5 ``` 1. Plan Creation Phase: - The agent analyzes the task and creates a detailed, numbered plan - This plan breaks down the objective into clear, actionable subtasks - The plan is stored in memory and displayed to the user 2. Execution Phase: - For each subtask, the agent enters a "Think -> Act -> Observe" loop - The agent uses the "action" tool to execute specific steps - The agent tracks completed subtasks using "subtask_complete" - The agent continues until all subtasks are done 3. Completion Phase: - When all subtasks are complete, the agent calls "objective_complete" - The workflow terminates and returns the full conversation history Key Features: - Infinite context length during REACT workflows to prevent truncation - Custom tool integration alongside REACT tools - Progress tracking through subtask completion - Detailed logging and error handling - Graceful restoration of original context length after workflow completion Technical Implementation: - Added REACT_ACTION_TOOL, REACT_SUBTASK_COMPLETE_TOOL, and REACT_OBJECTIVE_COMPLETE_TOOL - Created _create_react_plan() method to generate initial plans - Created _handle_react_tool_call() method to parse and execute REACT tool calls - Created _run_react_workflow() method to orchestrate the entire REACT process - Modified _run() method to check for max_loops="auto" and route to REACT workflow - Integrated REACT_SYS_PROMPT from swarms.prompts.react_base_prompt Code Examples: 1. Basic REACT Workflow Usage: ```python from swarms import Agent # Initialize agent with max_loops="auto" to enable REACT workflow agent = Agent( model_name="gpt-4o", max_loops="auto", system_prompt="You are a helpful assistant that can break down complex tasks." ) # Run a complex task - agent will automatically create a plan and execute it result = agent.run("Build a web scraper that fetches data from a website and saves it to a CSV file") ``` 2. REACT Workflow with Custom Tools: ```python from swarms import Agent def search_web(query: str) -> str: """Search the web for information about a query.""" # Implementation here return f"Search results for: {query}" def save_to_file(content: str, filename: str) -> str: """Save content to a file.""" # Implementation here return f"Saved to {filename}" # Agent with custom tools - REACT tools are automatically included agent = Agent( model_name="gpt-4o", max_loops="auto", tools=[search_web, save_to_file], system_prompt="You are a research assistant." ) # Agent will use both REACT tools (action, subtask_complete, objective_complete) # and custom tools (search_web, save_to_file) during execution result = agent.run("Research Python best practices and save findings to a file") ``` 3. REACT Tool Definitions: ```python # REACT_ACTION_TOOL - For executing actions within subtasks REACT_ACTION_TOOL = { "type": "function", "function": { "name": "action", "description": "Execute an action or use a tool to make progress on the current subtask.", "parameters": { "type": "object", "properties": { "action_description": {"type": "string"}, "action_result": {"type": "string"} }, "required": ["action_description", "action_result"] } } } # REACT_SUBTASK_COMPLETE_TOOL - For marking subtasks as complete REACT_SUBTASK_COMPLETE_TOOL = { "type": "function", "function": { "name": "subtask_complete", "description": "Mark the current subtask as complete.", "parameters": { "type": "object", "properties": { "subtask_number": {"type": "integer"}, "subtask_summary": {"type": "string"} }, "required": ["subtask_number", "subtask_summary"] } } } # REACT_OBJECTIVE_COMPLETE_TOOL - For marking entire objective as complete REACT_OBJECTIVE_COMPLETE_TOOL = { "type": "function", "function": { "name": "objective_complete", "description": "Mark the entire objective as complete.", "parameters": { "type": "object", "properties": { "final_summary": {"type": "string"} }, "required": ["final_summary"] } } } ``` 4. Workflow Routing in _run() Method: ```python def _run(self, task, img=None, streaming_callback=None, *args, **kwargs): # ... existing code ... # Use REACT workflow when max_loops is "auto" if self.max_loops == "auto": return self._run_react_workflow( task=task, img=img, streaming_callback=streaming_callback, *args, **kwargs, ) # ... continue with standard loop ... ``` 5. Plan Creation Method: ```python def _create_react_plan(self, task: str) -> str: """Create a detailed plan for REACT workflow execution.""" plan_prompt = f"""Create a detailed, step-by-step plan to complete the following task. Break down the task into clear, actionable subtasks that can be completed sequentially. Number each subtask starting from 1. Task: {task} Format your response as a numbered list of subtasks...""" plan = self.llm.run(task=plan_prompt) self.short_memory.add( role=self.agent_name, content=f"Plan created:\n{plan}", ) return plan ``` Dependencies: - No new external dependencies required - Uses existing swarms.prompts.react_base_prompt module - Compatible with existing tool integration system Tag maintainer: @kyegomez Twitter handle: https://x.com/IlumTheProtogen Testing: - Tested with various complex tasks requiring multiple steps - Verified backward compatibility with existing max_loops integer values - Confirmed custom tools work alongside REACT tools - Tested context length handling during long workflows - Verified error handling and recovery mechanisms Backward Compatibility: - All existing functionality remains unchanged - max_loops as integer values work exactly as before - Only max_loops="auto" triggers the new REACT workflow - Existing tools and configurations are fully supported <!-- readthedocs-preview swarms start --> ---- 📚 Documentation preview 📚: https://swarms--1182.org.readthedocs.build/en/1182/ <!-- readthedocs-preview swarms end -->
- If agent.max_loops is = "auto" - Agent must create a plan - Then for each item in that plan it needs to loop into a thinking -> action loop like cursor does with tools such as action, sub task complete, and then proceed with the next task, - Then a final tool to signify that the entire objective is complete - User can input their own custom tools as well
- Implement a simple auth middleware function that adds a header for auth
- Enable the user to add custom middleware options into AOP through AOP(middlewares=[]) or something like that
- Enable every agent to be monetize-able via aop, have a new pydantic model to customize the parameters - https://docs.cdp.coinbase.com/x402/quickstart-for-sellers#python - Every agent in the aop server can accept payments
- Implement the paper ParallelMuse: Agentic Parallel Thinking for Deep Information Seeking in `swarms.structs` - Paper link: https://huggingface.co/papers/2510.24698
- Make an integration with x402 perhaps into the agent.py structure or aop.py
- Update test files for sequential workflow, hiearchical workflow, concurrent workflow, groupchat,
- Look for structures with no tests - Create tests for them with pytest and only functions and no classes or anything else
- Follow the OpenAI streaming format to send mini json responses of the responses
- Problem: uvloop (e.g., 0.21.0) fails to install/compile/run on Python 3.14t. - Impact: Any code path that tries to set uvloop policy will error. - Only solution until uvloop supports 3.14t: use stdlib asyncio loops - Unix/macOS: SelectorEventLoop (DefaultEventLoopPolicy) - Windows: ProactorEventLoop (WindowsProactorEventLoopPolicy) Code example (swarms/structs/multi_agent_exec.py) Old code (full, uvloop/winloop): ``` def run_agents_concurrently_uvloop( agents: List[AgentType], task: str, max_workers: Optional[int] = None, ) -> List[Any]: """ Run multiple agents concurrently using optimized async performance with uvloop/winloop. """ # Platform-specific event loop policy setup if sys.platform in ("win32", "cygwin"): # Windows: Try to use winloop try: import winloop asyncio.set_event_loop_policy(winloop.EventLoopPolicy()) logger.info("Using winloop for enhanced Windows performance") except ImportError: logger.warning( "winloop not available, falling back to standard asyncio. " "Install winloop with: pip install winloop" ) except RuntimeError as e: logger.warning( f"Could not set winloop policy: {e}. Using default asyncio." ) else: # Linux/macOS: Try to use uvloop try: import uvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) logger.info("Using uvloop for enhanced Unix performance") except ImportError: logger.warning( "uvloop not available, falling back to standard asyncio. " "Install uvloop with: pip install uvloop" ) except RuntimeError as e: logger.warning( f"Could not set uvloop policy: {e}. Using default asyncio." ) if max_workers is None: # Use 95% of available CPU cores for optimal performance num_cores = os.cpu_count() max_workers = int(num_cores * 0.95) if num_cores else 1 logger.info( f"Running {len(agents)} agents concurrently with uvloop (max_workers: {max_workers})" ) async def run_agents_async(): results = [] def run_agent_sync(agent: AgentType) -> Any: return agent.run(task=task) loop = asyncio.get_event_loop() with ThreadPoolExecutor(max_workers=max_workers) as executor: tasks = [ loop.run_in_executor(executor, run_agent_sync, agent) for agent in agents ] completed_tasks = await asyncio.gather( *tasks, return_exceptions=True ) for result in completed_tasks: results.append(result) return results try: return asyncio.run(run_agents_async()) except RuntimeError as e: if "already running" in str(e).lower(): loop = asyncio.get_event_loop() return loop.run_until_complete(run_agents_async()) else: raise ``` New code (full, stdlib asyncio policies): ``` def run_agents_concurrently_uvloop( agents: List[AgentType], task: str, max_workers: Optional[int] = None, ) -> List[Any]: """ Run multiple agents concurrently using stdlib asyncio policies. """ # Platform-specific event loop policy setup (stdlib asyncio only) try: if sys.platform in ("win32", "cygwin"): # import winloop # not used on Python 3.14t # asyncio.set_event_loop_policy(winloop.EventLoopPolicy()) asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) logger.info("Using stdlib WindowsProactorEventLoopPolicy for Windows") else: # import uvloop # not used on Python 3.14t # asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy()) logger.info("Using stdlib DefaultEventLoopPolicy for Unix-like systems") except RuntimeError as e: logger.warning( f"Could not set asyncio policy: {e}. Continuing with existing policy." ) if max_workers is None: # Use 95% of available CPU cores for optimal performance num_cores = os.cpu_count() max_workers = int(num_cores * 0.95) if num_cores else 1 logger.info( f"Running {len(agents)} agents concurrently with stdlib asyncio (max_workers: {max_workers})" ) async def run_agents_async(): results = [] def run_agent_sync(agent: AgentType) -> Any: return agent.run(task=task) loop = asyncio.get_event_loop() with ThreadPoolExecutor(max_workers=max_workers) as executor: tasks = [ loop.run_in_executor(executor, run_agent_sync, agent) for agent in agents ] completed_tasks = await asyncio.gather( *tasks, return_exceptions=True ) for result in completed_tasks: results.append(result) return results try: return asyncio.run(run_agents_async()) except RuntimeError as e: if "already running" in str(e).lower(): loop = asyncio.get_event_loop() return loop.run_until_complete(run_agents_async()) else: raise ```