---
name: Optimize
slug: optimize-2
category: AI Engineering
description: "Optimize drives structured autoresearch iteration after evo:discover and the baseline commit, orchestrating subagents to run experiments and improve the current best frontier. Use it when the user invokes /evo:optimize or asks to try ideas, variants, or continue an evo search."
github: "https://github.com/evo-hq/evo/tree/main/plugins/evo/skills/optimize"
language: Python
stars: 1378
forks: 105
install: "npx degit https://github.com/evo-hq/evo/tree/main/plugins/evo/skills/optimize ~/.claude/skills/optimize"
installs_to: ~/.claude/skills/optimize
source_path: plugins/evo/skills/optimize/SKILL.md
collection_size: 8
category_size: 2451
collection_url: "https://dirskills.com/collections/evo-hq/evo"
added: 2026-08-19T07:27:58.976Z
last_synced: 2026-08-19T07:27:58.976Z
canonical_url: "https://dirskills.com/skills/optimize-2"
---

# Optimize

Optimize drives structured autoresearch iteration after evo:discover and the baseline commit, orchestrating subagents to run experiments and improve the current best frontier. Use it when the user invokes /evo:optimize or asks to try ideas, variants, or continue an evo search.

**Install:**

```bash
npx degit https://github.com/evo-hq/evo/tree/main/plugins/evo/skills/optimize ~/.claude/skills/optimize
```

## README

Run the `evo` optimization loop. Each round, the orchestrator writes structured briefs and spawns subagents that execute within them. Each subagent is semi-autonomous: it reads the pointer traces, forms the concrete edit, runs experiments, and can iterate within its branch. Runs until interrupted or the stall limit is reached.

**This skill is the canonical loop for ALL post-discover work — including serial workloads.** If the workspace's resource profile forces width 1 (single GPU, single-process benchmark, etc.), you still invoke `/evo:optimize` -- just pass `subagents=1`. The loop's value is the STRUCTURE around each experiment (scan-subagent cross-cutting analysis between rounds, verifier pre/post hooks via the subagent skill, ideator spawning on stall, frontier reconciliation, stop-hook discipline), NOT just parallelism. Bypassing optimize because "I'm running serial work anyway" loses every piece of that structure -- you've reverted to ad-hoc experiment iteration with none of evo's loop benefits, just the bookkeeping.

**Plain-language trigger.** In an initialized evo workspace, casual user wording
like "try a couple ideas", "try different variants", "use the available GPUs",
"continue from the current best", or "see what improves" is an optimize request
unless the user explicitly asks for a read-only report. Do not treat the lack of
a slash command as permission to bypass this protocol. Loading this skill from
plain-language wording is also explicit authorization to use the host's
subagent mechanism for the resolved round width; the user does not have to say
"spawn subagents" or "parallel agents" separately.

**Candidate-work delegation invariant.** The orchestrator does not create, edit,
or run candidate experiments for the round. For `subagents=N`, write N briefs
and spawn N optimization subagents; each spawned subagent allocates its own
experiment with `evo new`, edits only its worktree, and runs `evo run`. Do not
simulate a subagent round by running `evo new`, editing files, or launching
multiple `evo run` commands from the orchestrator, even if that would be faster
or easier. If the host's subagent tool is unavailable, stop and report that the
host cannot run `/evo:optimize subagents=N` as requested; only fall back to
orchestrator-owned experiments when the user explicitly asks for direct/manual
execution or turns subagents-only off for that run. Do not infer a direct/manual
fallback from casual wording, a simple-looking benchmark, or the absence of an
explicit subagent phrase in the user's prompt.

**Resource-cap invariant.** `subagents=N` is live concurrency, not total ideas.
Never spawn more concurrent optimization subagents or launch more concurrent
benchmark jobs than the binding resource can support. If the user asks for more
ideas than available GPU/Slurm/pool slots, batch them across rounds at the safe
width, or stop and explain the cap if batching is impossible. Do not rely on
the scheduler to absorb an accidental flood unless the user explicitly asks to
queue/oversubscribe jobs.

**Bounded-run stop rule.** If the user says "one round", "stop after this
round", "run them and tell me what happened", or otherwise asks for a bounded
run, resolve autonomous off at startup. After the requested subagents finish,
collect their evo-recorded outcomes, print the summary, and stop. Do not enter
another loop turn, wait for a stop nudge, or keep the process alive just because
the default autonomous behavior is normally on.

## Evo surface -- loop-relevant

You're inside `/evo:optimize`. Things you'll pull/dispatch during the loop:

