Skip to main content

Overview

The PlannerGeneratorEvaluator is a domain-agnostic three-agent orchestration harness inspired by the GAN-style architecture described in Anthropic’s harness design research. It coordinates long-running autonomous tasks from a short natural-language prompt, using an iterative generate-evaluate feedback loop to converge on high-quality output across any domain. All three agents communicate through a single shared file on disk. The harness follows this workflow:
  1. Planning: Planner expands a short prompt into an ambitious plan with steps and evaluation criteria
  2. Contract Negotiation: Generator proposes what “done” looks like for each step; Evaluator reviews
  3. Execution: Generator produces concrete output and self-assesses before handoff
  4. Evaluation: Evaluator scores output per-criterion with hard thresholds — any criterion below its threshold fails the step
  5. Feedback Loop: On failure, Generator receives scores + trajectory signal (refine or pivot) and retries
  6. All state on disk: The shared state file is the single append-only record of the run. Each run() call rewrites it from scratch

Installation

Key Features

Attributes

str
default:"None"
Unique identifier for this harness instance. Auto-generated via generate_id("planner-generator-evaluator") if not provided.
str
default:"PlannerGeneratorEvaluator"
Human-readable name for this harness.
str
Description of the harness purpose.
str
default:"gpt-5.4"
Model identifier for all three agents
str
default:"None"
Override model for the Planner
str
default:"None"
Override model for the Generator
str
default:"None"
Override model for the Evaluator
int
default:"10"
Upper bound on plan steps to execute
int
default:"3"
Retries allowed after a failed evaluation before the harness advances to the next step. Each step gets up to max_retries_per_step + 1 attempts; 0 means one attempt
str
default:"os.getcwd()"
Directory where output is produced. Created if it does not exist
str
default:"None"
Path for the shared state file. Defaults to {working_directory}/pge_shared_state_{id}.md
Dict[str, float]
default:"{}"
Fallback score thresholds by criterion name, on the same 1-10 scale the Evaluator scores with. Criterion names are matched in lowercase. See Pass and fail rules
OutputType
default:"dict"
Format for the returned conversation history, such as "dict", "str", "list", "final", "json" or "yaml"
bool
default:"False"
Enable verbose logging
str
default:"PLANNER_SYSTEM_PROMPT"
System prompt for the Planner agent. Defaults to the built-in planner prompt.
str
default:"GENERATOR_SYSTEM_PROMPT"
System prompt for the Generator agent. Defaults to the built-in generator prompt.
str
default:"EVALUATOR_SYSTEM_PROMPT"
System prompt for the Evaluator agent. Defaults to the built-in evaluator prompt.
Agent
default:"None"
Pre-configured Agent for planning. When set, planner_model_name and planner_system_prompt are not applied to it
Agent
default:"None"
Pre-configured Agent for generation (e.g., with file/code tools). When set, generator_model_name and generator_system_prompt are not applied to it
Agent
default:"None"
Pre-configured Agent for evaluation (e.g., with Playwright MCP). When set, evaluator_model_name and evaluator_system_prompt are not applied to it
Raises:

Methods

run()

Execute the full PGE harness pipeline from a short prompt to completed output.
Parameters:
  • task (str): A short natural-language description of the desired task
Returns: Formatted conversation history according to output_type Raises: ValueError if task is empty or not a string. Any error raised by an agent is logged and re-raised. Each call clears the conversation and rewrites the shared state file, so reusing one harness for several tasks does not carry the previous task forward. After run() completes, access harness.last_result for structured metadata:

batched_run()

Run the harness on multiple tasks sequentially.
Parameters:
  • tasks (List[str]): List of task prompts to process
Returns: List of results, one per task

get_harness_result()

Return the current state of the harness as a dictionary.
Returns: Dictionary with id, name, shared_state_path, and conversation (the full conversation history as a dict)

__call__()

Makes the harness callable directly, as a convenience alias for run().
Parameters:
  • task (str): A short natural-language description of the desired task
  • *args, **kwargs: Forwarded to run()
Returns: Same as run()

Return Types

The PGE harness produces three structured return types that are also re-exported from swarms.structs so you can type-annotate against them.

StepContract

