Sandbox API

Harbor

Run a benchmark task and collect its results. Use these paths for new integrations.

Run a benchmark task and collect its results. Use these paths for new integrations.

Every request needs a credential — see Authentication.

MethodPathSummary
GET/sandbox/harbor/api-versionsList Harbor API versions
GET/sandbox/harbor/v2/capabilitiesHarbor API v2 capabilities
GET/sandbox/harbor/v2/jobs/{job_id}Get job status (v2)
GET/sandbox/harbor/v2/jobs/{job_id}/artifactsList job artifacts (v2)
GET/sandbox/harbor/v2/jobs/{job_id}/artifacts/archiveDownload job archive (v2)
GET/sandbox/harbor/v2/jobs/{job_id}/artifacts/test-stdout/{relative_path}Download verifier test stdout (v2)
POST/sandbox/harbor/v2/jobs/{job_id}/cancelCancel job (v2)
GET/sandbox/harbor/v2/jobs/{job_id}/eventsSSE job events (v2)
POST/sandbox/harbor/v2/jobs/{job_id}/retry-errored-trialsRetry only errored pass@k trials (v2)
POST/sandbox/harbor/v2/jobs/{job_id}/retry-provider-blockedRetry full pass@k after provider-blocked failure (v2)
POST/sandbox/harbor/v2/jobs/execute-tasksEnqueue Harbor datapoint job (v2)
POST/sandbox/harbor/v2/jobs/verify-taskEnqueue Harbor verify-task job (v2)
POST/sandbox/harbor/v2/run/datapointRun Harbor datapoint (v2)
POST/sandbox/harbor/v2/verify-taskRun Harbor verifier only (v2)

Common headers

Accepted on every endpoint on this page.

NameInTypeRequiredDescription
x-correlation-idheaderstringnoEnd-to-end correlation id for this eval run. When set, the gateway and downstream services honor it verbatim in logs, Cloud Trace span attributes, async job payloads, and Langfuse trace.id. When omitted, the gateway generates a ULID and echoes it on the response.

Endpoints

List Harbor API versions

GET /sandbox/harbor/api-versions

Responses

StatusDescriptionBody
200Successful Responseobject

Harbor API v2 capabilities

GET /sandbox/harbor/v2/capabilities

Responses

StatusDescriptionBody
200Successful Responseobject

Get job status (v2)

GET /sandbox/harbor/v2/jobs/{job_id}

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
200Job statusobject
404No job with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError

Example response:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "running",
  "timings": {
    "enqueued_at": 1753420800.12,
    "started_at": 1753420802.44,
    "queue_wait_ms": 2320
  },
  "created_at": 1753420800.12,
  "updated_at": 1753420802.44
}

List job artifacts (v2)

GET /sandbox/harbor/v2/jobs/{job_id}/artifacts

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
200Successful Responseobject
422Validation ErrorHTTPValidationError

Download job archive (v2)

GET /sandbox/harbor/v2/jobs/{job_id}/artifacts/archive

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
presignedquerybooleanno
asquerystring | nullnoSet to "json" to receive {"url": ...} instead of a 307 redirect. Requires presigned=true.
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
200Successful Responseany
404No artifact with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError

Download verifier test stdout (v2)

GET /sandbox/harbor/v2/jobs/{job_id}/artifacts/test-stdout/{relative_path}

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
relative_pathpathstringyes
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
200Successful Responseany
404No artifact with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError

Cancel job (v2)

POST /sandbox/harbor/v2/jobs/{job_id}/cancel

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
200Successful Responseobject
404No job with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError

SSE job events (v2)

GET /sandbox/harbor/v2/jobs/{job_id}/events

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
Last-Event-IDheaderstring | nullno
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
200Server-sent events streamany
404No job with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError

Retry only errored pass@k trials (v2)

POST /sandbox/harbor/v2/jobs/{job_id}/retry-errored-trials

