Agent optimize
Skill skillberry-ai/cap-evolve/skills/algorithms/agent-optimize
Fully-agentic, free-form optimization algorithm. Use in agent orchestration mode when you want the conversational agent to own the whole search — understand the benchmark/inputs first, run the baseline, then freely propose capability edits, triage on cheap task subsets, and accept only on a full-val significance gate, all bounded by a free-text stop_condition it re-reads with the run-dir spend. Agent-mode only (orchestration_mode: agent); for a deterministic loop use hill-climb | gepa | skillopt.From its SKILL.md
npx -y skills add skillberry-ai/cap-evolve --skill agent-optimizeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- runs commandsInstructs the agent to run 6 commands, including `cp -r "$R/candidates/$(python -c "from cap_evolve import RunDir;print(RunDir.open('$R').best_id)")" "$R/work/cand_N"` and 5 more.
SKILL.md
7.9 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it
agent-optimize — the free-form loop you own
This is the one algorithm with no deterministic subprocess and no per-iteration
optimizer. You — the conversational agent that ran intake — are the optimizer, the
scheduler, and the stopping rule. cap-evolve run (with orchestration_mode: agent)
does check → baseline, prints a handoff with the run_dir, and returns. From there the
search is yours: what to edit, what to evaluate, when to evaluate it, when to call it
done. Your freedom is bounded by exactly two things — the honesty invariants below
(most of which core enforces whether you cooperate or not) and the project's free-text
stop_condition.
Nothing new lives in core for this. You drive the existing cap-evolve primitives (the
phase scripts + the RunDir API), so events.jsonl / rollouts / results / snapshots stay
populated and the dashboard renders unchanged.
Phase 0 — understand before you optimize
Do this once, before any edit, and ask the user any blocking question here (mirror intake's ask-if-missing discipline) so the loop then runs unattended:
- Read
PROJECT.md,capevolve.yaml, the adapter (adapters/adapter.py), and every file undercapability_path(the seed capability you'll edit). - Understand what one evaluation does: what a task is, what
run_targetproduces, whatscore()rewards, and what the per-task feedback says (that is your learning signal). - Note the val and test sizes,
num_trials,gate_mode/gate_k_se, and the capabilities under optimization (the allowed edit surface, e.g.system-prompt,tools). - Read the free-text
stop_conditionand restate it to yourself as concrete checks (score goal on full val, cost ceilings, time). This is what tells you when to finish.
Agent-mode loop
Everything below runs against the handed-off run_dir (call it $R) and project ($P).
$S is the skills dir ($CAPEVOLVE_SKILLS_DIR). Baseline has already scored the seed on
val and set best_id = seed; read its val mean/stderr from $R/baseline.json.
Each round:
- Read the signal. Look at the current best candidate's per-task val rollouts under
$R/rollouts/val/(and the diagnose skill if you want them clustered) to see which tasks fail and why. This is free — no new evaluation. - Propose ONE coherent edit yourself. Copy the current best into a fresh candidate dir
and edit it (you may consult the
system-prompt/toolscapability skills for guidance, and spawn helper subagents for parallel sub-tasks — but you make the edit):
Every edit must encode a general rule — never hardcode a task's id, gold value, or answer.cp -r "$R/candidates/$(python -c "from cap_evolve import RunDir;print(RunDir.open('$R').best_id)")" "$R/work/cand_N" # …edit $R/work/cand_N/policy/policy.md and/or tools/tools.py … - (Optional) Cheap triage. To decide if an edit is even worth a full-val eval, you may informally sample a subset of tasks. Triage is informational only — it may never be the accept/reject decision (see honesty invariant 1).
- Honest gate on FULL val. Evaluate the candidate on the whole val split — this writes
rollouts+results into the run dir:
Then apply the significance gate against the current best's val mean:python "$S/phases/evaluate/scripts/run.py" --run-dir "$R" --project "$P" \ --candidate "$R/work/cand_N" --split val --n-trials <num_trials>
Accept only if the gate says Δ > k·SE. Also apply no-regression: reject if the candidate breaks any val task the current best passed, even when the mean rises.python "$S/phases/gate/scripts/run.py" --mode paired --k-se <gate_k_se> \ --current <best_mean> --candidate <cand_mean> \ --current-stderr <best_se> --candidate-stderr <cand_se> - Commit the decision through the run dir (so the dashboard +
best_idstay real):
On reject:python - <<'PY' from cap_evolve import RunDir rd = RunDir.open("$R") rd.snapshot("cand_N", "$R/work/cand_N") # persist as a candidate rd.set_best("cand_N") # ACCEPT: make it the new parent rd.log_event("accept", candidate="cand_N", val=<cand_mean>, note="<one-line why>") rd.update_spent(iterations=1) PYlog_event("reject", …)+update_spent(iterations=1)and keep the old best.
See your constraints every few steps
There is no cap-evolve status command — you read what already exists. Every 2–3 rounds,
re-read both:
- the free-text
stop_conditionfromcapevolve.yaml(score goal, cost ceilings, time), and - the run-dir spend:
python -c "from cap_evolve import RunDir; import json; print(json.dumps(RunDir.open('$R').spent.to_dict(), indent=2))"
Compare spend and the latest full-val mean against the stop_condition, then decide:
keep optimizing, or stop and seal. (The Stop hook also re-nudges you across turns so you
keep driving until the run is finalized.)
Stop & seal (exactly once)
Stop when the stop_condition is met (e.g. full-val mean ≥ the score goal) or the budget/
stall is hit. Then seal the held-out test split exactly once and write the report:
python "$S/phases/finalize/scripts/run.py" --run-dir "$R" --project "$P" --n-trials <num_trials>
python "$S/phases/report/scripts/run.py" --run-dir "$R"
(There is no cap-evolve finalize subcommand — the orchestrate/host prose uses that as
shorthand; the real seal is the finalize phase script above, which scores the best on test
once and burns the seal. A second finalize raises TestSealError.) A run with no finalize
has no result.
Honesty invariants (non-negotiable; core enforces most of these)
- Accept/reject and the score-goal check are ALWAYS on FULL val through the gate. Cheap subset triage is informational only and may never gate.
- The test split stays sealed until the single finalize. You never score test during the
loop — the evaluate phase physically restricts
--splittotrain|val; only finalize touches test, once. - Never edit
splits.json, anything underrollouts/test/, or gold/test files (a PreToolUse hook blocks it and core owns the seal). - Generalize, don't overfit — every edit is a general rule, never a task-specific answer.
- Drive through cap-evolve primitives, never around them — every val eval via the
evaluate phase, every accept via
snapshot+set_best+log_event. A round that produced no run-dir artifacts is a bug: fix it before continuing. - Always finish with finalize + report.
What good vs bad looks like
- Good: Phase 0 done and blocking questions asked up front; each accepted candidate has
rollouts + a
set_best/acceptevent; the score goal is confirmed on full val; the run ends with a single sealed-test number — even if the honest answer is "no significant gain". - Bad: gating on a triage subset; accepting a mean gain that regresses a passing task; peeking at test mid-run; declaring success on val without ever finalizing.
References
references/algorithm.md— why free-form + how honesty survives full agent autonomy, with sources.
What ships with it: 6 files
9.8 KB alongside SKILL.md, 4 of them executable
references/
- algorithm.md3.1 KB
scripts/
- abstract.pyruns826 B
- _bootstrap.pyruns1.3 KB
- check.pyruns1.7 KB
- run.pyruns2.2 KB
- meta.yaml623 B
Gives 0 of the 12 instructions most context ai engineering skills give in ~1.9k tokens
Counted across 1,328 of the 2,349 authors here whose files we hold, read 2026-09-06
- Dispatch a fresh subagent for each taskin 76 of 1328, across 59 files
- Perform spec compliance review before code quality reviewin 44 of 1328, across 34 files
- Dispatch a final code reviewer after all tasksin 38 of 1328, across 26 files
- Answer subagent questions before allowing implementationin 36 of 1328, across 26 files
- Use the least powerful model capable of the taskin 33 of 1328, across 26 files
- Create a TodoWrite list for all tasksin 32 of 1328, across 22 files
- Perform a task review after each implementationin 31 of 1328, across 24 files
- Extract all tasks and context from the planin 29 of 1328, across 20 files
- Provide full task text to subagentsin 28 of 1328, across 20 files
- Use git worktrees for isolated workspacesin 25 of 1328, across 20 files
- Specify the model explicitly when dispatching a subagentin 23 of 1328, across 18 files
- Execute all tasks from the plan without stoppingin 21 of 1328, across 16 files
Said here and by no other author read
- ask the user any blocking questions before starting
- check affordability before spending on candidates
- read the per-task pass rate to identify defects
- audit measurements before crediting a failure
- read candidate traces after two rejected rounds
- bundle only independent parts in multi-part edits
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.