| name | opencode-worker-bridge |
| version | 0.2.0 |
| description | Use the OpenCode Worker Bridge as an agent-neutral, file-backed OpenCode delegation bridge packaged as a Codex skill. It starts, supervises, validates, and cleans up bounded OpenCode worker runs through JSON artifacts, command output, API transport checks, event observation, permission/session controls, PTY WebSocket utilities, and deterministic validation artifacts. |
OpenCode Worker Bridge
Use this skill when an orchestrating agent should delegate bounded work to an
OpenCode-backed worker while preserving file-backed state, deterministic
validation artifacts, and explicit readiness evidence.
This is not a Codex native subagent implementation and does not claim behavioral
parity with Codex internal subagents. Treat it as a public CLI and JSON-artifact
bridge for OpenCode delegation.
Contract
All worker state must be file-backed. Do not rely on chat memory for worker status, bugs, session ids, prompts, or validation results.
Use references/opencode-worker-contract.md for the public command and protocol
surface. Use references/native-connector-contract.json for the static native
wrapper/readiness contract. Use references/opencode-api-manifest.json only
when exact OpenCode operation coverage matters.
Stable source-of-truth boundaries:
- JSON artifacts under the selected run directory.
- Command output from
opencode_worker.py.
- The public reference files under
references/.
Do not treat chat memory, implementation modules, or wrapper responses alone as
proof of worker state. Wrapper responses are routing/evidence summaries whose
source_of_truth declares the evidence channel: most operations point back to
JSON artifacts, while stdout-only operations such as run_status use
stdout_json and may have empty artifact_paths.
The deterministic control script is:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" --help
If OPENCODE_WORKER_BRIDGE_ROOT is unset, resolve it from the current source checkout
first, then from the installed skill path:
if [ -d "$PWD/skills/opencode-worker-bridge/scripts" ]; then
OPENCODE_WORKER_BRIDGE_ROOT="$PWD/skills/opencode-worker-bridge"
else
OPENCODE_WORKER_BRIDGE_ROOT="${CODEX_HOME:-$HOME/.codex}/skills/opencode-worker-bridge"
if [ ! -d "$OPENCODE_WORKER_BRIDGE_ROOT" ] && [ -d "$HOME/.agents/skills/opencode-worker-bridge" ]; then
OPENCODE_WORKER_BRIDGE_ROOT="$HOME/.agents/skills/opencode-worker-bridge"
fi
fi
Supervisor Loop
- Create a run directory under the user workspace, for example
artifacts/opencode-worker-bridge/<timestamp>/.
- Start or attach to OpenCode through
$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py start; keep the state JSON in that run directory.
- Record every bug, retry, and optimization candidate in a JSONL file in the run directory.
- Delegate bounded prompts through
$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py delegate or a domain runner such as jobshop.
- Watch worker state through JSON reports, session messages, API calls, and
events.
- Validate outputs with deterministic scripts. Natural-language claims are not proof.
- Use
supervisor --run-dir to run the delegate/validate/retry repair loop.
- Stop the worker with
stop unless an explicit attach/reuse policy says otherwise.
Public Command Surface
Command labels:
| Label | Meaning |
|---|
offline | No OpenCode server, credentials, or model call required. |
live-read | Requires a live OpenCode server or state file but should not create sessions or mutate the server. |
live-write | Starts/stops OpenCode, creates sessions, sends prompts, uses PTY APIs, or otherwise changes live server/session state. |
run-state-mutating | Writes or updates local run-dir artifacts, pool files, reports, or generated prompts. |
Public commands:
| Command | Label | Requirements and writes |
|---|
start | live-write, run-state-mutating | Requires opencode; writes opencode-worker-state.json and log files. |
status | live-read | Requires worker state; prints process/API health. |
delegate, continue-session, jobshop | live-write, run-state-mutating | Require worker state, provider/model credentials when the route needs them, and prompt input; write job/status/report artifacts. |
call, events, pty-connect, pty-smoke | live-read or live-write by OpenCode operation | Require state or base URL. PTY commands mutate live PTY/session state. |
run-status, validate, compact | offline; compact is run-state-mutating | Inspect or write local JSON artifacts only. |
recover | offline, optionally run-state-mutating or live-write | Default writes resume-plan.json; --apply --mode reattach performs a live continuation only with explicit state and prompt. |
supervisor, resolve-blocker | offline, optionally live-write | Validate and render follow-ups from local artifacts; retry/apply modes require state and mutate live sessions. |
doctor | offline | Installed-surface readiness only; does not verify live credentials, provider/model routes, or permission semantics. |
preflight | live-read | Verifies live OpenCode health and provider/model route visibility before delegation. |
dogfood | offline, run-state-mutating | Runs deterministic public-surface self-tests and writes dogfood-report.json. |
live-validation-plan, stress-run --mode plan, api-drift without --state | offline, run-state-mutating | Generate deterministic plans/reports without model calls. |
api-drift --state, event-watch --state | live-read, run-state-mutating | Read live routes/events and write reports; event policies may update local worker status/blocker files. |
event-watch --events-file | offline, run-state-mutating | Deterministic event-policy test from a JSON file. |
native-wrapper | offline by default; --execute inherits wrapped command label | Plans or executes wrapper operations that return artifact paths or stdout JSON according to each operation's source_of_truth, plus validation summaries. |
native-connector | offline, run-state-mutating | Emits readiness artifacts only; it does not install or expose MCP/native connector tools. |
cleanup | offline dry-run; live-write with --apply | Acts only on opencode-worker-bridge state files under an explicit run root. |
release-notes | offline, run-state-mutating | Generates deterministic release-note JSON and markdown artifacts. |
pool-status, pool-acquire, pool-release, pool-recover | offline, run-state-mutating except status | Operate the file-backed concurrency pool. |
Source-checkout-only maintainer checks:
python3 scripts/check_contracts.py
python3 scripts/check_stress_harness.py
python3 scripts/check_multiagent_fixture.py
python3 scripts/check_dogfood.py
PYTHONPATH=skills/opencode-worker-bridge/scripts python3 -m coverage run -m pytest
Installed-agent checks should use the public CLI surface instead:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" doctor --json
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" dogfood --run-dir /tmp/opencode-worker-bridge-dogfood
Opt-in canary suite:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/canary_suite.py" all --run-dir /tmp/canary
Core Commands
Start a worker (live-write, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" start \
--state /abs/run/opencode-worker-state.json \
--cwd /abs/workdir \
--port 4096
Inspect worker status (live-read):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" status \
--state /abs/run/opencode-worker-state.json
Delegate a prompt and save the transcript (live-write, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" delegate \
--state /abs/run/opencode-worker-state.json \
--run-dir /abs/run \
--job-id implementation-1 \
--prompt-file /abs/run/task.md \
--permission-profile standard \
--report /abs/run/delegation-report.json
Continue an existing multi-turn worker conversation (live-write, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" continue-session \
--state /abs/run/opencode-worker-state.json \
--run-dir /abs/run \
--job-id followup-1 \
--session-id ses_... \
--prompt-file /abs/run/follow-up.md \
--permission-profile standard \
--report /abs/run/follow-up-report.json
delegate and continue-session write job_envelope.json and
worker.status.json when --run-dir is supplied. Prefer the public named
permission profiles: minimal, standard, allow_all, read-only,
workspace-write, trusted-test, or full-trusted. The legacy
--allow-all-permissions flag remains an alias for allow_all.
Call any OpenCode API operation by committed operationId (live-read or live-write by operation):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" call session.list \
--state /abs/run/opencode-worker-state.json
Tail OpenCode events (live-read):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" events \
--state /abs/run/opencode-worker-state.json \
--limit 5
Connect to an OpenCode PTY over WebSocket or run the live PTY smoke (live-write):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" pty-connect \
--state /abs/run/opencode-worker-state.json \
--pty-id pty_... \
--send "pwd\n"
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" pty-smoke \
--state /abs/run/opencode-worker-state.json \
--report /abs/run/pty-smoke.json
Run the job-shop delegation validation (live-write, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" jobshop \
--state /abs/run/opencode-worker-state.json \
--run-dir /abs/run/jobshop
Stop the worker (live-write, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" stop \
--state /abs/run/opencode-worker-state.json \
--run-dir /abs/run
Protocol Commands
Run status report (offline; reads lifecycle, artifacts, blockers, verdict):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" run-status \
--run-dir /abs/run \
--state /abs/run/opencode-worker-state.json
Recover from crashed worker / resume plan (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" recover \
--run-dir /abs/run \
--scan-dir /abs/workspace \
--report /abs/run/resume-plan.json
Apply safe recovery modes explicitly (run-state-mutating; reattach is live-write only with explicit state and prompt):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" recover \
--run-dir /abs/run \
--apply \
--mode cleanup \
--pool-dir /abs/pool
Render a blocker follow-up from blocked.json or needs_input.json (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" resolve-blocker \
--run-dir /abs/run \
--response "Use the smaller scope and continue." \
--report /abs/run/blocker-resolution-report.json
Compact transcript into conversation summary (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" compact \
--report /abs/run/delegation-report.json \
--output /abs/run/conversation_summary.json
Run the delegate/validate/retry supervisor repair loop (offline; retry actions are live-write):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" supervisor \
--run-dir /abs/run \
--validator /abs/validator.py \
--retry-action continue \
--state /abs/run/opencode-worker-state.json \
--session-id ses_... \
--follow-up-file /abs/run/follow-up.md \
--retry-limit 3
Validate a contract file (offline, run-state-mutating when writing a report):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" validate \
/abs/run/job_envelope.json \
--expect-type job_envelope \
--expect-schema-version 1
Run deterministic contract canaries (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/canary_suite.py" smoke-envelope --run-dir /tmp/canary
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/canary_suite.py" all --run-dir /tmp/canary
Run offline installed-surface readiness and deterministic dogfood:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" doctor --json
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" dogfood \
--run-dir /tmp/opencode-worker-bridge-dogfood
doctor reports offline installed-surface readiness. A passing doctor report
does not prove live OpenCode credentials, provider/model route visibility, or
permission semantics. Use preflight with explicit live state before delegation.
It always reports optional developer-tool availability in optional_checks;
without --strict-dev, optional failures do not affect passed. With
--strict-dev, pytest, coverage, and requirements-dev.txt become required.
In this skill, dogfood means an offline self-test of the public CLI and JSON
artifact protocol. It checks readiness, canaries, native-wrapper planning, event
policies, blocker handling, recovery, cleanup, dry-run live-validation planning,
and deterministic fixtures without live OpenCode/model calls. It is not live
self-delegation on a real task.
Prepare manual live validation without running model calls (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" live-validation-plan \
--run-dir /abs/run/live-validation \
--provider deepseek \
--model deepseek-v4-pro \
--variant max
Check a live OpenCode server before expensive delegation (live-read):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" preflight \
--state /abs/run/opencode-worker-state.json \
--provider deepseek \
--model deepseek-v4-pro \
--variant max
Concurrency Pool Commands
The file-backed concurrency pool provides acquire/release/heartbeat/recover
semantics across worker slots. Use these CLI commands to manage pool state:
Inspect pool state (offline):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" pool-status \
--pool-dir /abs/pool
Acquire a pool slot (creates the pool if needed; offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" pool-acquire \
--pool-dir /abs/pool \
--max-workers 4 \
--worker-id worker-1
Release a pool slot (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" pool-release \
--pool-dir /abs/pool \
--worker-id worker-1
Recover stale locks (locks older than 300s; offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" pool-recover \
--pool-dir /abs/pool
Native Wrapper And Readiness
List or plan the implemented wrapper surface without live calls (offline):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" native-wrapper list --json
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" native-wrapper invoke run_status \
--input-json '{"run_dir":"/abs/run"}'
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" native-wrapper invoke run_status \
--set run_dir=/abs/run \
--set artifact_glob=outputs/*.json
artifact_glob accepts a scalar glob, a JSON array, or repeated --set
entries.
Wrapper plans with missing conditional execution inputs return
status: "planned_incomplete" and execution_ready: false. Plan-only
incomplete calls exit 0; incomplete --execute calls exit nonzero. For
run_status --execute, use stdout_json as the source of truth because the
wrapped command prints run-status JSON instead of writing a report artifact.
Run wrapper execution only when the underlying command is intentionally allowed
(--execute inherits the wrapped command boundary):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" native-wrapper invoke event_watch \
--input-json '{"run_dir":"/abs/run","event_file":"/abs/events.json","policy":"record_only"}' \
--execute \
--report /abs/run/native-wrapper-result.json
Wrapper outputs are routing/evidence summaries. Most wrapper operations use
referenced JSON artifacts as source-of-truth evidence. Stdout-only operations
such as run_status use stdout_json, as declared by their
source_of_truth.
Do not claim exact Codex-native subagent parity. Remaining external limits are
the Codex internal subagent API, live OpenCode/model credentials, permission
semantic mismatch, and provider/model behavior differences.
native-connector emits readiness artifacts only. It does not install MCP
servers, expose connector tools, or register anything with Codex:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" native-connector \
--run-dir /abs/run/connector
Stable native-wrapper manifest fields are schema_version, kind, status,
source_of_truth, transport, supported_modes, external_limits,
operations[].id, operations[].wraps_command,
operations[].required_inputs, operations[].writes,
operations[].boundary, operations[].mutates_live_server,
operations[].mutates_run_state, operations[].implemented,
operations[].input_schema, operations[].conditional_execution_requirements,
operations[].output_contract, operations[].output_contract.source_of_truth,
operations[].output_contract.artifact_paths, and
operations[].output_contract.result_kind.
Environment-specific metadata such as absolute module, script, run_dir,
wrapper_manifest, and timestamp values are evidence for the current
installation, not portable contract keys.
See references/opencode-worker-contract.md for per-operation input schemas,
defaults, write behavior, and minimal wrapper examples.
Additional Operations
Opt-in live concurrent stress runner plan (offline, run-state-mutating):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" stress-run \
--run-dir /abs/run/stress \
--mode plan \
--provider deepseek \
--model deepseek-v4-pro \
--variant max
Check API drift in deterministic manifest mode (offline, run-state-mutating;
add --state for live-read route checks):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" api-drift \
--manifest "$OPENCODE_WORKER_BRIDGE_ROOT/references/opencode-api-manifest.json" \
--provider deepseek \
--model deepseek-v4-pro
Tail events and apply a file-backed policy. Use --events-file for offline
tests or --state for live reads:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" event-watch \
--run-dir /abs/run \
--state /abs/run/opencode-worker-state.json \
--policy record_only
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" event-watch \
--run-dir /abs/run \
--events-file /abs/events.json \
--policy record_only
Owned-process cleanup (dry-run is offline; add --apply for live-write cleanup):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" cleanup \
--run-root /abs/run \
--report /abs/run/cleanup-report.json
Generate deterministic release notes artifact:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" release-notes \
--run-dir /abs/run/release \
--implemented gap-1 \
--implemented gap-2
Optional integration with start and stop:
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" start \
--state /abs/run/opencode-worker-state.json \
--pool-dir /abs/pool \
--pool-worker-id worker-1
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" stop \
--state /abs/run/opencode-worker-state.json \
--pool-dir /abs/pool \
--pool-worker-id worker-1
Recover restart planning (offline, run-state-mutating; writes a plan only):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" recover \
--run-dir /abs/run --apply --mode restart-plan
Run status with an external artifact glob (offline):
python3 "$OPENCODE_WORKER_BRIDGE_ROOT/scripts/opencode_worker.py" run-status \
--run-dir /abs/run --artifact-glob "*.json"
Protocol Files
Supported public schema version: 1. Validate protocol files with
validate --expect-schema-version 1 when a command writes an artifact.
Protocol compatibility note: The Kind values below use the goal-delegator-
prefix, which is a stable protocol identifier preserved from the original
goal-delegator project name. These are not the current skill or package name
(opencode-worker-bridge). Do not rename the kind values; they form the
file-backed JSON contract.
| File | Kind | Required public fields |
|---|
job_envelope.json | goal-delegator-job | schema_version, kind, job_id, status, artifacts, route, timestamps |
blocked.json, needs_input.json | goal-delegator-blocked | schema_version, kind, reason, safe_to_retry, needed_from_orchestrator, evidence_paths |
worker.status.json | goal-delegator-worker-status | schema_version, kind, lifecycle, pid, process_alive, base_url, updated_at |
conversation_summary.json | goal-delegator-conversation-summary | schema_version, kind, summary, message_count, key_artifacts, remaining_work |
supervisor_verdict.json | goal-delegator-supervisor-verdict | schema_version, kind, status, attempts, validation, next_action |
stop-verdict.json | goal-delegator-stop-verdict | schema_version, kind, success, pid_exited, port_released, cleanup_errors, cleanup_warnings |
event-observation-report.json | goal-delegator-event-observation-report | schema_version, kind, events, event_count, policy, action_taken, timestamp |
native-wrapper-manifest.json | goal-delegator-native-wrapper-manifest | schema_version, kind, operations, transport, source_of_truth, status, external_limits |
native-wrapper-result.json | goal-delegator-native-wrapper-result | schema_version, kind, operation_id, status, command, artifact_paths, validation_summary, execution_ready, source_of_truth |
native-connector-readiness.json | goal-delegator-native-connector-readiness | schema_version, kind, connector_type, status, operations, transport, source_of_truth |
stress-run-report.json | goal-delegator-stress-run-report | schema_version, kind, mode, config, job_results, verdict |
api-drift-report.json | goal-delegator-api-drift-report | schema_version, kind, checks, drift_count, warning_count, status, passed |
cleanup-report.json | goal-delegator-cleanup-report | schema_version, kind, run_root, dry_run, processes_cleaned, processes_skipped, error_count |
release-notes.json | goal-delegator-release-notes | schema_version, kind, version, implemented_gaps, deferred_items, validation_commands |
doctor-report.json | goal-delegator-doctor-report | schema_version, kind, readiness_scope, live_readiness_command, not_checked, version, passed, checks, optional_checks, timestamp |
dogfood-report.json | goal-delegator-dogfood-report | schema_version, kind, passed, checks, run_dir, timestamp |
For doctor-report.json, not_checked is required readiness-scope evidence:
it lists live credentials, provider/model routes, live permission semantics, and
provider/model behavior checks that doctor intentionally does not perform.
Lifecycle values include created, starting, ready, delegated,
running, awaiting_validation, needs_input, blocked, failed, passed,
completed, pending, stopping, stopped, healthy, busy, idle,
done, crashed, and unknown.
Permission profiles:
| Profile | Permissions |
|---|
minimal, read-only | read, glob, grep, list |
standard, workspace-write | read, edit, glob, grep, list, bash, todowrite, question |
trusted-test | workspace-write plus task |
allow_all, full-trusted | trusted-test plus external_directory, webfetch, websearch, repo_clone, repo_overview, lsp, skill |
Issue taxonomy:
| ID | Meaning | Recovery |
|---|
transport | HTTP, SSE, WebSocket, or health-check transport failed. | Check OpenCode health and retry the transport call. |
model_output | Worker output was missing, refused, or invalid for the required artifact. | Retry with a stricter artifact schema. |
validation | Deterministic validation failed for an artifact or protocol file. | Send a validation-failure follow-up. |
permission | Worker lacked the required profile or permission. | Use a broader named permission profile. |
timeout | Session or worker action exceeded a bounded timeout. | Compact transcript and retry smaller scope. |
cleanup | Stop, port release, process cleanup, or stale-lock recovery failed. | Rerun stop and inspect stop-verdict.json. |
orchestrator_policy | Worker needs an explicit policy decision or orchestrator input. | Answer via resolve-blocker. |
harness_bug | Deterministic harness, fixture, or schema check is defective. | Fix the harness before live calls. |
unknown | Issue is not classified. | Record evidence and classify manually. |
See references/opencode-worker-contract.md for the full public protocol surface
and per-command examples.
Pass Criteria
For job-shop validation, the authoritative artifact is artifacts/opencode_jobshop_solution.json inside the job run directory, and the authoritative verdict is artifacts/jobshop_validation_report.json.
Pass requires the deterministic validator to report passed: true. If the worker returns prose without the JSON artifact, the run fails.