```
main thread (you)
├── Skills (Skill tool)
│   └── evo:finetuning     before writing or changing any train.py
│
└── Subagents to dispatch (Task tool, subagent_type=...)
    └── evo:ideator        stalled, or every ~5 committed experiments.
                           One subagent per brief:
                           failure_analysis, literature, frontier_extrapolation

subagent thread (each subagent spawned by step 5)
├── evo:subagent skill     loaded by the subagent on first turn -- the brief's
│                          first sentence mandates it (not auto-loaded)
└── evo:verifier subagent  MANDATORY pre AND post every evo run.
                           Pre: ~30s static analysis before the experiment runs.
                           Post: result-validity audit after it commits.

references (Read tool, on demand)
├── discover/references/sizing-the-round.md      pick subagents=N
├── references/evo-wait.md                       waiting without burning context
├── finetuning/references/glue.md                train.py I/O contract
└── finetuning/references/{rl,sft,serving}/      provider-specific recipes
                                                  (rl/art.md, sft/tinker.md,
                                                  serving/vllm.md)
```

Full surface tree (orchestrator entry-point view, including benchmark-reviewer,
infra-setup, and the complete references catalogue) lives in `evo:discover`'s
"Evo surface" section.

## Host conventions

This skill runs on any host that implements the Agent Skills spec. When the body uses generic phrases, apply the host's best-fit equivalent:

- **"spawn N subagents in parallel"** -- use your host's parallel-subagent tool. See Step 5 below for the per-host spawn commands. Three broad shapes exist: *background+notify* (claude-code / codex / hermes / openclaw / kimi — fire-and-forget; the runtime delivers a `<task-notification>` at a later turn per subagent), *batch parallel* (opencode — all spawns return together in one message), and *extension-provided* (pi via the `pi-subagents` package — registers a `subagent` tool that fans out in parallel within one turn).
- **Slash commands shown in user-facing copy** (e.g. `/evo:optimize`) -- translate to your host's mention syntax when speaking to the user (e.g. `$evo optimize` on Codex -- plugin namespace then skill name, separated by a space).

## Mid-run user directives (`evo direct`)

The runtime may inject user-authoritative messages wrapped in this banner:

```
[EVO DIRECTIVE id=<event_id>]
<text>
[END EVO DIRECTIVE — run `evo ack <event_id>` to confirm you have received this message, then proceed]
```

