Overview
ThePlannerGeneratorEvaluator 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:
- Planning: Planner expands a short prompt into an ambitious plan with steps and evaluation criteria
- Contract Negotiation: Generator proposes what “done” looks like for each step; Evaluator reviews
- Execution: Generator produces concrete output and self-assesses before handoff
- Evaluation: Evaluator scores output per-criterion with hard thresholds — any criterion below its threshold fails the step
- Feedback Loop: On failure, Generator receives scores + trajectory signal (refine or pivot) and retries
- 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 attemptstr
default:"os.getcwd()"
Directory where output is produced. Created if it does not exist
Path for the shared state file. Defaults to
{working_directory}/pge_shared_state_{id}.mdDict[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 itAgent
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 itAgent
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 itMethods
run()
Execute the full PGE harness pipeline from a short prompt to completed output.task(str): A short natural-language description of the desired task
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.tasks(List[str]): List of task prompts to process
get_harness_result()
Return the current state of the harness as a dictionary.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().
task(str): A short natural-language description of the desired task*args,**kwargs: Forwarded torun()
run()
Return Types
The PGE harness produces three structured return types that are also re-exported fromswarms.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 anapproved 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.
to_dict() method. EvaluationReport.to_dict() leaves out raw_evaluation.
HarnessResult
Final result container — populated afterrun() 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’samendments, 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 highestStep 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:- Score table rows of the form
| criterion | score | threshold | PASS/FAIL |. Each score is compared with the threshold in its own row. - Inline scores such as
Clarity: 7/10orClarity: 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 overdefault_thresholds. A criterion with no threshold uses6.0. - No scores found: an
Overall Status: PASSorOverall Status: FAILline decides. If there is none, the step passes.
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