Skip to main content
The SDK returns structured data. TypeScript uses objects. Python uses dataclasses for most entities and dictionaries for stats, analyses, checks, and rubric records. Examples reuse the SDK setup. Run Python snippets inside an async function. job is a result from jobs().get(); event comes from a trial trace.

Field access by language

Most domain field names are snake_case in both languages. One deliberate Python exception is a check row’s task tally: row.tasks["byStatus"].

Job or check row?

jobs.list() defaults to jobs. With kind="all", discriminate before reading fields:
A check row has task-check counts. It does not have job arms, attempts, trial counts, or trial spend caps.

Status vocabulary

FAILED remains part of the job vocabulary. Do not infer all trial outcomes from the job’s status: a completed job can contain scoring, infrastructure, or budget failures.

Null is information

Do not replace missing cost or reward with zero in a report.

Cost and statistics

usage groups spent_usd, input/cached/cache-write/output token counts, as_of, and provisional. A provisional reading can increase. Job stats.cost_usd includes trial model spend and judge spend. judge_cost_usd identifies the judge share. Analysis cost is separate in stats.analysis.cost_usd; GPU compute estimates are separate too. Uploaded jobs use stats.reported_cost_usd for the archive’s reported cost. Their metered cost_usd and judge_cost_usd are null. Their worst_case_spend_usd is also null because they did not run under Evolve’s cap. An uploaded dataset reference can have version: null when its archive supplied no version. Job completion/error/cancellation counters overlap. Use the per-status trial tally when you need disjoint counts. Analysis tallies can also overlap when an earlier completed result stays visible while a newer analysis is pending or has failed. passAtK(job) / pass_at_k(job) reads sorted points from the server’s stats.evals groups. It does not recompute them locally. A single-attempt job, incomplete group, or non-binary rewards may have no pass@k points.

Name types safely

TypeScript exports useful types such as JobCreate, Job, Trial, and HostedClientConfig. Some nested input/result types are inferred through methods instead of exported by name:
The root-exported RetryConfig is for the separate Swarm API. Use the job’s retry shape for managed evals. Python exports hosted types such as DatasetSelector, AgentArm, and JobRetryConfigInput. Dataclass fields use attributes; TypedDict values use dictionary keys. The schemas below name each field. A ? marks a field that may be absent; null means it may be present without a value. Python uses None for null and normal dictionaries for nested TypedDict records.

Job fields

Job is returned by submission, detail reads, and job actions. A returned object describes the accepted state; use watch to wait for execution. The compact TypeScript schemas below describe data shapes. Some nested names are inferred types rather than root exports. Python fields keep the same spelling unless the language table above says otherwise.
Python stats are dictionaries. n_completed_trials, n_errored_trials, and n_cancelled_trials can overlap; they are not a partition of trials. evals groups rewards by agent, model, and dataset. Its current mean metric counts unrewarded trials as zero. Task rollups and comparisons use scored trials, with different handling of null rewards explained below.
A check row is a summary, not a full Check. In Python, row.tasks is a dictionary and its key remains byStatus.

Trial fields

A Trial holds one attempt’s outcome and evidence. reward is the primary scalar; verifier_result.rewards preserves the complete reward map. A new pending or failed analysis can appear in newer_analysis while analysis keeps an earlier completed result.
Each timing record has started_at and finished_at; overlapping phases must not be added as independent durations. Python step_results, sandbox_provider_degrade, and gpu_cost hold dictionaries.analysis_not_imported explains why an uploaded analysis.json was retained as a file but not accepted as an analysis. It is null when absent or successfully imported, and can be omitted by older servers. Older imported trials can have null exception messages and tracebacks.
Attempt phases are prepare, build, boot, install, agent, verify, and persist. Verifier mode is shared or separate. Sandbox provider is e2b, daytona, or modal.

Task rollups

jobs().tasks(id) gives one JobTaskRollup per distinct (task_name, source) pair. It is the short route from a job summary to the tasks needing inspection. Python returns a JobTaskRollup dataclass; check is a dictionary or None. A scored trial with a null reward contributes zero to this rollup’s mean.

Comparison results

