Skip to main content

Overview

The PlannerWorkerSwarm implements a planner-worker-judge architecture for parallel multi-agent task execution. Based on Cursor’s “Scaling long-running autonomous coding” research, it separates planning from execution: a planner decomposes goals into prioritized tasks, worker agents claim and execute tasks concurrently from a shared queue, and a judge evaluates the cycle results. The swarm follows a cycle-based workflow:
  1. Planning: A planner agent decomposes the goal into concrete, prioritized tasks with dependencies
  2. Execution: Worker agents independently claim tasks from a shared queue and execute them concurrently via ThreadPoolExecutor — no worker-to-worker coordination
  3. Evaluation: A judge agent evaluates the combined results and decides: complete, fill gaps, or fresh start
  4. Iteration: If not complete, the planner receives judge feedback and produces new tasks for the next cycle
PlannerWorkerSwarm is not exported from the top-level swarms package. Import it from swarms.structs.planner_worker_swarm.
PlannerWorkerSwarm emits OpenTelemetry spans: one when it is constructed, and one for each run() call. Worker threads carry the tracing context, so each worker’s Agent.run span nests under the swarm run. See Telemetry to turn tracing off.

Installation

Attributes

str
default:"PlannerWorkerSwarm"
Name identifier for this swarm instance
str
default:"A planner-worker execution swarm"
Description of the swarm’s purpose
List[Union[Agent, Callable]]
required
Worker agents that execute tasks. Must not be empty.
int
default:"1"
Maximum planner-worker-judge cycles (must be greater than 0)
str
default:"gpt-5.4"
Model for the planner agent
str
default:"gpt-5.4"
Model for the judge agent
int
default:"1"
Max recursive sub-planner depth. 1 = no sub-planners; 2 = CRITICAL tasks are decomposed once.
Optional[float]
default:"None"
Max seconds for the entire worker pool per cycle
Optional[float]
default:"None"
Max seconds per individual task execution
Optional[int]
default:"None"
Max concurrent worker threads. Defaults to min(len(agents), os.cpu_count() or 4).
OutputType
default:"dict-all-except-first"
Format for the final result
bool
default:"False"
Whether to save the conversation history to the swarm’s workspace directory at the end of each run()
bool
default:"False"
Enable verbose logging
Raises:

Methods

run()

Executes the planner-worker-judge cycle up to max_loops times or until the judge declares the goal complete.
Parameters:
  • task (str): The goal to accomplish
  • img (str, optional): Optional image input, passed to the planner, every worker and the judge
Returns: Formatted conversation history per output_type Raises:
  • ValueError: If task is not provided
Each call clears the shared conversation before adding the new task, so reusing one swarm instance does not carry the previous task’s transcript forward. The task queue is not cleared between run() calls.

get_status()

Returns a structured status report of the swarm and its task queue.
Returns: Status dict with name, original_task, and queue (containing total, progress, status_counts, and per-task details)

Usage Examples

Quick Start

Multi-Cycle with Judge Feedback

Set max_loops > 1 so the judge can request additional planning cycles when the goal is not yet achieved:
The judge evaluates each cycle:
  • Cycle 1: Judge finds gaps (“missing regional analysis”) — planner creates targeted tasks
  • Cycle 2: Judge finds remaining issues (“outlook section too shallow”) — planner fills gaps
  • Cycle 3: Judge marks complete with quality 9/10

Recursive Sub-Planners

Set max_planner_depth > 1 to automatically decompose CRITICAL-priority tasks via sub-planner agents:
When the top-level planner produces a CRITICAL task (e.g., “Design the database schema and API endpoints”), it gets cancelled and replaced by the sub-planner’s more granular subtasks.

Timeouts

  • worker_timeout: Total wall time for the worker pool per cycle. Workers stop claiming new tasks after this deadline.
  • task_timeout: Per-task execution limit. If exceeded, the task fails with a TimeoutError and may be retried. The timed-out call is not interrupted: the worker records the failure once that call returns.

Checking Swarm Status

SwarmRouter Integration

PlannerWorkerSwarm is available as a swarm type in SwarmRouter:

Architecture

Design Principles (from the Cursor blog)

Task State Machine

Cycle Flow

How It Works

Planner Agent: Created internally each cycle. Uses structured output (PlannerTaskSpec) to produce a plan narrative and a list of concrete tasks with title, description, priority (0-3), and dependency titles. On subsequent cycles, the planner receives the judge’s feedback (gaps + follow-up instructions) appended to the original task. Worker Execution: Each worker runs in a ThreadPoolExecutor thread, independently claiming tasks from a shared TaskQueue. Workers never coordinate with each other. Each worker loop: claims a task, resets agent memory, builds context (WORKER_SYSTEM_PROMPT + task description + dependency results), executes via agent.run(), and marks the task complete or failed. A completed result is added to the shared conversation under the worker’s name. Optimistic concurrency: every task has a version field. State transitions check the expected version — if another worker modified the task, the operation is rejected. This avoids lock-based coordination problems (deadlocks, forgotten releases). Claim priority: highest priority first, then oldest first, with dependency satisfaction required. Judge Agent: Created internally after workers complete. Its task holds the original goal and a status report of every task in the queue. The shared conversation reaches it as typed chat turns, not pasted into the task: its own earlier verdicts arrive as assistant turns and the planner’s and workers’ messages as labelled user turns, so in later cycles it can tell its own reasoning from theirs. It produces a CycleVerdict:

Fresh Start vs Gap Fill

Schemas

PlannerTask

Represents a single task in the shared queue.

TaskPriority

Best Practices

Error Handling

Performance Considerations

Source Code

View the source code on GitHub