running-series
Runs and reads AQVEN series without making the owner the monitor: probes and a dev smoke first, fixed size, a background wait, the 90% spend pause, 429 and infra errors by rule. Use first when startin
Files13
View on GitHubSKILL.mdpackages/aqven/src/aqven/agent_plugin/skills/running-series/SKILL.md
GitHubMUST
- Never claim anything from a provisional verdict or from n=1. Statuses are
running,awaiting_approval,waiting_human,done,failed,cancelled;invalidis a verdict, not a status (verdicts:confirmed,refuted,inconclusive,invalid,signal). - A pause at 90% of the cap (
pause.reason: spend_near_cap) and a start above the project cap (cap_above_project) are decided by a person in Studio. Report the spend and wait: never cancel, never cut repeats, cases or variants, never raiseresearch.spend_cap_usdto get past it. research.spend_cap_usdinaqven.yamlchanges only to a number the owner named, followed byaqven check.- The engine handles 429: the model's lane pauses and halves its parallel calls, and an attempt that ended on a
rate limit runs once more at the end of the series. Never cancel over 429, never lower
rpm. - Follow a smoke to its end in the same turn. An infrastructure error, or a variant three times slower than the rest, stops the launch until it is fixed, the variant is dropped, or the owner decides.
- Wait in the background, unpiped: never
| head,| tail,sleeploops,curlor REST calls to the server. - While a series runs, change no file in the package: an edit to its subject, experiment, dataset, code or a
shared type ends it
invalidwithinputs_changed; downloads unpack outside the package (building-datasets). Cancel only a series the owner asked you to cancel.
Procedure
| # | Step | Exit criterion |
|---|---|---|
| 1 | Preconditions: aqven_check clean; every new agent passed models check --live (choosing-models); a smoke of the same experiment on dev with --cases 1 --repeats 1, or --cases 10 for a new output contract (the first ten dev cases in file order: make sure they vary). This smoke on the real node is the probe of record. Follow it to the end with series_get and wait_seconds; collect every distinct error per variant, fix them in one batch, rerun once |
no NOT_RUNNABLE (it lists problems[] per case and variant before any model call), no MODEL_FEATURE_UNSUPPORTED; zero infrastructure errors; every variant finished an attempt; latency outliers named |
| 2 | series_list {experiment_id} first: a series of this experiment still running, or one already done that answers the question, is read, not paid again. Size, controls and --cap decided before the start; the design is not cut to fit the cap. Many variants: screen, then confirm (designing-experiments) |
no design questions after the start; no series paid twice |
| 3 | Before holdout: one line to the owner (claim, why now, what each verdict means); the last dev series of this experiment had infra_error_rate below 5% |
the owner knows why holdout is spent |
| 4 | Start in the background, unpiped (Claude: Bash with run_in_background: true): uv run aqven series <experiment_id> --path <package> --on dev, adding --on holdout, --cases N, --repeats R, --cap USD when needed. The first line appears within seconds; read it once: series <series_id> started on dev: N attempts (… cases × … repeats × … variants), cap $X, status running; a next line below the recommended … means too few cases. Progress lines follow: done/total attempts, $spent of $cap, status … |
series_id known; a shortage of cases passed on to the owner |
| 5 | First snapshot after the probe attempt (a series runs one attempt first, then up to 8 at once): MCP series_get with {series_id, view: "summary", wait_seconds: 50}. Per variant in variant_briefs: finished, passed, failed, errors, running, p50/p95 latency, the primary metric with its interval, and the top 3 failure groups (an error code or check:<id>) with one example each. The snapshot is clean only when every variant has at least one finished attempt. For a variant with failures: series_outputs {series_id, variant, outcome: "error"} (or "failed") gives every row's error_code and run_id; never .aqven/. A variant where every attempt failed, or infrastructure errors other than 429 above 5% → series_cancel and debugging-runs; swapping an owner's model needs the owner's yes. A median latency three times the other variants' → tell the owner, smokes included |
the owner does not find the errors first |
| 6 | One line to the owner: "series <series_id> runs in the background, I continue when it ends", with its Studio page /research/series/<series_id> on the project server; end the turn. The end of the background command wakes you |
the turn does not hang on polling |
| 7 | Exit code of the background command: 0 done; 1 cancelled or failed, or the project server could not start; 2 refused (NOT_FOUND, NOT_RUNNABLE, INPUT_INVALID, REQUEST_INVALID); 3 awaits approval; 4 waits for a person at a human node; 5 the CLI lost the project server after 300 s of retries (meanwhile it prints lost contact with the project server (…), retrying in …): the series keeps running there, so series_get before any restart |
the branch chosen by the code |
| 8 | Code 3: report pause.reason, pause.spent_usd, the cap, the attempts left and the link; wait. When the owner has continued it and tells you, follow it with series_get and wait_seconds: 50 |
the owner knows what to decide and where |
| 9 | A series started over MCP or in Studio has no background command: follow it with series_get and wait_seconds: 50, never sleep |
the same discipline |
| 10 | Stuck: two snapshots in a row without growth of progress.done while running, and no lane pause line (… rate-limited — pausing …, parallel 8→4) in the console → run_list {series_id, status: "running", view: "compact"} names the hanging attempts, then run_get_node: an attempt hanging at the provider with no error; the engine cuts it only after 600 s of stream silence (MODEL_STREAM_STALLED) or at the agent's limits.seconds |
the hanging variant named to the owner |
| 11 | done: quote verdict.text as it is; the conclusion rests on rows, not only on aggregates: series_outputs {series_id, split: "dev", fields: [<pointer>, <node id>]} shows what each variant answered, with checks per row. divergent: true on a case row of include_cases: the variants' pass rates on that case differ (for example 3 of 3 repeats against 1 of 3); always false with one variant. Open 5 to 10 lost and won cases with their inputs before the report (reporting-results); a failed attempt counts against every binary check; spend.usd is a lower bound when spend.unpriced_attempts > 0 |
the conclusion rests on rows |
| 12 | invalid with infra_errors: fix the cause (fallback_models, an aggregator's upstream fallbacks, join, on_rate_limit) and run again with the same threshold |
the threshold never moved |
| 13 | Journal and report with reporting-results; go on with the work |
the owner never has to ping |
include_cases returns dev rows only, failing first, case_limit a page (50 by default, up to 200; pass
next_cursor as cursor), the rest counted in hidden_cases. series_outputs and aqven series export return
held-out attempts too: filter split: "dev" (--split dev) for anything that informs a change; held-out outputs
enter a report only as aggregates. A counted failure is a failed check, a broken output type after
retries (MODEL_RETRIES_EXHAUSTED, MODEL_SCHEMA_MISMATCH, OUTPUT_SCHEMA_REJECTED), truncation or a refusal;
a missing key, a provider error, a timeout, MODEL_STREAM_STALLED or MODEL_FEATURE_UNSUPPORTED is an
infrastructure error and stays out of the metrics.
| Verdict (reason) | What to do |
|---|---|
confirmed |
apply the change, keep its cases as regression cases, record the decision |
refuted |
drop the change or form a new hypothesis; never read it as "no risk" |
inconclusive (below_mde) |
fresh cases and a new holdout series of the recommended size; never rerun for another answer |
inconclusive (uninformative, no_discordance) |
the cases are too easy or too hard; write cases at the boundary |
signal (dev_split, judge_not_validated) |
keep exploring, or validate the judge first |
invalid (cancelled, budget_cut, inputs_changed, infra_errors, no_data) |
fix the cause, run again |
Pitfalls
| What goes wrong | Do instead |
|---|---|
A home-made curl loop over the REST API breaks on the response body and waits for a status that never comes (invalid is a verdict, not a status) |
series_get, the statuses above |
sleep loops and long timeouts hold the turn and flood the owner with polling calls to approve |
the background command and one line |
| The owner finds a failing variant or a slow model before the agent does | step 5 on the first snapshot |
| The owner reported a smoke's errors four times, because the turn ended after each start and each fix | follow the smoke to its end; fix every error it shows in one batch |
| A smoke showed one timeout, the full series started anyway, and a quarter of that variant's attempts timed out | an infrastructure error in the smoke stops the launch |
Series output piped through tail, so nothing showed until the end and the owner asked whether requests went out |
unpiped; the start line, then progress lines |
A polling sleep on the output file was blocked by the host |
read the start line once; the end of the command wakes you |
include_cases on twenty variants overflowed the tool answer |
view: "summary" first, fields for the metrics you need; case rows with case_limit, or series_outputs, only for a failing variant |
run_get called once per attempt to read what a series answered |
series_outputs pages of up to 200 rows, or aqven series export |
Held-out outputs read case by case through series_outputs, then a prompt tuned to them |
split: "dev"; held-out rows only as aggregates |
| A turn ends after a start without a word, and the owner has to ask what is going on | step 6 |
| Repeats, cases or variants cut, or one series split in two, to stay under the approval line; a comparison postponed over spend | the design stays; report and wait |
| The cap key guessed, or looked up on the web | research.spend_cap_usd, only the owner's number |
A variant hangs at one provider and the delay is blamed on rpm |
step 10 |
A holdout series ends invalid on 429: a model has nowhere else to go and a parallel node needs every branch (join: all) |
fallback_models, an aggregator's upstream fallbacks, join: quorum where a missing branch is acceptable |
A shared type or check edited while a series runs makes it invalid with inputs_changed |
no edits while it runs |
| An archive unpacked into the package during a series | raw downloads outside the package (building-datasets): media no longer stall the server (ADR-0059), but spec files in a drop (.yaml, .yml, .md, .liquid, .py) still re-check the project; after exit 5, series_get before any restart |
Tools and commands
uv run aqven series <experiment_id> --path <package> --on dev|holdout [--cases N] [--repeats R] [--cap USD] [--json], exit codes 0 to 5; in the background, unpiped.uv run aqven series export <series_id> --path <package> [--format jsonl|csv] [--fields F …] [--variant V] [--outcome passed|failed|error|waiting|running] [--split dev|holdout] [--out FILE]: the rows ofseries_outputs; exits 2 on an unknown series, 5 when it loses the server.aqvenMCPseries_start,series_get(series_id,view,wait_seconds,fields,include_cases,case_limit,cursor),series_outputs(split,variant,case,outcome,fields,page_size,cursor),series_list(experiment_id,status),series_cancel,run_list(series_id,view: "compact"),run_get_node.
References
references/engine/run-a-series.md: the smoke, purpose, size, the launch plan, the cap, the CLI flags and exit codes. Read before step 1.references/engine/read-a-series.md: statuses, the first snapshot, verdicts and reasons, the matrix, stability, failures against infrastructure errors. Read at steps 5 and 11.references/mcp-cli/experiments-and-series.md:series_start,series_getand its summary,series_outputs,series_list,series_cancel,look, the split. Read before the first MCP call.references/mcp-cli/runs.md:run_listbyseries_idwithview: "compact",run_get_node. Read at step 10.references/reference/status-and-verdicts.md: every status, verdict, pause reason, attempt outcome and exit code, generated from the engine. Read when a value is not in this skill.references/studio/series.md: what the owner sees and where Continue is. Read at step 8.references/reference/project.md,references/studio/settings.md:research.spend_cap_usdand the Research budget setting. Read before touching the cap.references/integrations/model-providers.md: rate-limit lanes andon_rate_limit. Read at steps 5 and 12.references/reference/cli.md: every CLI command.references/reference/findings.md: the finding file a holdout series writes.