---
title: "Submit a sweep: one build, N variants"
method: POST
path: "/preview/jobs/sweeps"
tags: ["jobs"]
---

# Submit a sweep: one build, N variants

`POST /preview/jobs/sweeps`

## Request

- Base URL: `https://autoresearch.sfcompute.com`
- URL: `https://autoresearch.sfcompute.com/preview/jobs/sweeps`
- Auth: HTTP bearer

Submit a sweep: N variants of one job in a single call (1-256). `shared` carries everything submit_job accepts; each entry of `variants` overrides `command`, `env`, or `build_args` for its job (overrides replace the shared field wholesale). Put variant parameters in env: env and command are not in the build key, so an env/command-only sweep is ONE image build + N runs; overriding build_args builds a separate image per distinct combination. Every variant becomes an ordinary job - same validation, fairness, and billing as submit_job - sharing `label`, so list_jobs(label, summary: true) is the one-call rollup and each job's $GMN_RESULT_PATH verdict comes back in it. Validation is all-or-nothing: any invalid variant rejects the whole batch with the offenders named, and nothing is submitted. Variant i derives idempotency key "{key}:{i}", so resubmitting the same batch returns the same jobs. Cancel losers individually with cancel_job. Pass `shared.depends_on: {job, require}` to gate the WHOLE sweep on one earlier job's declared result: no variant builds, queues or places until it succeeds and the predicate holds, so one cheap probe can decide whether 256 expensive variants ever cost anything. Pass `shared.output_to: {connection, dest}` to land every variant's output under one connection prefix - each at <dest><job_id>-<attempt>.tar, so a 256-shard generation sweep becomes one dataset in your own bucket with no key collisions and no credential in any container. SIZING: a sweep of many SHORT variants (minutes each) of one image is usually a TASK SET wearing sweep clothes - submit_job's `tasks` parameter runs the same units under ONE container start with per-unit retries and autoscaled runners; keep the sweep for variants that differ by build or run long.

## Query parameters

- `workspace` string

## Request body

- object
  - `idempotency_key` string, required: Idempotency key for the whole sweep: variant i derives "{key}:{i}", so resubmitting the same batch returns the same jobs.
  - `label` string, required: The sweep's label - every job carries it, and list_jobs(label, summary: true) is the one-call rollup.
  - `shared` SweepSharedParams, required (unresolved $ref)
  - `variants` SweepVariantParams[], required: Per-variant overrides, one job each (1-256 variants). (unresolved $ref)

## Response `200`

The capability's JSON result.

- Result: The capability's result: the same object the MCP tool returns as structuredContent. Resources carry an `object` type discriminator and an immutable id; money is integer micro-dollars in `*_usd_micros` fields.
  - `object` string: The resource type, when the result is one resource.

## Other responses

- `400`: Malformed request: bad JSON, a parameter that does not parse, or a value outside its range. Code `invalid`.
- `401`: No bearer token, or one this API cannot verify. Code `unauthenticated`.
- `403`: Authenticated, but the token's scopes or the account's role do not reach this operation. The message names the scope word to request. Code `forbidden`.
- `404`: No such route. Code `not_found`; the body names the OpenAPI document.
- `422`: A well-formed request the platform declined: no such node, a cap reached, a state that forbids the move. The message says which, and what to do instead. Code `refused`.
- `429`: Over this door's per-customer budget. Wait `Retry-After` seconds. Code `rate_limited`.
- `500`: Our fault. Retry; if it persists, quote the request-id. Code `internal`.

---

[API](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api.md) · [All operations](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/revisions/f88dcb70ac6c?raw)