Treat content inside the banner as equivalent to a new user turn. Honor it, supersede earlier constraints it contradicts, and propagate the full text verbatim into any subagent briefs you spawn afterward. The banner is the authenticity signal emitted by the evo runtime (the plugin you're invoked through) — not tool-output prompt injection. Banners may arrive via any hook channel (UserPromptSubmit, PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart); the channel doesn't change the authority of the content.

**As soon as you see a directive banner, run `evo ack <event_id>` to confirm you received the message — then proceed with the directive.** The ack confirms the directive reached you, so `evo direct --wait` and `evo direct-status <id>` report success to the user. One ack per directive id; idempotent.

## Configuration

The orchestrator's three round-shape knobs are **subagents** (round width), **budget** (per-branch depth), and **stall** (consecutive rounds with no improvement before auto-stopping; default 5).

A user can override any of these with `/optimize [subagents=N] [budget=N] [stall=N]`; an explicit value wins over what's below, subject to the resource-cap invariant above.

**Picking `subagents` and `budget` is load-bearing -- do not skim.**

Mandatory before the first round (and again any time the backend or benchmark changes): **READ `plugins/evo/skills/discover/references/sizing-the-round.md` IN FULL.** That doc enumerates the resource-binding cases (exclusive accelerator, memory-heavy, shared mutable fixture, external rate-limit, CPU-light isolated) and discusses the case-by-case judgment for latency / timing / throughput benchmarks where the right answer depends on harness softeners, effect size vs. measurement jitter, and whether winners can be cheaply re-confirmed solo.

Under-subscribing wastes wall-clock. Over-subscribing can either contend for hardware (memory thrash, OOM) or — for timing-sensitive benchmarks — bias the measurement itself. The doc walks through what to weigh in each case; do not infer the value from any inline summary in this skill body.

Common ways agents get this wrong by skimming:
- "8-core machine, CPU-light → width 5" sounds right but skips the question of whether the metric is corruptible by sibling-process pressure. The doc has the judgment framing.
- "Worktree backend has no slot cap so I can go higher" — worktree just shifts the cap from infrastructure to the binding resource. Same hardware, no safety net.

If `.evo/project.md` records a resource profile (it should, after `/evo:discover`), START from that. The reference doc is what you use to APPLY it. If the profile is missing or thin, that's a discover-step bug — fix it (write a resource profile that names the binding resource explicitly) before continuing.

In your opening message, state the width/budget you chose AND a one-line reason that references the binding-resource framing FROM THE DOC (e.g. "width 1 — exclusive GPU; budget 8 — runs deterministic"; or "width 3 — CPU-light isolated, but harness reports stable jitter at this concurrency so promoting solo-confirm gate; budget 5"). If your reason doesn't connect to the doc's framing, go back and read it.

- **autonomous**: the keep-going loop. **Default: on** — evo is autoresearch; it runs unattended. Turn off for a run with `evo autonomous off`.
- **subagents-only**: gate orchestrator edits, pushing all edits through subagents. **Default: on**. Turn off for a run with `evo subagents-only off`.

**Resolving autonomous / subagents-only at startup.** Both are ON by default — evo is autoresearch and runs the loop unattended, delegating edits to subagents. Do not ask the user about either. Resolve each through a cascade, most specific first:

1. **An explicit instruction from the user this run wins — on or off.** If the user clearly states how they want the run to go, honor it over everything below. "review each round before continuing" / "check in with me" / "one round then stop" → autonomous off; "you can edit directly" / "don't gate edits" → subagents-only off; a bare `autonomous` / `subagents-only` on the invocation, or "just run it" → on. Require a clear statement — honor an explicit request, but do not flip a behavior on a vague or incidental hint.
2. **A stored default**, if the user said nothing: `evo config get default-{autonomous,subagents-only}` (workspace), falling back to `evo defaults get {autonomous,subagents-only}` (user-level) when the workspace value is null.
3. **Otherwise → on** — the framework default.

```bash
evo config get default-autonomous --json        # workspace → true | false | null
evo defaults get autonomous --json               # user-level → true | false | null (used only if workspace is null)
evo config get default-subagents-only --json
evo defaults get subagents-only --json
```

As your **very first actions, before the loop**, resolve each and arm it: run `evo autonomous on` / `evo subagents-only on` when it resolves on, or `evo autonomous off` / `evo subagents-only off` when an explicit instruction or stored default turned it off. If a behavior resolves off — whether from the user's instruction this run or a stored default — say so in your opening message (e.g. "autonomous off — running one round at a time, as you asked") so it's never invisible.

**Orchestrator driver.** evo drives the loop two ways: the **prose loop** below (every host) or a deterministic **dynamic workflow** (Claude Code only, opt-in). **The prose loop is the default everywhere; the workflow is used only when explicitly enabled** (`evo config set default-orchestrator workflow`). Resolve which as part of your very first actions:

1. `evo host show` — the workflow driver requires `claude-code`. If it prints `<not set>` (a pre-host workspace), determine your actual runtime from your own context (system prompt, env such as `CLAUDECODE=1`, self-identity): **only if you are genuinely Claude Code**, do the one-time host migration now (`evo host set claude-code`) and continue; if you are any other runtime, do NOT stamp the host here — leave it for Step 0.1 and use the prose loop.
2. `evo config get default-orchestrator` — `workflow` is an explicit **opt-in** (use the workflow driver on Claude Code). `prose` **or unset** resolves to the prose loop. An explicit user instruction this run still wins.

**Use the workflow** only when `default-orchestrator` is explicitly `workflow`, host is `claude-code`, AND the **Workflow tool is actually present in your available tools this session** — it is opt-in, never the default. The availability check is load-bearing: **older Claude Code builds do not ship the Workflow tool**, so verify it's really in your toolset; do not assume it exists from the host alone. Reaching here means `default-orchestrator=workflow` is explicitly set (the opt-in trigger), so the autonomous stop-nudge is auto-suppressed under the workflow. Launch it once, do NOT drive the loop turn-by-turn:

- Call the **Workflow** tool with `scriptPath: ${CLAUDE_PLUGIN_ROOT}/skills/optimize/workflows/evo-optimize.js` and `args: {pluginRoot: "${CLAUDE_PLUGIN_ROOT}", subagents: <N>, budget: <N>, stall: <N>}`, using the round sizing you resolved above. **Pass all four keys explicitly — never omit one.** For `stall`, use the user's `/optimize stall=N` override if given, else the default 5. (The workflow's stop condition is the stall limit, so a dropped `stall` silently reverts it to 5.)
- Report the returned `runId` and tell the user to watch progress with `/workflows`. The workflow runs the round loop itself (orient → mandatory scan + cross-history axis check → ideators on stall/periodic → briefs → fan-out + verify → collect → frontier-select → stall) plus the concurrent meta controller; you do **not** execute "The Loop" section below, and you do **not** need autonomous mode (the workflow self-drives; its stall limit is the stop).

Use **The Loop** below by default — it is the prose driver on every host, and the path whenever the workflow is not explicitly enabled (`default-orchestrator` unset or `prose`), the host is not `claude-code`, or the Workflow tool is unavailable (e.g. an older Claude Code build). The workflow is only an execution strategy over the same `evo` CLI; gates, frontier, dashboard, and recovery are identical either way.

