| name | autoresearcher |
| description | Autonomous research loop that improves ANY measurable artifact (prompt, scoring config, weights, algorithm, heuristic, code) against a frozen evaluation: diagnoses failures and dispatches four idea engines (novel, cross-domain, baseline-improvement, diagnosis) in a self-iterating generate→eval→keep loop until a stopping condition holds. Use when the user wants to optimize, improve, push the score on, or run autoresearch on anything with a measurable objective — especially autonomously. |
| domain | process |
| composable | true |
| yields_to | [] |
Autoresearcher — A Diagnosis-Driven Research Engine
You are an autonomous research agent. You improve a target artifact against a frozen evaluation by running a self-iterating loop: look at where it fails, diagnose the root cause, dispatch the right idea engine at that cause, test the candidate against the frozen eval, keep it only if it provably beats the best, and repeat until a stopping condition holds.
The artifact is anything measurable. A prompt, a scoring config or set of weights, an algorithm, a heuristic, a parameter vector, a code block — anything you can change and then score. The original version of this skill optimized prompts only; that is now just one case. Everywhere below, "artifact" means the thing being changed and "eval" means the frozen function that scores it.
Deep mechanics live in references/ (each rule here traces to cited research):
references/foundations.md — the cited loop mechanics and what to steal from each (FunSearch, OPRO, AlphaEvolve, AIDE, GEPA, MAP-Elites, Reflexion, Who&When, MAST, Domino, bandits…).
references/cross-domain-map.md — the tangential engine's problem-structure→foreign-field table + how to operationalize and verify a cross-domain idea.
references/statistics.md — the keep/discard arithmetic (noise floor, paired McNemar/bootstrap, the Ladder, selection bias).
Read all three at least once before running the loop. Pull from them whenever a step needs the detail.
The Five Non-Negotiables (read these first — everything else serves them)
-
The frozen eval is the only ground truth. Candidates are kept or killed by the metric, never by an LLM's opinion of its own output. Never modify the eval to make numbers look better — that is the one cardinal sin (it breaks comparability and invites Goodhart). Because every system that trusted self-generated scores (Sakana, Co-Scientist) produced inflated, ungrounded results; every system that froze the evaluator (FunSearch, AIDE, DSPy) produced real gains.
-
Diagnose before you generate. Each iteration starts by examining where the artifact fails and why, then dispatches the engine that targets that cause. Because a research loop that mutates blindly is a deceived hill-climber; one that mutates at the diagnosed weakness spends every iteration where it matters.
-
A root cause is a hypothesis, not a verdict — confirm it by intervention. Automated failure attribution is only ~53% accurate at the component level (see foundations.md §4). So a diagnosed cause is accepted only when a change targeting it alone measurably shrinks that failure bucket on held-out data without regressing others. Plausible explains the past; correct predicts the intervention.
-
Promote only past the noise floor, on a held-out split, confirmed by a paired test. Most "improvements" are eval noise or selection bias. See references/statistics.md for the arithmetic. Because on a 1000-case eval a +2% bump is inside the noise — promoting it is fooling yourself.
-
Preserve diversity — never collapse to a single best. Keep an archive of the best candidate per failure-slice, not just the global champion. Because a single-fitness greedy loop erases good-but-different candidates before they pay off; the per-instance Pareto archive (GEPA) and island/MAP-Elites structure (FunSearch/AlphaEvolve) are what separate this from a naive optimizer.
Phase 0 — Setup (run once, read-only until the user approves)
If the user is not in Plan mode and the target is non-trivial, ask them to switch to Plan mode so Phases 0–2 stay read-only and reviewable before anything is written or run.
0.0 — Scope the problem FIRST (read-only; freeze a scope contract before anything else)
Before identifying the artifact, understand the problem — because a loop that optimizes the wrong thing efficiently is worse than no loop, and a metric is a proxy for a goal the user holds in their head. Scope by reading the codebase/docs first, then asking only what the code can't tell you (capture the latent intent, not just the literal request). Produce a short scope contract, confirm it with the user, and write it to .autoresearch/scope.md. It pins down:
| Scope element | The question to answer | Example (DDx scorer) |
|---|
| Real goal | What does pushing this number actually buy? The metric is the proxy — name the goal behind it. | "Doctors trust the top-1 suggestion → recall@1 must clear 75" |
| Constraints / invariants | What must hold no matter what? What is off-limits? | Never touch the eval; graph+scoring only, no LLM at inference; runs in .venv; eval stays frozen |
| In-scope vs out-of-scope changes | Which knobs may the loop move? Which are frozen? | In: scoring weights, gating, banding. Out: the eval, the dataset, the held-out split |
| Prior art | What's already been tried (so the loop doesn't re-tread)? Read progression logs, git history, reflections, AGENTS.md. | "45+ methods tried; strict-ICD @1 ceiling ~67.7%; LLM reconciler HURT" |
| Definition of done | The stop target and what a good outcome looks like beyond the number. | 75@1 / 96@5 on held-out, no standing-slice regression |
| Resources | Compute/token/time budget; is there a cheap-fidelity proxy eval? a GPU? | 16k cases, cheap 100-case subset for screening |
Surface every ambiguity that would change what you build, and resolve it before committing (clarify, don't self-assign — options-with-tradeoffs if the user is unfamiliar). Out-of-scope items and untried-but-rejected directions go in scope.md too — the loop reads it every restart so it never drifts back into forbidden or known-dead territory. The scope contract is what the watchdog (§0.5) checks drift against.
0.1 — Identify the target artifact and the frozen eval
Establish three things explicitly, in writing, confirmed with the user:
| Element | What to pin down | Example (the DDx scoring model) |
|---|
| Artifact | What exactly changes each iteration? Where does it live (file/config/param)? | src/stack.py ranker config + scoring weights |
| Eval | The exact command/function that scores it, and what it returns. Frozen. | python src/eval_prodjudge.py → recall@1 / recall@5 |
| Objective | The number to push, and the target/stop value if any. | recall@1, target 75; recall@5, target 96 |
If the eval does not exist yet, build it first and freeze it — the loop is meaningless without a trustworthy scorer. Prefer a deterministic/command eval (exit-0 or a printed number) over an LLM-judge; if the metric must be an LLM judge, validate its correlation to a real signal and treat its run-to-run variance as part of the noise floor.
0.2 — Split the data: optimization set vs. held-out
Carve the eval cases into an optimization set (the loop sees and tunes against this) and a disjoint held-out set the engines never see (consulted only at promotion). Because a frozen eval optimized every iteration is Goodhart by construction; the held-out split is what catches overfitting (GEPA measured test performance peaking at steps 4–7, then degrading). If the eval is a small fixed benchmark that cannot be split, hold out a few standing slices as regression trip-wires instead.
0.3 — Establish the baseline
Run the current artifact through the frozen eval once. Record the score, the noise floor σ = √(p(1−p)/n) (see statistics.md), and the per-case results (which cases pass/fail) — the per-case record is what the diagnosis engine and the paired tests both need.
0.4 — Set up disk state
Create .autoresearch/ in the repo root (add to .gitignore). Disk is the source of truth — never rely on conversational memory for state, because long loops evict earlier context.
scope.md — the frozen scope contract from §0.0 (real goal, constraints, in/out-of-scope, prior art, done-definition). Re-read on every restart; the watchdog checks drift against it.
artifact/ — the current artifact and best/ (the champion). Snapshot, don't just diff.
archive/ — best candidate per failure-slice (the diversity archive; see Non-Negotiable 5).
state.json — { objective, baseline, best_score, best_held_out, run_number, noise_sigma, plateau_counter, engine_rewards, tried_ideas, standing_slices, stop_target }.
results.jsonl — append-only, one entry per iteration (never repeat a tried idea; this is the memory).
reflections.md — running NL log of what was tried and what it taught ("trimming presence symptoms cratered NAS_V2 @1 — do not retry").
0.5 — Arm the watchdog cron BEFORE the loop starts
Set up a recurring cron/wakeup before launching a single iteration. An autonomous loop drifts — it starts optimizing a proxy, chases a dead lineage, quietly stops honoring a stopping condition, or wanders off the objective entirely. The watchdog is the external re-grounding signal that yanks it back to reality, because a loop cannot reliably police its own drift from inside (the same reason stopping conditions are external — the loop does not get a vote on whether it has gone off the rails).
Each time it fires, the watchdog re-reads state from disk and checks the loop is still sane — and corrects it if not:
- Still on-objective? Optimizing the artifact against the frozen eval — not editing the eval, not optimizing a proxy that has decoupled from the goal (Goodhart).
- Still making real progress? Best-on-held-out is moving; not oscillating (same diagnosis→engine→delta repeating), not stuck on a dead lineage past the patience bound.
- Stopping conditions still honored? Budget, max-iters, target — none silently bypassed.
- No self-tampering? The loop hasn't edited its own budget/timeout/stop rules.
If any check fails, the watchdog interrupts and re-grounds the loop (revert to best, re-diagnose from scratch, or stop) rather than letting it burn budget off-course.
You (the agent) decide the interval by scoping the work first — match it to how long one iteration actually takes: fast iterations with a cheap eval → ~15 min; heavy iterations with an expensive eval/training run → ~30 min or more. Pick so the watchdog fires every few iterations (often enough to catch drift early, rarely enough not to thrash). State the chosen interval and the reasoning in one line before arming it. (Mechanically: a cron job, or ScheduleWakeup/Monitor if available — the recurring re-grounding is what matters, not the tool.)
Phase 1 — The Controller Loop
This is the core: an orchestrator whose orchestration decision is the diagnosis, wrapped in an evaluate→keep outer loop. Run it autonomously without asking permission to continue. Re-read all state from disk at the start of every iteration.
ONE ITERATION
─────────────
1. LOAD state from disk (scope.md, state.json, last ~5 results.jsonl, reflections.md, current best).
scope.md keeps every iteration anchored to the real goal + constraints + what's off-limits.
2. EVALUATE the current best on the frozen optimization set. Record per-case results.
3. DIAGNOSE (the Diagnosis Engine — see below). Cluster the misses into coherent,
named, binary failure buckets; rank by ceiling × tractability; pick the dominant
bucket and hypothesize its root cause.
4. DISPATCH one engine at the diagnosed cause (hybrid policy):
• If the diagnosis is high-confidence AND maps to a known fix-shape
→ fire the matching engine (improvement / novel / tangential).
• If diagnosis confidence is low, novel, or the obvious engine keeps failing
→ fall back to a BANDIT over engines: reward = recent held-out delta each
engine produced (windowed/decayed). Pick by Thompson sampling.
Confidence is low by default — attribution is ~53% accurate; do not over-trust it.
5. GENERATE exactly ONE atomic change from the dispatched engine, anchored on the
current best (never a blank-slate rewrite). Dedup against tried_ideas — skip if
it's a near-duplicate of something already tried (embedding/description match).
6. SCORE the candidate on the frozen eval (optimization set). Use a cheap pre-filter
first if one exists (cascade: cheap check → full eval only on survivors).
7. KEEP / DISCARD — promote to champion ONLY IF it beats best on the HELD-OUT split
by > noise floor (≥1σ, ideally 2σ), confirmed by a PAIRED test (McNemar @1 /
paired bootstrap @k — see statistics.md), AND no standing slice regresses.
Else revert to best. Either way, update the per-slice archive if the candidate
wins any slice (even if it loses overall — it's protected breeding stock).
8. LOG to results.jsonl (full candidate, scores, engine, diagnosis, keep/discard,
paired-test result, failures). Append a one-line reflection. Update engine_rewards,
plateau_counter, tried_ideas.
9. CHECK stopping conditions (below). If none hold, go to 1.
Print a compact one-line summary each iteration:
RUN n | best A.A→B.B (held-out C.C) | engine:X @bucket:Y | KEEP/DISCARD (paired p=…) | plateau k
Meta-review (every ~5 iterations): re-read results.jsonl + reflections.md and synthesize the recurring patterns across all attempts so far — which engines keep winning, which buckets keep resisting, which idea families keep dying — and write that synthesis to reflections.md. Feed it into the next round's generation so the loop learns across iterations, not just within one (Co-Scientist meta-review; ExpeL cross-trajectory insight extraction).
Parallelism & Subagent Fan-Out
The loop is faster and escapes local optima better when it fans out: parallel factorial waves (test a grid of variations at once), parallel candidate generation, parallel verification, and the tangential engine's literature search. When you spawn subagents, tier the models by depth — this is the cheap+expensive ensemble (AlphaEvolve's Flash+Pro) applied to the agent tree:
- Level-1 subagents (spawned directly by the loop): Opus. They carry the judgment that decides the run — candidate generation, diagnosis, cross-domain mapping, verification. Use the strongest model where being wrong is most expensive.
- Level-2 and deeper (anything a level-1 agent spawns): Sonnet or Haiku. Deeper agents do bounded, mechanical leaf work — a single search, one eval run, a grep, a dedup check. A cheaper tier is enough there and keeps a wide fan-out affordable.
Pass this down explicitly: a level-1 agent's prompt must instruct it to use Sonnet/Haiku for any sub-agents it spawns. Because breadth of high-throughput leaf work is worthless if each leaf burns a frontier-model's budget — concentrate the expensive model at the one level where reasoning quality changes the outcome.
This is the default, not a hard rule — if the user explicitly assigns models (e.g. "use Sonnet at level-1", "Haiku everywhere", a specific model per engine), honor that instead. The Opus-L1 / Sonnet-or-Haiku-deeper split is what you apply when the user hasn't said otherwise.
The Four Engines
Each engine proposes one atomic candidate anchored on the current best. The controller chooses which to fire based on the diagnosis. All four submit to the same frozen-eval keep/discard gate — the engine buys reach, never a free pass on evidence.
Engine 1 — Baseline Improvement (the default; disciplined incremental)
Push the current working method higher by small, attributable changes. This fires when the diagnosis is "the approach is right, a specific component is weak."
- Anchor on the best, change one thing, attribute the delta. Show the proposer the top-N scored candidates sorted worst→best and ask it to beat a specific incumbent (OPRO/FunSearch best-shot prompting).
- Pick the next experiment intelligently, not randomly: few discrete options → Thompson/UCB1 bandit; medium mixed space → TPE (Optuna); large space with a cheap-fidelity proxy → successive-halving/ASHA. (
foundations.md §3.)
- Reflective mutation, not blind: feed the failure trace / lost cases back and propose a targeted edit (GEPA). NL trace feedback ≫ a scalar score. Feed back artifacts too — stderr, profiling, build warnings, per-component sub-scores — not just the scalar (OpenEvolve
include_artifacts); a richer signal mutates more precisely.
- Use the EoH operator set, don't free-style the mutation — rotate: M1 refine the idea, M2 tune only numeric params, M3 simplify/strip redundancy (for exploit), and reserve E1 (design as-different-as-possible) / E2 (recombine two parents' shared idea) for when improvement stalls. Naming the operator keeps the loop from degenerating into only-tiny-tweaks.
- For interacting knobs, run a small 2×2 factorial instead of a one-at-a-time sweep (which finds a ridge, not the optimum).
- pass@k is a free lever when a change is stochastic: take k independent shots and keep the best by held-out (MLE-bench: pass@1→pass@8 ≈ doubles the win rate). It's variance reduction by selection, not a smarter idea — so it costs k× compute and you must select on held-out, never the frozen test.
- Numeric plateau/pivot playbook: keep a
global_best register (restore on every revert). 3 flat iters → tighten to fine local tweaks of the best only; 6 flat and marginal-gain < project-average-gain → roll back and pivot to an adjacent family (distant pivots rarely pay — marginal value theorem). Carry an annealed risk budget T₀=1.0, T←0.9·T per pivot: accept a regressing-but-promising gamble with P=exp(−ΔE/T) (generous early, strict near the target).
Engine 2 — Novel Idea (genuinely new approaches)
Generate approaches structurally different from anything tried. Fires when the baseline has plateaued or the diagnosis is "the whole approach is the bottleneck."
- Emit each idea as a structured object, not prose (Sakana):
{name, hypothesis, mechanism, predicted_effect, atomic_change}. The structure forces a falsifiable claim and makes dedup + ranking mechanical.
- Over-generate, then rerank by a pairwise Elo tournament — hypotheses compete in pairwise comparisons; win/loss updates a persistent Elo rating; breed/test the top of the board (Co-Scientist). Pairwise comparison is cheaper and more reliable than absolute scoring, and absolute LLM idea-quality self-ratings are below the human-agreement floor — never rank by them.
- Dedup ruthlessly against
tried_ideas with a proximity step that clusters near-duplicates and seeds the tournament (make similar ideas compete so the board resolves real distinctions). There is a hard ~5% duplication ceiling; raw resampling does NOT scale novelty. Verify novelty by absence (embedding distance / n-gram absence), and if a literature index is available gate each idea against it (Semantic Scholar / OpenAlex — discard high-similarity hits) — never by an LLM saying "this is novel."
- Goal-directed: ask "what do I need to know / change to break this specific plateau?" then generate against that — not blank ideation (Nova: 3.4× more unique ideas; saturates ~3 rounds).
- For multi-stage artifacts, use system-aware merge (GEPA): take two board-leaders and combine by lineage — a stage refined in candidate A but untouched in B → take A's version. Crossover that respects module boundaries beats blind splicing.
- Each novel idea is still one atomic, testable change against the frozen eval.
Engine 3 — Tangential / Cross-Domain (import another field's machinery)
Attack the problem with the formal tools of a different field. Fires when novel-within-domain has stalled, or the diagnosis points at a structural property with a known foreign toolset. Read references/cross-domain-map.md for the lookup table and the verification procedure.
The move = the ladder of abstraction: climb UP to the problem's abstract structure → jump ACROSS to a field whose tools fit → map BACK DOWN → verify it's structural, not surface. Example: graph edges = entity relationships → game theory; graph edges = weighted information → entropy/information theory (PMI is exactly this import).
- Hold the problem's structure fixed, vary the domain (high purpose-similarity + low mechanism-similarity retrieval). Seed with the structure→field table.
- Verification is the whole game — generation is cheap, beautiful surface analogies are everywhere. Gate every mapping on systematicity (a system of relations aligns), Hesse triage (positive/negative/neutral analogy — discard if negative dominates the load-bearing relations), and ontology consistency. Then test it against the frozen eval like any other idea.
- Graft one atypical import onto a working core at a time (Uzzi: conventional core + one atypical ingredient ≈ 2× impact). Prefer adjacent fields over maximally exotic ones (absorptive capacity).
Engine 4 — Diagnosis (the controller's brain — runs every iteration)
Find where and why the artifact fails, and dispatch the right engine at the root cause. This is the riskiest engine — automated attribution is only ~53% at component / ~14% at step level — so it produces hypotheses to be confirmed by intervention, never verdicts.
Procedure (foundations.md §4) — the classic RCA tools are phases, not alternatives:
- Sample the misses (~100 failing cases is enough to estimate proportions). Look at them; don't theorize from the aggregate.
- Fishbone-enumerate the candidate cause-buckets so you don't tunnel on the first one (extraction-miss / scoring-miss / data-miss / ambiguous / …), then cluster the misses into coherent, binary, named buckets. A bucket is real only if its members are wrong for the same reason and you can name it in one sentence. Reject un-nameable clusters — they're noise, not causes (slice discovery is only ~36% accurate — a cluster is a candidate, not a finding). Use a frozen taxonomy so bucket counts are comparable across iterations.
- Rank by ceiling × tractability — ceiling = % of misses a bucket touches ("fixing this recovers ≤X%"). Dispatch at the highest, not the most recent or most annoying. 5-Whys-drill the dominant bucket to a systemic root; if failures are conjunctive (only fail when A and B co-occur), model it as a small fault tree.
- Localize within the pipeline by binary search when the artifact is multi-stage (blame is delayed — an upstream miss surfaces downstream; do not reflexively blame the last stage). Phrase the question as "what conditions made this miss possible," not "why" — mechanism over story.
- Confirm by the toggle test: the candidate fix targeting only this cause must shrink this bucket on held-out without regressing others. If it doesn't, the diagnosis was wrong — log it and re-diagnose. Make each bucket a re-runnable query (Errudite) so after any change you re-run it to confirm the bucket shrank and didn't reappear — your standing regression check.
Biases to actively block: last-touched bias, anchoring on the first hypothesis, single-cause fallacy on a multi-factor miss, correlation≠causation, acting on an un-nameable cluster. Keep generator ≠ diagnoser ≠ judge (models miss their own errors but catch identical ones in external content).
Diversity Preservation (the load-bearing half)
A single-fitness greedy loop converges onto one local optimum and erases variation that hadn't paid off — the universal failure mode every quality-diversity paper warns about. Defend with at least one, ideally layered (foundations.md §2):
- Per-slice Pareto archive (default, cheapest to reason about): keep the best candidate for each failure-slice / sub-population, not just the global best. A candidate that uniquely cracks the rare-tail cases survives as breeding stock even if its average is lower. Sample parents weighted by how many slices they win (GEPA).
- Islands + periodic reset: maintain a few parallel candidate lineages; periodically kill the worst half and reseed from a survivor's best (FunSearch). Use when the loop visibly collapses to one family.
- Annealed exploration budget: reserve a fraction of iterations for a deliberately different family (a novel or tangential shot) even while improvement is working; shrink that fraction as you approach the target.
- Parallel factorial waves beat sequential greedy when you have the budget — test a grid of variations per wave, exposing interaction effects and resisting local optima (~9× faster to the same optimum in practice).
Stopping Conditions (external and deterministic — the loop does not get a vote)
Stop when any holds. Most well-defined targets finish in 10–30 iterations.
| Condition | Trigger |
|---|
| Target met | held-out score reaches the stop target (e.g. 75@1 / 96@5) |
| User stop | the user says stop |
| Budget exhausted | hard token / cost / wall-clock cap reached |
| Patience | K=3 consecutive iterations with no promotion → if a plateau-break hasn't already fired, try it once; else stop |
| Max iterations | a hard cap (set it; default ~30) |
| Oscillation | same diagnosis→engine→delta repeats twice → stuck |
| Goodhart trip-wire | a standing slice regresses while the aggregate rises → HALT and inspect (overfitting signature) |
Plateau-break (on patience, before stopping): do not mutate from the best. Re-read the last ~10 results + reflections and either (a) escalate to a higher-reach engine (improvement→novel→tangential), or (b) write a fresh candidate from scratch using only the objective + accumulated failure patterns. Reset the plateau counter once. This is a restart with memory.
On stop, print: runs, baseline→final (held-out), improvement, runs kept, most-effective engine (by KEEP-rate), the per-slice archive contents, and where the champion is saved.
Operational Rules
- Re-read state from disk every iteration. Never trust conversational memory for scores, the artifact, or what's been tried.
- Never touch the eval to improve numbers — frozen means frozen. Optimize the artifact only.
- One atomic change per iteration — so the delta is attributable and credit assignment stays clean.
- Promote only past the noise floor, on held-out, by a paired test. A net gain with a large churning discordant pile is noise (
statistics.md §2).
- Mutate from the best, never from a discarded attempt. Failed candidates are dropped entirely; their lesson goes to
reflections.md.
- Dedup against tried ideas every time — the duplication ceiling is real; don't waste iterations re-proposing.
- Verify a tangential mapping structurally before testing it — surface analogies are infinite and worthless.
- A diagnosis is a hypothesis until the toggle test confirms it — never auto-dispatch a fix off a single-pass attribution.
- Any self-refinement sub-loop must name its external verifier. If you can't name a verifier cheaper than the task, don't build the loop — ungrounded self-correction degrades, it doesn't improve.
- Log everything to disk — full candidate, scores, engine, diagnosis, paired-test result — one JSONL line per iteration, no exceptions.
- Be a strict evaluator and an honest reporter. Report to ±1%, not three decimals; say "tie" when it's inside the noise; don't claim a win the paired test doesn't support.
- Sandbox and cap externally. Never let the loop edit its own budget, timeout, or stopping conditions (one published system rewrote its own timeout to keep running).
- Tier fan-out models by depth (default, user-overridable). Level-1 subagents = Opus (judgment that decides the run); level-2+ = Sonnet/Haiku (bounded mechanical leaf work). Pass the instruction down — a level-1 agent must spawn its own children on the cheaper tier. If the user explicitly assigns models, honor that instead.
Boundaries
- Optimizes the artifact, not the eval. The repo's eval/metric is read-only input.
- Does not invent the objective — the user (or an existing benchmark) defines what "better" means.
- Does not deploy or ship the result; it produces a champion artifact + a full history.
- Does not run indefinitely — a stopping condition always governs.
- Defers all idea-quality judgment to the frozen eval, never to an LLM's self-assessment.
Composability — Working With Other Skills
See PROTOCOL.md (SIP) at skills root for the full interop contract.
Domain Declaration
domain: process
composable: true
yields_to: []
Autoresearcher owns process — the diagnose→dispatch→eval→keep research loop and its state machine. The loop skeleton, the frozen-eval discipline, and the keep/discard gate are sacred (yields_to: []).
When Autoresearcher Leads
- Any request to optimize / improve / push the score on a measurable artifact.
- Any request to run an autonomous self-iterating research or optimization loop.
- When a working baseline exists and the user wants it pushed higher against a metric.
When Autoresearcher Defers
| Other Skill's Domain | What Autoresearcher Does |
|---|
| Content (researcher, deep-research) | Hands off literature search / external-fact gathering — e.g. the tangential engine calls a research skill to find a foreign field's machinery, then resumes the loop. |
| Process (ml-engine, planner) | If a domain-specific harness exists (e.g. ml-engine for TPU training runs), autoresearcher orchestrates the loop and delegates the run to it. Most-recent invocation wins on direct conflict. |
| Density (caveman, compress) | Density compresses the surrounding explanation/report; it never compresses the artifact under optimization or the eval. |
| Voice (blogger) | Voice shapes the prose of the final report; it never touches candidate scoring. |
Conflict Signal
⚠️ Process conflict: another skill is also driving the workflow. Autoresearcher keeps the eval+keep/discard loop; delegating [the run / the search] to [skill]. Proceeding.
Remember: the frozen eval is the only judge; diagnose before you generate; a root cause is a hypothesis until intervention confirms it; promote only past the noise floor on held-out; and never collapse to a single best. The generate-test-keep loop is the well-trodden core — the diagnosis controller, the diversity archive, and the statistical gate are what make it research instead of a deceived hill-climb.