A negotiated agreement between the Generator and the Evaluator for one step of the plan — the title and acceptance criteria the Generator commits to, plus an approved flag and any amendments the Evaluator pushed back with.
int
required
1-indexed position in the plan.
str
default:"\"\""
Short step title.
str
default:"\"\""
What the Generator’s output must satisfy for the Evaluator to approve.
bool
default:"False"
Whether the Evaluator approved this contract.
str
default:"\"\""
Evaluator-suggested changes when not approved.

EvaluationReport

Per-step evaluation produced by the Evaluator agent — criterion scores, threshold checks, pass/fail, and feedback used to drive retries.
int
required
Step this report belongs to.
Dict[str, float] | None
default:"None"
Map of lowercased criterion name to score, on the Evaluator’s 1-10 scale.
Dict[str, float] | None
default:"None"
Minimum scores needed to pass each criterion.
bool
default:"False"
Whether the step met every threshold.
str
default:"\"\""
Specific, retry-targeted feedback for the Generator.
str
default:"\"\""
Short prose summary of the evaluation.
str
default:"\"\""
Unparsed Evaluator output. On a retry, this full text is what the Generator receives as feedback.
All three classes are plain Python classes with a to_dict() method. EvaluationReport.to_dict() leaves out raw_evaluation.

HarnessResult

Final result container — populated after run() and accessible via harness.last_result.
str
default:"\"\""
Path to the shared state file, which holds the plan, every contract, work log and evaluation, and the final summary.
str
default:"\"\""
The full plan the harness executed against.
List[Dict[str, Any]] | None
default:"None"
One dict per step with step_number, contract (the StepContract as a dict), evaluations (one EvaluationReport dict per attempt), retries and passed.
float
default:"0.0"
Wall-clock seconds for the full run.
int
default:"0"
Number of steps that hit passed=True.
int
default:"0"
Total retries across all steps.

Usage Examples

Basic Usage

Custom Agents with Tools

Pass pre-configured agents with tools so the Generator can write files and the Evaluator can verify them on disk:

Evaluator with Playwright MCP (Web App Testing)

For web application development, give the Evaluator browser automation via Playwright MCP so it can test the running app like a real user:

Custom Thresholds

Provide default score thresholds that apply when the Planner doesn’t define them. They are used when the Evaluator reports inline scores (accuracy: 7/10); a score table row carries its own threshold. See Pass and fail rules:

Architecture Details

Shared State File

All inter-agent communication flows through a single append-only markdown file. Each agent call receives the full file pasted into its task, and its reply is appended as a new timestamped, labeled section:

Contract negotiation

Before each step, the Generator proposes a contract and the Evaluator reviews it. The contract counts as approved when the review contains “approved” and not “amendments required”. Execution proceeds either way: an unapproved review is kept as the contract’s amendments, and it stays in the shared state for the Generator to read.

Step count

The harness reads the number of steps from the plan: the highest Step N it finds, else the highest numbered list item, else 3. The result is capped at max_steps.

Pass and fail rules

The Evaluator’s reply is parsed in this order:
  1. Score table rows of the form | criterion | score | threshold | PASS/FAIL |. Each score is compared with the threshold in its own row.
  2. Inline scores such as Clarity: 7/10 or Clarity: 7 out of 10. Each score is compared with the plan’s threshold for that criterion. Plan thresholds come from the Planner’s criteria table, layered over default_thresholds. A criterion with no threshold uses 6.0.
  3. No scores found: an Overall Status: PASS or Overall Status: FAIL line decides. If there is none, the step passes.
Any criterion below its threshold fails the step. On a retry, the Generator receives the Evaluator’s full reply as feedback.

Refine vs. Pivot

When a step fails evaluation, the harness compares the average score of the last two evaluations for that step:
  • Scores improving — REFINE: keep the current direction, fix specific issues
  • Scores declining or stagnant — PIVOT: take a fundamentally different approach
This signal is passed to the Generator alongside the Evaluator’s feedback. It needs two scored evaluations, so it first appears on the second retry.

Evaluation Criteria

The Planner defines domain-appropriate criteria as part of the plan. Each criterion has:

Source Code

View the source code on GitHub