Skip to main content
The hosted surface is a set of clients, one per noun. Each one reads EVOLVE_API_KEY from the environment, or takes a HostedClientConfig(api_key=..., base_url=...). Create a key on the dashboard’s API keys page. Every call is a coroutine, and every client is an async context manager with close(). A request never follows a redirect: the client refuses every 3xx and raises it as an error, so the key only reaches the host you configured.

Start a job

datasets is a list of selectors, as dicts or DatasetSelector dataclasses. A bare name resolves to the active version; task_names, exclude_task_names and n_tasks narrow the task set. Every arm in agents, a dict or an AgentArm, names a model_name, and version, reasoning_effort, kwargs, preset and skills are optional. sandbox_provider picks "e2b", "daytona" or "modal". The retry policy is a JobRetryConfigInput dict and comes back resolved as JobRetryConfig. The fields are the same ones a -c config file takes on the CLI. Results are dataclasses with the wire’s snake_case names and Literal vocabularies for every closed set. Four keys the wire spells in camelCase are mapped: next_cursor, has_more, by_status and task_matrix. A refused request raises EvolveAPIError; see errors.

Wait for it

watch() returns a handle you either await, for the final job, or iterate, for each event. Pick one form per call.
The stream replays from the beginning, so attaching late loses nothing, and it resumes on its own after a disconnect. event.data is a plain dict; branch on event.type and read it by key.

Read the result

Every list on this surface works the same way: await it for one page, iterate it to walk every page. pass_at_k(job) reads a finished job’s pass@k out of its stats as sorted numbers. A trial id is global, so trials() reaches one without the job.
artifact() takes the same names as evolve trial download --stream. None means the trial never stored that artifact; it is a normal answer, not an error.

Download

The archive is the standard job directory, the same tree evolve job download unpacks.

Analyze

analyze() enqueues one analysis per trial and returns at once. watch_analysis() follows the batch of analyses to its end.

The catalog

Everything else

analyses(), checks(), skills(), agents(), auth() and orgs() are built the same way. meta() fetches the platform’s capability document, the live list of harnesses, models and limits, and needs no key. hosted() builds every client from one configuration.
Run any of the snippets above inside an async def main() and start it with asyncio.run(main()).