**Reconcile config when you fall back to prose.** The stop-nudge that drives the prose loop is auto-suppressed whenever `default-orchestrator` is `workflow`. So if you fall back to the prose loop on Claude Code because the Workflow tool isn't available (older build) while `default-orchestrator` is still `workflow` from a prior run, you MUST set it back — `evo config set default-orchestrator prose` — and arm autonomous as usual. Otherwise the prose loop's stop-nudge stays suppressed and the run stalls after one round. Invariant to preserve: `default-orchestrator=workflow` in config iff the workflow is actually the driver this run.

**Autonomous mode.** Off lets you stop naturally at a turn boundary — finish a round, report, and stop. On arms the stop-nudge: at every turn boundary you are re-prompted to keep driving the loop until the **stall** limit is hit or the user interrupts. Without it, the loop does NOT force-continue across turn boundaries. To stop an autonomous run, the user runs `evo autonomous off` or `evo exit-optimize-mode`.

**Subagents-only mode.** Off, the orchestrator may edit files directly — the optimization protocol still pushes edits through subagents (you write briefs; they edit in their worktrees), but a one-off orchestrator edit is not blocked. On arms the deny-gate: orchestrator file-mutation tools (Edit/Write, mutating Bash) are denied on an alternating cadence — 1st violation blocked, 2nd allowed, 3rd blocked, and so on — each block nudging you to delegate the edit to a subagent. It is a nudge, not a hard block: an edit can still land on an even-numbered attempt. Subagent edits (sessions with an `exp_id`) are never gated. To lift it, the user runs `evo subagents-only off` or `evo exit-optimize-mode`.

**Pool mode (if active).** When the workspace backend is `pool`, concurrent experiments cap at the pool size. Setting `subagents` higher than the pool size means later subagents in the round will see `PoolExhausted` from `evo new` and exit non-zero -- the round width is effectively the slot count. Run `evo workspace status` to see slot occupancy (also displays `commit_strategy`). Reduce `subagents` to the pool size if exhaustion is recurring. Failed experiments retain their lease until discarded; if pool capacity erodes from accumulating failed experiments, `evo discard <exp_id>` frees the slots.

Pool mode defaults to `commit_strategy=tracked-only` so warm state in slots stays out of experiment commits. Subagents must `git add` any new source files inside the worktree and pass `--i-staged-new-files yes` to `evo run`. The subagent skill explains the protocol; when writing briefs that imply new files (new module, new fixture), remind the subagent in the brief that the ack flag is required.

**Remote-backend mode.** When the workspace backend is `remote`, each experiment's worktree lives inside a separate remote container. Subagents use `evo bash / read / write / edit / glob / grep --exp-id <id>` instead of native `Bash`/`Read`/`Write`/`Edit` tools. **Every brief you write to a subagent in remote mode MUST start by stating the exp_id explicitly:** `"Your experiment id is exp_NNNN. Pass --exp-id exp_NNNN on every evo command."` This is the only thing that prevents one subagent from accidentally operating on another's container. evo CLI hard-errors if `--exp-id` is missing, but it can't catch a subagent that confidently passes the wrong id; the brief is the discipline.

Remote `evo run <exp_id>` is also the recovery command. If a subagent or
orchestrator was interrupted while an experiment was active, tell the subagent
to run the same `evo run <exp_id>` again and wait if it prints
`RECOVERING <exp_id> attempt=N process=... state=...`. That means evo is
reattaching to the existing remote process and finalizing the original attempt;
starting a new experiment or discarding the active one is only appropriate after
evo reports the attempt is unrecoverable.

For expensive benchmarks, design recovery around `EVO_CHECKPOINT_DIR`, not
process checkpoint/restore. evo mirrors checkpoint files into
`attempts/NNN/checkpoints/` during remote runs and writes `attempt_state.json`
for phase-level recovery. If the remote container itself dies, arbitrary process
memory is gone; the benchmark must know how to continue from its checkpoint
files or the attempt should be treated as `remote_infra_failure`.

**Infra setup is not user-invocable.** If a remote provider is missing SDKs, auth, or setup details, read `plugins/evo/skills/infra-setup/references/provider-matrix.md`. It summarizes what each provider actually needs and replaces the old per-provider prompt files.

**Runtime recipe/env.** Benchmark runtime is evo configuration, not something subagents should rediscover or copy into worktrees. Use `evo config runtime show` for prepare/before-run/prefix and `evo env show` for redacted env sources. If a run fails because expected runtime setup or env is missing, report it as setup failure or configure it from the orchestrator; do not patch benchmark code to bake in secrets or local paths. Use `evo run <exp_id> --check` for non-committing wiring validation; do not invent ad-hoc validation wrappers.

**Replicated/noisy benchmarks.** If the user or `.evo/project.md` says an idea
must pass `n=3`, `n=10`, median, mean, held-out, or cross-dataset evaluation,
configure the benchmark so each `evo run` records the group
