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
| Layer | Role |
|---|---|
Harbor (/sandbox/harbor/*) | Task eval: materialize → harbor run -a <agent> → verifier |
Agent Runtime (/sandbox/agent/*) | Ad-hoc runs (instruction + workspace, no task zip) |
| OpenCode | One 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 CLI | Gateway 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=VAL | harbor_extensions.agent_env |
--ak key=value | agents[].params and/or harbor_extensions.agent_kwargs (extensions win) |
| custom agent import | harbor_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.
| Concept | What it is | Sandbox API |
|---|---|---|
Harbor CLI --mode | Does not exist for Plan/Build | — |
OpenCode default_agent | Which primary agent runs headlessly (plan, build, …) | harbor_extensions.opencode_agent |
OpenCode agent.*.mode | Agent type (primary / subagent) in config | Not 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.
| Key | Type | Purpose |
|---|---|---|
agent | object | Define or override primary agents and subagents (mode, model, prompt, tools, permission, …). |
permission | object | Global permission gates (edit, bash, …) applied to the run. |
tools | object | Enable/disable built-in or MCP tools. |
model | string | Default model for the run. |
small_model | string | Model for lightweight tasks (titles, summaries). |
subagent_depth | integer | How deeply subagents may invoke other subagents (default 1). |
instructions | array | Extra instruction/rule file paths merged into context. |
command | object | Custom slash-command definitions. |
mcp | object | Additional MCP servers (merged with gateway-injected servers). |
Rules and precedence
default_agentis not accepted here — useopencode_agent(single source of truth). Supplying it returns400.- Platform-authoritative wins: gateway-injected MCP servers and the
opencode_agent-deriveddefault_agentoverride the overlay. Overlaymcpentries are merged in additively (they never drop gateway servers). - Locked/blocked keys:
$schemacannot 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.
| Condition | Message (abridged) |
|---|---|
| Not an object | opencode_config must be an object |
| Empty object | opencode_config must not be empty |
default_agent present | must not set default_agent; use … opencode_agent |
| Disallowed top-level key | unsupported opencode_config keys: [...] |
agent not an object of objects | opencode_config.agent[...] must be an object |
| Serialized size > 64 KiB | opencode_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.