Batch-refill incomplete pass@k attempts for a terminal datapoint job. Counts result.outcome.trials_detail rows with status=errored and enqueues a new job with pass_at_k=N_errored plus metadata.retry_of / retry_kind=errored_trials. Completed attempts (including reward 0.0) are not retried. Parent archive is immutable; combine scores client-side. By default notifications/deliver/writeback are not copied (pass include_side_effects=true to keep them). Optional Idempotency-Key returns the same child job on repeat. v1: single-agent datapoints only. Requires a durable request snapshot from enqueue. Returns 400 when nothing errored or the snapshot/contract is missing; 409 when the parent is still running.

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
include_side_effectsquerybooleannoWhen true, copy the parent's notifications/deliver/writeback onto the child. Default false so a refill does not re-fire webhooks.
Idempotency-Keyheaderstring | nullno
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
202Follow-up job acceptedobject
400Nothing to retry, multi-agent, or missing request snapshot
409Parent job is not terminal
422Validation ErrorHTTPValidationError

Example response:

{
  "job_id": "child-uuid",
  "retry_of": "parent-uuid",
  "pass_at_k": 3,
  "retried_exceptions": [
    "TerminusNoProgressError"
  ],
  "status": "queued"
}

Retry full pass@k after provider-blocked failure (v2)

POST /sandbox/harbor/v2/jobs/{job_id}/retry-provider-blocked

Enqueue a new job with the parent's original pass_at_k when result.outcome.failure_class=provider (quota/auth/rate-limit). Unlike retry-errored-trials, this re-runs the full k budget with a fresh KeyHive lease. Sets metadata.retry_of / retry_kind=provider_blocked. Optional Idempotency-Key returns the same child job on repeat. v1: single-agent datapoints only.

Parameters

NameInTypeRequiredDescription
job_idpathstringyes
include_side_effectsquerybooleanno
Idempotency-Keyheaderstring | nullno
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Responses

StatusDescriptionBody
202Follow-up job acceptedobject
400Parent is not provider-blocked or snapshot missing
409Parent job is not terminal
422Validation ErrorHTTPValidationError

Enqueue Harbor datapoint job (v2)

POST /sandbox/harbor/v2/jobs/execute-tasks

Parameters

NameInTypeRequiredDescription
Idempotency-Keyheaderstring | nullno
X-Sandbox-Job-Idheaderstring | nullno
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Request body

application/json, required — ExecuteTasksRequest

FieldTypeRequiredDescription
task_slugstringyes
agentsDatapointAgentBody[]yesOne or more agents to run against the same materialized task (max 8).
metadataobjectno
artifactsstring[] | nullno
sandboxstring | nullno
notificationsobject[] | nullno
writebackHarborTaskWritebackSpec | nullno
deliverDeliverSpec | nullno
require_verifier_evidenceboolean | nullnoWhether outcome.valid_for_scoring requires the verifier to have produced a machine-readable test report. Defaults to true: a verifier that writes a reward without collecting any test proves nothing, and with no report there is no way to tell the difference. Set false when the task uses a shell verifier you trust and you want to score on its reward alone — the rewards themselves are returned either way, and the job still succeeds. Deployment-wide override: SANDBOX_HARBOR_REQUIRE_VERIFIER_EVIDENCE=false.

Responses

StatusDescriptionBody
202Successful Responseobject
422Validation ErrorHTTPValidationError

Enqueue Harbor verify-task job (v2)

POST /sandbox/harbor/v2/jobs/verify-task

Parameters

NameInTypeRequiredDescription
Idempotency-Keyheaderstring | nullno
X-Sandbox-Job-Idheaderstring | nullno
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Request body

application/json, required — VerifyTaskRequest

FieldTypeRequiredDescription
task_slugstringyes
metadataobjectno
workspace_fixture_urlstring | nullno
sandboxstring | nullno

Responses

StatusDescriptionBody
202Successful Responseobject
422Validation ErrorHTTPValidationError

Run Harbor datapoint (v2)

POST /sandbox/harbor/v2/run/datapoint

Parameters

NameInTypeRequiredDescription
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Request body

application/json, required — RunDatapointRequest

FieldTypeRequiredDescription
task_slugstringyes
agentsDatapointAgentBody[]yesOne or more agents to run against the same materialized task (max 8).
metadataobjectno
artifactsstring[] | nullno
sandboxstring | nullno
notificationsobject[] | nullno
writebackHarborTaskWritebackSpec | nullno
deliverDeliverSpec | nullno
require_verifier_evidenceboolean | nullnoWhether outcome.valid_for_scoring requires the verifier to have produced a machine-readable test report. Defaults to true: a verifier that writes a reward without collecting any test proves nothing, and with no report there is no way to tell the difference. Set false when the task uses a shell verifier you trust and you want to score on its reward alone — the rewards themselves are returned either way, and the job still succeeds. Deployment-wide override: SANDBOX_HARBOR_REQUIRE_VERIFIER_EVIDENCE=false.

Example:

{
  "task_slug": "example-task",
  "metadata": {
    "task_archive_url": "https://storage.example/tasks/example-task.zip"
  },
  "agents": [
    {
      "name": "oracle",
      "harbor_agent": "oracle",
      "harbor_extensions": {
        "agent_env": {
          "SANDBOX_DOCS": "1"
        }
      }
    }
  ]
}

Responses

StatusDescriptionBody
200Datapoint completedobject
404No job with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError
429The project is already running its maximum number of concurrent jobs. Nothing was enqueued, so retrying after Retry-After is safe and cannot duplicate a run. Use POST /jobs/execute-tasks instead if you would rather the platform queue the work than refuse it: the async route accepts the job with a 202 and lets it wait for capacity.
504The run did not finish inside the synchronous wait. It has not been cancelled — it is still running, and the job id is in the response headers. Poll GET /jobs/{job_id}, or follow GET /jobs/{job_id}/events, rather than resubmitting. Use POST /jobs/execute-tasks instead if your tasks routinely run this long.

Example response:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "succeeded",
  "results": [
    {
      "agent": "oracle",
      "reward": 1
    }
  ]
}

Run Harbor verifier only (v2)

POST /sandbox/harbor/v2/verify-task

Parameters

NameInTypeRequiredDescription
X-Sandbox-Project-Idheaderstring | nullnoProject to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted.
X-Sandbox-Tenant-Idheaderstring | nullnoTenant for this request. Must match the credential's tenant when the credential carries one.

Request body

application/json, required — VerifyTaskRequest

FieldTypeRequiredDescription
task_slugstringyes
metadataobjectno
workspace_fixture_urlstring | nullno
sandboxstring | nullno

Example:

{
  "task_slug": "my-task",
  "metadata": {
    "task_archive_url": "https://storage.example/tasks/my-task.zip"
  }
}

Responses

StatusDescriptionBody
200Datapoint completedobject
404No job with this id in this tenancy. Job records expire, so this is also the answer for a job that has aged out.
422Validation ErrorHTTPValidationError
429The project is already running its maximum number of concurrent jobs. Nothing was enqueued, so retrying after Retry-After is safe and cannot duplicate a run. Use POST /jobs/execute-tasks instead if you would rather the platform queue the work than refuse it: the async route accepts the job with a 202 and lets it wait for capacity.
504The run did not finish inside the synchronous wait. It has not been cancelled — it is still running, and the job id is in the response headers. Poll GET /jobs/{job_id}, or follow GET /jobs/{job_id}/events, rather than resubmitting. Use POST /jobs/execute-tasks instead if your tasks routinely run this long.

Example response:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "succeeded",
  "results": [
    {
      "agent": "oracle",
      "reward": 1
    }
  ]
}

Schemas

The object shapes referenced above.

DatapointAgentBody

FieldTypeRequiredDescription
namestringyesLogical agent label in the datapoint result
harbor_agentstringyesHarbor agent id (catalog or factory)
modelstring | nullnoLLM model override
pass_at_kintegernoDefault: 1.
paramsobjectnoPer-request agent kwargs forwarded to Harbor as --ak key=value. Merged with harbor_extensions.agent_kwargs (extensions win on conflict).
harbor_extensionsobject | nullnoHarbor passthrough: agent_env (--ae), agent_kwargs (--ak), sandbox (-e), n_concurrent, custom_agent_import. When harbor_agent is opencode: opencode_agent sets default_agent in opencode.json (plan | build); opencode_config deep-merges an allowlisted subset of opencode.json (agent, permission, tools, model, small_model, subagent_depth, instructions, command, mcp) — e.g. a custom agent.review subagent.

DeliverSpec

v2 customer delivery — maps to staged_zip writeback internally.

FieldTypeRequiredDescription
agent_run_zipPresignedDeliverable | nullnoUpload agent outputs as a single zip after the run.

ExecuteTasksRequest

FieldTypeRequiredDescription
task_slugstringyes
agentsDatapointAgentBody[]yesOne or more agents to run against the same materialized task (max 8).
metadataobjectno
artifactsstring[] | nullno
sandboxstring | nullno
notificationsobject[] | nullno
writebackHarborTaskWritebackSpec | nullno
deliverDeliverSpec | nullno
require_verifier_evidenceboolean | nullnoWhether outcome.valid_for_scoring requires the verifier to have produced a machine-readable test report. Defaults to true: a verifier that writes a reward without collecting any test proves nothing, and with no report there is no way to tell the difference. Set false when the task uses a shell verifier you trust and you want to score on its reward alone — the rewards themselves are returned either way, and the job still succeeds. Deployment-wide override: SANDBOX_HARBOR_REQUIRE_VERIFIER_EVIDENCE=false.

HTTPValidationError

FieldTypeRequiredDescription
detailValidationError[]no

HarborTaskWritebackSpec

FieldTypeRequiredDescription
enabledbooleannoDefault: true.
destinationWritebackDestinationyes
mode"in_place_overwrite" | "versioned_suffix" | "staged_zip"noDefault: "in_place_overwrite".
include_pathsstring[] | nullno
include_run_outputsbooleannoDefault: true.
include_judge_outputsbooleannoDefault: false.
deliverable_filesstring[] | nullno
deliverable_destination_prefixstringnoDefault: "outputs/{label}/".
missing_deliverable_is_failurebooleannoDefault: true.
include_telemetrybooleannoDefault: false.
deliverables_onlybooleannoDefault: false.

PresignedDeliverable

One presigned HTTP upload target.

FieldTypeRequiredDescription
urlstringyesPresigned PUT (or POST) URL.
method"PUT" | "POST"noDefault: "PUT".
headersobjectno
keystringnoLogical artifact name in writeback outcomes. Default: "agent_run.zip".

PresignedPut

One presigned write target, keyed by relative path within the destination.

FieldTypeRequiredDescription
keystringyesRelative path under the destination root. The writeback step matches files to URLs by this key.
urlstringyes
method"PUT" | "POST"noDefault: "PUT".
headersobjectno

RunDatapointRequest

FieldTypeRequiredDescription
task_slugstringyes
agentsDatapointAgentBody[]yesOne or more agents to run against the same materialized task (max 8).
metadataobjectno
artifactsstring[] | nullno
sandboxstring | nullno
notificationsobject[] | nullno
writebackHarborTaskWritebackSpec | nullno
deliverDeliverSpec | nullno
require_verifier_evidenceboolean | nullnoWhether outcome.valid_for_scoring requires the verifier to have produced a machine-readable test report. Defaults to true: a verifier that writes a reward without collecting any test proves nothing, and with no report there is no way to tell the difference. Set false when the task uses a shell verifier you trust and you want to score on its reward alone — the rewards themselves are returned either way, and the job still succeeds. Deployment-wide override: SANDBOX_HARBOR_REQUIRE_VERIFIER_EVIDENCE=false.

ValidationError

FieldTypeRequiredDescription
locstring | integer[]yes
msgstringyes
typestringyes
inputanyno
ctxobjectno

VerifyTaskRequest

FieldTypeRequiredDescription
task_slugstringyes
metadataobjectno
workspace_fixture_urlstring | nullno
sandboxstring | nullno

WritebackDestination

FieldTypeRequiredDescription
urlstring | nullnoDestination root URL (s3://, gs://, or presigned PUT for staged_zip). Optional when presigned_writes fully specifies targets.
presigned_writesPresignedPut[] | nullno
storage_connector_idinteger | nullno

Machine-readable spec: OpenAPI YAML.