Sandbox API

Harbor and OpenCode flags

How to pass Harbor CLI options and OpenCode Plan/Build through the Sandbox gateway API.

Harbor and OpenCode flags

Consumers call the Sandbox gateway. They do not invoke harbor run or the OpenCode TUI CLI directly. The harbor-worker maps JSON fields to Harbor flags (and, when the agent is OpenCode, to opencode.json).

Harbor is not OpenCode

LayerRole
Harbor (/sandbox/harbor/*)Task eval: materialize → harbor run -a <agent> → verifier
Agent Runtime (/sandbox/agent/*)Ad-hoc runs (instruction + workspace, no task zip)
OpenCodeOne optional Harbor/catalog agent (opencode) with Plan/Build

Most Harbor agents (oracle, terminus-2, claude-code, …) never touch OpenCode. Plan/Build applies only when harbor_agent / agent_id is opencode.

Upstream: Harbor agents, OpenCode agents, OpenCode config.

Harbor CLI ↔ JSON matrix

Harbor CLIGateway JSON
-a <agent>agents[].harbor_agent or Agent Runtime agent_id
-e <env>top-level sandbox or harbor_extensions.sandbox (docker, daytona, …)
-m <model>model
-n <n>harbor_extensions.n_concurrent
--ae KEY=VALharbor_extensions.agent_env
--ak key=valueagents[].params and/or harbor_extensions.agent_kwargs (extensions win)
custom agent importharbor_extensions.custom_agent_import

OpenCode Plan / Build

OpenCode Plan vs Build is not a Harbor --mode flag. Headless OpenCode uses default_agent in opencode.json (plan | build | custom primary agent).

Do not confuse with OpenCode's per-agent mode field (primary | subagent) in opencode.json — that configures agent type, not Plan vs Build. See OpenCode agents — Mode.

ConceptWhat it isSandbox API
Harbor CLI --modeDoes not exist for Plan/Build
OpenCode default_agentWhich primary agent runs headlessly (plan, build, …)harbor_extensions.opencode_agent
OpenCode agent.*.modeAgent type (primary / subagent) in configNot exposed; use defaults

Pass:

"harbor_extensions": {
  "opencode_agent": "plan"
}

The worker writes visible_seed/opencode.json with "default_agent": "plan" and sets --ak opencode_config_path=… + OPENCODE_CONFIG_PATH.

Custom agents (opencode_config)

opencode_agent only selects a primary agent. To define or override OpenCode agents — including custom subagents like a code reviewer — pass opencode_config. It is a JSON fragment that the worker deep-merges into the generated opencode.json, matching OpenCode's own "configs are merged, not replaced" model.

"harbor_extensions": {
  "opencode_agent": "build",
  "opencode_config": {
    "agent": {
      "review": {
        "mode": "subagent",
        "description": "Reviews code for best practices",
        "permission": { "edit": "deny", "bash": "deny" }
      }
    }
  }
}

The primary agent (build here) can then invoke review via OpenCode's Task tool or an @review mention. See OpenCode agents — note agent.*.mode is primary | subagent (agent type), which is not Plan vs Build.

Accepted keys

opencode_config accepts an allowlisted subset of the OpenCode config schema. Any other key is rejected with 400.

KeyTypePurpose
agentobjectDefine or override primary agents and subagents (mode, model, prompt, tools, permission, …).
permissionobjectGlobal permission gates (edit, bash, …) applied to the run.
toolsobjectEnable/disable built-in or MCP tools.
modelstringDefault model for the run.
small_modelstringModel for lightweight tasks (titles, summaries).
subagent_depthintegerHow deeply subagents may invoke other subagents (default 1).
instructionsarrayExtra instruction/rule file paths merged into context.
commandobjectCustom slash-command definitions.
mcpobjectAdditional MCP servers (merged with gateway-injected servers).

Rules and precedence

  • default_agent is not accepted here — use opencode_agent (single source of truth). Supplying it returns 400.
  • Platform-authoritative wins: gateway-injected MCP servers and the opencode_agent-derived default_agent override the overlay. Overlay mcp entries are merged in additively (they never drop gateway servers).
  • Locked/blocked keys: $schema cannot be overridden; account- or credential-scoped keys (provider, enabled_providers, disabled_providers, share, autoupdate) are rejected.
  • Size limit: the serialized overlay must be ≤ 64 KiB.

Rendered opencode.json

Given opencode_agent: "build" and the review example above, the worker writes visible_seed/opencode.json (then points OpenCode at it via OPENCODE_CONFIG_PATH):

{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "build",
  "agent": {
    "review": {
      "mode": "subagent",
      "description": "Reviews code for best practices",
      "permission": { "edit": "deny", "bash": "deny" }
    }
  }
}

Validation errors

All checks run at enqueue time and return 400 with a descriptive message — the run is never silently accepted with a bad config.

ConditionMessage (abridged)
Not an objectopencode_config must be an object
Empty objectopencode_config must not be empty
default_agent presentmust not set default_agent; use … opencode_agent
Disallowed top-level keyunsupported opencode_config keys: [...]
agent not an object of objectsopencode_config.agent[...] must be an object
Serialized size > 64 KiBopencode_config too large (...)

Harbor datapoint example

curl -sS -H "X-Api-Key: $SANDBOX_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "task_slug": "my-task",
    "sandbox": "daytona",
    "metadata": {"task_archive_url": "https://..."},
    "agents": [{
      "name": "builder",
      "harbor_agent": "opencode",
      "model": "anthropic/claude-sonnet-4-5",
      "params": {"temperature": 0},
      "harbor_extensions": {
        "opencode_agent": "plan",
        "agent_env": {"FOO": "1"}
      }
    }]
  }' \
  "$SANDBOX_GATEWAY_URL/sandbox/harbor/v2/run/datapoint"

Agent Runtime example

curl -sS -H "X-Api-Key: $SANDBOX_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "agent_id": "opencode",
    "instruction": "Propose a plan to fix the failing test",
    "model": "anthropic/claude-sonnet-4-5",
    "harbor_extensions": { "opencode_agent": "plan" }
  }' \
  "$SANDBOX_GATEWAY_URL/sandbox/agent/v1/runs"

Not exposed as first-class API fields

Use agent_env, workspace files, or agent_kwargs for other OpenCode knobs. We do not surface TUI-only UX (Tab Plan/Build, /connect) or raw Harbor ops flags (--debug, --force-build) as dedicated request fields — those are worker/platform defaults.