| name | explore-exploit |
| description | Use when a task has a large solution space and a measurable quality signal and the goal is to generate many candidates and select the best — naming/branding, UX/UI variants, marketing copy, code optimization, prompt tuning. Triggers: "brainstorm and pick the best", "explore and exploit", "simulated annealing", "tournament of options", "generate N options and rank them", iterate-until-score loops, or /explore-exploit. |
Explore/Exploit Optimizer
Overview
Domain-agnostic search harness: takes a goal, a frozen rubric, and a budget, then orchestrates subagents through hot exploration → clustering → successive-halving tournament → stochastic-beam refinement → Swiss-pod final. Returns top 3 finalists with scores, strengths, weaknesses, and reasoning. Every round is appended to a markdown log before the next round starts.
The pipeline is a hybrid of the 3 winners of a judged 20-metaheuristic search (2026-06-12, see run log): successive halving (8.82/10) is the budget backbone, Gumbel-top-k beam (7.80) is the refinement engine, Swiss pairwise pods (7.90) decide the final order. Classic simulated annealing ranked 14/20 — sequential accept/reject chains waste a parallel-agent substrate; its temperature idea survives as the rung schedule and decaying selection noise.
Inputs — collect ALL before round 0; ask if missing
- Goal — 1–2 sentences: what is being optimized, for whom.
- Rubric — 3–5 weighted criteria with scoring anchors (what a 9 looks like, what a 3 looks like). Freeze before scoring; never change mid-run.
- Hard constraints — numeric/binary only (≤12 chars, must compile, must pass test X, LCP < 2s). Unenforceable adjectives ("short", "clean") must be converted to numbers first.
- Budget — total agent calls (default 60).
- Named competitors/baselines — distinctiveness is only meaningful relative to specific rivals; list them upfront.
Iron Rules
Violating the letter of these rules is violating their spirit.
- Hard constraints eliminate before scoring. A collision or violation is dead, not "6/10".
- One judge prompt, frozen verbatim, used for every candidate in every round. No "fresh judges for the final" — that is score drift with extra steps.
- Never re-score an earlier candidate. A score is frozen at first judgment. When survivors must be compared again, use pairwise ordering pods (relative judgment), never new absolute scores.
- Judge in comparative fields of 5–10. A single candidate scored in isolation lands at ~7/10 and means nothing.
- The orchestrator owns arithmetic and filtering. Weighted sums, dedup, constraint checks, ELO/Borda math happen in plain JS — never trust agent arithmetic.
- Verify external facts on finalists only, with real lookups. Trademarks, domain availability, meanings in es/en/de/fr/pt, benchmarks — fatal on collision, evidence required, vibes forbidden.
- Append the round log to the markdown file BEFORE launching the next round. No log entry → the round didn't happen.
Pipeline
Phase 0 — Contract (no agent calls)
Write to the log: goal, frozen rubric + anchors, hard constraints as numbers, budget split, competitors, candidate JSON schema, and the verbatim judge prompt. This file is the contract; everything later references it.
Default log path: ~/claude.nosync/explore-exploit/<YYYY-MM-DD>-<slug>.md (fall back to ./explore-exploit-runs/ outside that workspace).
Phase 1 — Hot exploration (≈20% of budget)
10–12 parallel generator agents, each locked to a distinct creative lens/persona (diversity beats volume — 8 generators on one prompt produce 8× the same pun). Each emits 6–8 cheap candidates with self-reported constraint fields. Orchestrator JS then dedupes and kills hard-constraint violators for free.
Phase 2 — Cluster (no agent calls, or 1 tagger)
Group survivors into motif/approach families (by shared root word, layout archetype, algorithmic idea). Cap survivors per family per rung so one seductive motif can't flood the field before judging. This is the quality-diversity guard.
Phase 3 — Halving rungs (≈40% of budget)
Repeat until ≤8 alive: judge in comparative fields of 5–10 → keep top 50%.
- Early rungs: cheap proxy rubric (the 1–2 heaviest criteria only).
- Later rungs: full rubric minus verified-risk criteria.
- Per-rung spend stays roughly constant (fewer candidates × deeper evaluation).
- Ensemble 3 judges (median per criterion) once fields are small — judge noise is most decisive exactly where budget is tightest.
Phase 4 — Beam refinement (≈25% of budget, 2–3 rounds)
Beam = Gumbel-top-k over frozen scores: score + τ·(-ln(-ln(u))), τ decaying 2.0 → 0.3 per round (selection randomness needs no logits). Per beam member: 2–3 expander agents with assigned mutation lenses + 1 unconditioned wildcard agent per round as the exploration floor. Judge new candidates only, with frozen beam anchors displayed for calibration. A variant replaces its parent only if it beats it inside the same field. Prompt-level cooling: expander instructions go from "radical reinvention" → "minimal polish".
Phase 5 — Verify + Swiss final (≈15% of budget)
Real verification lookups on ≤6 finalists; collision = dead regardless of rank. Then one round-robin pod: a judge receives all survivors and returns a strict ordering (pairwise, drift-immune); JS expands to pairwise results and aggregates by Borda count. Frozen Phase-3/4 scores break ties.
Phase 6 — Report
Final log section + in-message summary:
- Top 3, each with: weighted score, Borda rank, strengths, weaknesses, reasoning per rubric criterion, verification evidence.
- Ranked table of all finalists.
- Near-misses with cause of death ("great option, fatal trademark collision") — useful when the user vetoes the winner.
- Process stats: candidates generated / survived filter / agent calls used vs budget.
Implementation
Use the Workflow tool (one workflow can run multiple phases; or one workflow per phase with the main loop writing the log between phases). Generic parameterized script: see workflow-template.js in this skill directory.
Two Workflow-runtime gotchas the template handles:
Math.random() throws in workflow scripts — pass a pre-generated noise: [...] array via args for Gumbel noise.
- Workflow scripts have no filesystem — log appends go through a tiny scribe
agent() call per round, or the main loop writes between phase-workflows.
Cost caps. Two layers: the budget input caps agent calls structurally, and a +300k-style token directive in the user prompt becomes a hard ceiling enforced by the Workflow runtime. The template degrades gracefully against that ceiling via budget.remaining() — shedding generators, extra rungs, refine rounds, then verification, in that order, always keeping reserve to reach the Final phase and always logging what was shed. Below ~250k expect a shallow run; an unverified winner is flagged verified: false.
Objective quality signals (benchmarks, test suites, eval runners)
When the signal is deterministic (execution accuracy, benchmark ms, test pass rate), it replaces the LLM judge — it is drift-immune by construction. Adjustments:
- Shift judging budget into generation, error analysis, and mutation; spawn analyst agents on failure transcripts to derive mutation lenses.
- Slice the eval set (e.g. 25%/25%/50% stratified): rungs use the cheap slices, the full set touches only finalists. Running the full eval on every candidate every round overfits the eval — selection IS training.
- Pin determinism (temperature 0, fixed seed) or take median-of-3 on finalists.
- Keep an LLM pairwise pod only as the tie-break among finalists within measurement noise, judging the criteria the runner can't see (maintainability, robustness).
Domain mapping examples
| Domain | Candidates | Cheap rung proxy | Expensive final eval |
|---|
| Naming/branding | names | memorability + fit only | trademark/domain/language lookups |
| UX/UI | design directions | one-line concept critique | coded prototype + design-review rubric |
| Code optimization | patch variants | micro-benchmark | full suite + production-shaped profile |
| Copy/content | drafts | hook strength only | full rubric + fact-check |
Common Mistakes
| Mistake | Reality / Fix |
|---|
| "Fresh judges for the final round, no earlier context" | That's score drift. Same frozen judge prompt; final comparison via pairwise ordering pods. |
| Whole process lives in-message | Unauditable, unrepeatable. Append to the log file every round, before the next round. |
| One-shot exploration, then pure exploitation | Converged pool, local optimum. Wildcard agent every refinement round + Gumbel τ floor. |
| Dedup only, no clustering | One seductive motif floods the field. Cap survivors per family per rung. |
| Scoring candidates in isolation | Everything scores ~7. Fields of 5–10, comparative, always. |
| Hardcoding the domain into the plan | Goal, rubric, lenses, mutation operators are parameters; phases never change. |
| "Brand risk looks fine" without lookups | Verify with real searches on finalists; evidence links in the log; collision = dead. |
| Re-scoring survivors each round "for fairness" | Score drift kills good early candidates. Scores freeze at first judgment. |
| Agent computes weighted totals | LLM arithmetic drifts. Orchestrator JS computes everything. |