Skip to content

Conversation

@IlumCI
Copy link
Contributor

@IlumCI IlumCI commented Nov 4, 2025

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: #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:

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
Loading
  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:
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")
  1. REACT Workflow with Custom Tools:
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")
  1. REACT Tool Definitions:
# 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"]
        }
    }
}
  1. Workflow Routing in _run() Method:
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 ...
  1. Plan Creation Method:
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

📚 Documentation preview 📚: https://swarms--1182.org.readthedocs.build/en/1182/

Added REACT workflow tools for automated task management, including functions for action execution, subtask completion, and objective completion. Updated the REACT workflow execution method to integrate these tools and handle responses accordingly.
f"Error in REACT workflow loop {loop_count}: {e}"
)
attempt += 1
if attempt >= self.retry_attempts:

Check failure

Code scanning / Pyre

Unsupported operand Error

Unsupported operand [58]: >= is not supported for operand types int and Optional[int].
logger.error(f"Error in REACT workflow: {error}")
# Restore original tools and context_length on error
if hasattr(self, "tools_list_dictionary"):
self.tools_list_dictionary = original_tools

Check failure

Code scanning / Pyre

Uninitialized local Error

Uninitialized local [61]: Local variable original_tools is undefined, or not always defined.
if hasattr(self, "tools_list_dictionary"):
self.tools_list_dictionary = original_tools
if hasattr(self, "context_length"):
self.context_length = original_context_length

Check failure

Code scanning / Pyre

Uninitialized local Error

Uninitialized local [61]: Local variable original_context_length is undefined, or not always defined.
# Check stopping conditions
if (
self.stopping_condition is not None
and self._check_stopping_condition(response)

Check failure

Code scanning / Pyre

Uninitialized local Error

Uninitialized local [61]: Local variable response is undefined, or not always defined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant