Sandbox API

Agent Runtime

Ad-hoc LLM agent runs

Ad-hoc LLM agent runs

Every request needs a credential — see Authentication.

MethodPathSummary
POST/sandbox/agent/agentsRegister Agent
GET/sandbox/agent/agents/{agent_id}Get Agent
GET/sandbox/agent/capabilitiesList agents (catalog-backed)
GET/sandbox/agent/v1/agentsList Agents
POST/sandbox/agent/v1/runsStart Agent Run
GET/sandbox/agent/v1/runs/{job_id}Agent run status
GET/sandbox/agent/v1/runs/{job_id}/eventsSSE agent run events

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

Register Agent

POST /sandbox/agent/agents

Request body

application/json, required — RegisterRequest

FieldTypeRequiredDescription
idstringyes
display_namestring | nullno
requires_modelbooleannoDefault: true.
mcp_adapterstring | nullno
air_gap_capablebooleannoDefault: false.
requires_reference_solutionbooleannoDefault: false.

Responses

StatusDescriptionBody
201Successful ResponseAgentOut
422Validation ErrorHTTPValidationError

Get Agent

GET /sandbox/agent/agents/{agent_id}

Parameters

NameInTypeRequiredDescription
agent_idpathstringyes

Responses

StatusDescriptionBody
200Successful ResponseAgentOut
404No agent with this id. Agents come from the catalog, so an id that worked before can disappear when a catalog entry is disabled — list /agents rather than hardcoding one.
422Validation ErrorHTTPValidationError

List agents (catalog-backed)

GET /sandbox/agent/capabilities

Responses

StatusDescriptionBody
200Successful Responseobject

List Agents

GET /sandbox/agent/v1/agents

Tier 1 catalog entries plus Harbor AgentFactory agents (deduped).

Responses

StatusDescriptionBody
200Catalog ∪ Harbor factory agentsobject

Example response:

{
  "agents": [
    {
      "id": "oracle",
      "display_name": "Oracle",
      "source": "catalog"
    },
    {
      "id": "opencode",
      "display_name": "OpenCode",
      "source": "catalog"
    }
  ],
  "count": 2
}

Start Agent Run

POST /sandbox/agent/v1/runs

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 — AgentRunBody

FieldTypeRequiredDescription
agent_idstringyes
instructionstringyes
modelstring | nullno
workspaceobject | nullno
sandbox_idstring | nullnoExisting long-lived sandbox for a continuing, ungraded agent loop. Only agents whose catalog integration is sandbox may attach. The sandbox must be running and owned by this tenant/project.
pass_at_kintegernoAgent Runtime is ungraded and normally runs once. Values above 1 are rejected when sandbox_id is set; use Harbor pass_at_k for fresh attempts. Default: 1.
agent_optionsobject | nullnoExecutor options for this run: agent_env, agent_kwargs, sandbox, n_concurrent, custom_agent_import. When agent_id 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. Accepted as harbor_extensions (deprecated) for backwards compatibility.

Example:

{
  "agent_id": "opencode",
  "instruction": "List files in the workspace root.",
  "model": "anthropic/claude-sonnet-4-5",
  "agent_options": {
    "agent_env": {
      "SANDBOX_DOCS": "1"
    }
  }
}

Responses

StatusDescriptionBody
202Run acceptedobject
400The agent's preconditions are not satisfied by this request
422Validation ErrorHTTPValidationError

Example response:

{
  "job_id": "agent-run-550e8400",
  "status": "queued",
  "agent_id": "opencode",
  "message": "run accepted",
  "status_url": "/sandbox/agent/v1/runs/agent-run-550e8400",
  "events_url": "/sandbox/agent/v1/runs/agent-run-550e8400/events"
}

Agent run status

GET /sandbox/agent/v1/runs/{job_id}

Status, timings and result for one agent run.

Reads the same durable record the worker writes and the harbor job route serves, so the two surfaces cannot disagree about a run.

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
200Current state of the runobject
404No run with this id in this tenancy
422Validation ErrorHTTPValidationError

Example response:

{
  "job_id": "agent-run-550e8400",
  "status": "running",
  "timings": {
    "enqueued_at": 1785124565.5,
    "started_at": 1785124573.5
  }
}

SSE agent run events

GET /sandbox/agent/v1/runs/{job_id}/events

Follow a run's phases as they happen.

The same stream generator the harbor route uses, over the same event log — an agent run and a datapoint run are narrated by one mechanism, so this is a second entrance to it rather than a second copy of it.

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. A meta frame arrives immediately, then one phase frame per phase transition, then done. Reconnect with Last-Event-ID to resume rather than replay.any
404No run with this id in this tenancy. The stream is refused rather than opened, so a mistyped id fails immediately instead of looking like a run that is slow to start.
422Validation ErrorHTTPValidationError

Schemas

The object shapes referenced above.

AgentOut

FieldTypeRequiredDescription
idstringyes
display_namestringyes
requires_modelbooleanyes
mcp_adapterstring | nullno
air_gap_capablebooleannoDefault: false.
requires_reference_solutionbooleannoDefault: false.

AgentRunBody

FieldTypeRequiredDescription
agent_idstringyes
instructionstringyes
modelstring | nullno
workspaceobject | nullno
sandbox_idstring | nullnoExisting long-lived sandbox for a continuing, ungraded agent loop. Only agents whose catalog integration is sandbox may attach. The sandbox must be running and owned by this tenant/project.
pass_at_kintegernoAgent Runtime is ungraded and normally runs once. Values above 1 are rejected when sandbox_id is set; use Harbor pass_at_k for fresh attempts. Default: 1.
agent_optionsobject | nullnoExecutor options for this run: agent_env, agent_kwargs, sandbox, n_concurrent, custom_agent_import. When agent_id 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. Accepted as harbor_extensions (deprecated) for backwards compatibility.

HTTPValidationError

FieldTypeRequiredDescription
detailValidationError[]no

RegisterRequest

FieldTypeRequiredDescription
idstringyes
display_namestring | nullno
requires_modelbooleannoDefault: true.
mcp_adapterstring | nullno
air_gap_capablebooleannoDefault: false.
requires_reference_solutionbooleannoDefault: false.

ValidationError

FieldTypeRequiredDescription
locstring | integer[]yes
msgstringyes
typestringyes
inputanyno
ctxobjectno

Machine-readable spec: OpenAPI YAML.