jobs().compare(ids) returns aggregates in your id order. Each task row has one cell per requested job; disagreement rows come first.
MIXED means attempts have different statuses. MISSING means the job has no attempts for that task. Comparison means use non-null rewards on scored trials. coverage.scored counts every scored trial, including ones with a null reward; those trials are excluded from the comparison mean. The comparison matrix groups by task name alone, including matching names from different datasets or versions. The per-job task summary groups by both task name and source.

Job events

Every event has seq: number, type, and data. Switch on type: different event types can have the same payload. Python’s JobEvent.data is a dictionary.
A job.created event includes only the four agent fields shown below. Imported or older jobs can have null spend or provider metadata. These are the received fields; the current SDK declaration instead uses the full AgentArm type and non-null spend and provider types.
live_spent_usd is a lagging lower bound. On settled events, missing reward means no score; zero is a score. An exception message can be absent on cancellation or older recorded events.
The circuit breaker compares typed failure classes. Its event follows trial.settled instead of trial.retrying; the attempt stays terminal.

Analysis and check results

Analysis reads a trial’s trajectory. A task check reviews the task itself. New criterion results use pass, fail, or not_applicable. Older records can also contain unknown. A not_applicable explanation distinguishes an irrelevant criterion from missing essential evidence. Python returns results and defaults as dictionaries. checks maps criterion names to { outcome, explanation, evidence }; evidence is a list of { where, quote } records, or null for imported Harbor analyses. The API returns no overall verdict; compute what you need from the criteria.
source distinguishes Evolve analyses from imported harbor analyze results. Imported results have null agent, model, effort, rubric, prompt, failure findings, attempts, and check evidence. Their estimated_cost_usd is the uploaded figure. Older servers that omit source are read as platform.failure_modes lists findings supported by evidence, independently of rubric criteria. An empty list means no finding was supported; null means not completed, not requested on an older result, or imported from Harbor. Each finding has at least one evidence entry. New fail criterion outcomes also require evidence.attempts is 1, or 2 if a run produced no valid result and was repeated once. Timeout and infrastructure failures do not trigger that repeat. When repeated, cost and token totals cover both attempts. Older servers may omit attempts.
A completed group may contain failed task checks; inspect every result. Each task check’s summary gives its main findings and evidence gaps; it is null before completion and on older results that did not include a summary.
events contains parsed activity after since; total counts every stored activity row. gateway_calls is separate and returned in full. Optional stored_at aligns one server timestamp per returned event; it is absent when events came from the stored transcript file. Python does not expose these transcript methods.

Filesystem results

Filesystem pages keep next_cursor in both SDKs. Python uses dataclasses for their records, and dictionaries for event data.
captured state does not guarantee every file’s bytes were retained. Inspect capture status, left_out, and each entry’s captured field.
On a captured entry, captured: false means no bytes were retained. left_out describes an omitted or failed capture; otherwise it may be an untouched image file. On a live entry, captured is null. Package entries have retained bytes.

Sharing and deletion

Jobs and checks use the same JobShares result. A link is unlisted; PRIVATE does not mean that email grants are absent. Read emails to inspect them.

Job imports

jobs().upload() returns an import record. COMPLETED supplies job_id while the imported job exists; FAILED supplies a typed failure. The imported job records earlier work and does not start an agent. receiving reports an upload still in transit. Import progress is separate: fetching, extracting, validating, or ingesting. Inspect skipped trials and task links before treating an upload as a complete benchmark.
The hub source variant is reserved in the type; current upload methods accept a local directory/archive or a public HTTPS archive URL.
TaskLinkedBy is dataset_flag, job_dataset_record, task_hash, or none. When no task is linked, TaskLinkReason is hash_mismatch, task_not_in_dataset, no_dataset_named, dataset_ambiguous, no_hash_match, or no_task_digest.

passAtK

Python: pass_at_k. Read already-computed pass@k points from a job; this helper does not recompute scores. Groups without eligible points are omitted.

gatewayUsageOf

Python: gateway_usage_of. Return the platform meter’s usage update from a trace event, or null / None. A harness’s own usage line has no gateway source and does not qualify.
Gateway payload keys stay camelCase inside Python dictionaries. promptTokens includes cached and cache-written input. Missing readings are not zero-cost calls.
Last modified on November 9, 2026