Get the FREE Ultimate OpenClaw Setup Guide →

bridge-opencode

Scanned
npx machina-cli add skill mikeng-io/agent-skills/bridge-opencode --openclaw
Files (1)
SKILL.md
13.6 KB

Bridge: OpenCode Multi-Model Adapter

This file is a REFERENCE DOCUMENT. Any orchestrating skill reads it via the Read tool and embeds its instructions directly into Task agent prompts. It is not invoked as a standalone skill — it is a reusable set of instructions for OpenCode dispatch.

Input schema, agent prompt template, output schema, verdict logic, artifact format, and status semantics are defined in bridge-commons/SKILL.md. This file covers OpenCode-specific connection detection, timeout multiplier, and execution paths.

Bridge Identity

bridge: opencode
model_family: multi-provider   # Routes to any configured AI provider
availability: conditional
connection_preference:
  1: native-dispatch  # Executor is OpenCode — internal agent routing
  2: http-api         # Any executor — opencode serve REST API at :4096
  3: cli              # Any other executor — opencode run
  4: halt             # None available — surface advisory, offer setup

Why OpenCode?

OpenCode is provider-agnostic — it routes to whichever AI providers are configured (Anthropic, OpenAI, Google, GLM, Qwen, etc.). Running it as a bridge lets the calling skill get a second opinion from a different model family than the one currently executing the skill.

Trade-off: 1.5× timeout multiplier applies because model calls go through OpenCode's routing layer.


Step 1: Pre-Flight — Connection Detection

Check A: Native Dispatch?

If the executor is OpenCode, this is the preferred path — route the task to an OpenCode internal agent within the current session rather than shelling out or calling the HTTP API.

# Check if running inside an OpenCode session
echo ${OPENCODE_SESSION_ID:+found}
# Alternatively: OPENCODE_CLIENT is set when OpenCode is the executor
echo ${OPENCODE_CLIENT:+found}

If in an OpenCode session → use native dispatch (route to general or explore subagent).

If executor is not OpenCode → proceed to Check B.


Check B: HTTP API Server Running?

curl -s --max-time 3 http://localhost:4096 -o /dev/null -w "%{http_code}"
# Also check custom port if OPENCODE_PORT env var is set

If responds (any HTTP code) → use HTTP API path (Step 3A). Server is already running.


Check C: CLI Installed?

which opencode

If found → proceed to Check D.

If not found → no connection available — go to Step 2 (Advisory).


Check D: Provider Authenticated? (CLI path only)

opencode auth list

If output shows at least one authenticated provider → proceed to CLI path.

If no providers configured → go to Step 2 (Advisory) with reason: no_provider_configured.


Step 2: Advisory — Halt and Present Options

Do not skip silently. Surface the appropriate message and wait for a choice.

Advisory: Not Installed

⚠ OpenCode is not installed or not in PATH.

Options:
  [1] Install OpenCode
      npm install -g opencode-ai
      # or: brew install opencode

  [2] Start the OpenCode server (if already installed elsewhere)
      opencode serve --port 4096
      Then re-run this review.

  [3] Skip OpenCode bridge
      Continue without OpenCode. Other available bridges will run.

  [4] Abort the entire review

What would you like to do? (1/2/3/4)

Return status: HALTED, halt_reason: cli_not_found.


Advisory: No Provider Configured

⚠ OpenCode is installed but no AI provider is authenticated.

Configure a provider:
  opencode auth login    # Select and authenticate a provider

Alternatively:
  [1] Skip OpenCode bridge
  [2] Abort the entire review

Return status: HALTED, halt_reason: no_provider_configured.


Non-Interactive Environments

Return status: HALTED with the full advisory in halt_message. Never silently skip.


Step 3: Read Multi-Model Configuration

Before estimating timeout, check bridge settings for a models array. This is a suite-owned config file — separate from OpenCode's own ~/.config/opencode/ config — that tells the bridge which models to use for multi-model dispatch.

cat .bridge-settings.json 2>/dev/null

Extract bridges.opencode.models:

multi_model_dispatch:
  condition: "bridges.opencode.models is present AND has 2+ entries"
  action: "Spawn one execution per model — treat each as an independent participant"
  example_config:
    models: ["glm/glm-4-7", "kimi/moonshot-v1-8k", "qwen/qwen-plus"]

single_model_dispatch:
  condition: "models missing OR empty OR has exactly 1 entry"
  action: "Single execution using configured model or OpenCode's default"

Why multi-model matters: Each model has different training data, biases, and reasoning patterns. With 3 models configured, bridge-opencode becomes its own mini-council — 3 independent perspectives before findings even reach the cross-bridge synthesis layer.


Timeout Estimation

Use bridge-commons base timeout table and intensity multiplier, then apply the OpenCode-specific multiplier:

opencode_multiplier: 1.5   # Always applied — provider routing overhead

# Single-model dispatch:
final_timeout: base_timeout × intensity_multiplier × 1.5

# Multi-model dispatch (models run in parallel, not sequential):
final_timeout: max(per_model_base_timeout) × intensity_multiplier × 1.5
# NOT the sum — all model invocations run simultaneously

OpenCode internally dispatches to one or more providers — each provider call adds latency.


Step 3: Dispatch — Single-Model vs Multi-Model

Multi-Model Dispatch (when models has 2+ entries)

Spawn one parallel execution per configured model. All models receive the identical bridge_input — independence is the point.

Via HTTP API (preferred when server running):

# For each model in bridge_settings.opencode.models, in parallel:
SESSION_A=$(curl -s -X POST http://localhost:4096/session \
  -H "Content-Type: application/json" \
  -d '{"title": "opencode-{model_slug}-{session_id}"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

curl -s -X POST http://localhost:4096/session/$SESSION_A/message \
  -H "Content-Type: application/json" \
  -d '{
    "content": [{"type": "text", "text": "{constructed_prompt}"}],
    "model": "{model_A}"   # e.g., "glm/glm-4-7"
  }' &

SESSION_B=... # similarly for model B
SESSION_C=... # similarly for model C

wait  # collect all

Via CLI (fallback):

# Run in parallel — one per model
timeout {final_timeout} opencode run "{constructed_prompt}" --model {model_A} &
PID_A=$!
timeout {final_timeout} opencode run "{constructed_prompt}" --model {model_B} &
PID_B=$!
timeout {final_timeout} opencode run "{constructed_prompt}" --model {model_C} &
PID_C=$!
wait $PID_A $PID_B $PID_C

If any model invocation times out or errors → mark it as skipped in instances_completed and continue with remaining results. Never block on a single model failure.

Post-dispatch: Mini-Synthesis within bridge-opencode

After all model invocations complete, run a mini-synthesis before returning to deep-council:

  1. Deduplication: Findings with >70% description overlap across models → merge (inherit highest severity, list contributing models as confirmed_by_models)
  2. Model-confirmed: Merged findings are elevated (intra-bridge_multi_model_confirmed: true)
  3. Single-model findings: Retained with model attribution
  4. Verdict: Apply bridge-commons verdict logic to the merged finding set

This mini-synthesis is the intra-bridge equivalent of deep-council's cross-bridge Stage B — but lighter (no full DA challenge round, just deduplication and model-agreement detection).


Single-Model Dispatch (when models is empty/missing or has 1 entry)

Proceed to Step 3A or 3B with the single configured model (or OpenCode's default if none specified).


Step 3A: Execute via HTTP API (Preferred)

The OpenCode HTTP server exposes a REST API. Use it when the server is already running.

OpenAPI spec available at: http://localhost:{port}/doc

Create a session and send a message

# Create session
SESSION=$(curl -s -X POST http://localhost:4096/session \
  -H "Content-Type: application/json" \
  -d '{"title": "bridge-review-{review_id}"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# Send prompt — use bridge-commons Agent Prompt Template for the constructed_prompt
curl -s -X POST http://localhost:4096/session/$SESSION/message \
  -H "Content-Type: application/json" \
  -d '{
    "content": [{"type": "text", "text": "{constructed_prompt}"}],
    "model": "{provider/model}"
  }'

For the bridge-commons Post-Analysis Protocol, use the same session for each round — the HTTP session maintains full conversation history, so Round 2+ only needs the context packet injected. Run each role as a separate message (or separate session per role for parallelism):

# Round 2 message — session already has Round 1 history
curl -s -X POST http://localhost:4096/session/$SESSION/message \
  -H "Content-Type: application/json" \
  -d '{
    "content": [{"type": "text", "text": "{role-specific Round N prompt from bridge-commons context packet}"}]
  }'

For true parallel role execution within a round, create one session per role — embed the previous-round outputs explicitly since sessions don't share state:

# Parallel round execution — one session per role, context embedded in each
CHALLENGER_SESSION=$(curl -s -X POST http://localhost:4096/session \
  -H "Content-Type: application/json" \
  -d '{"title": "challenger-round-2-{session_id}"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
# ... then send challenger Round 2 prompt with embedded context

Model format

Models must use provider/model format:

model_format: "provider/model"
examples:
  - "anthropic/claude-sonnet-4-20250514"
  - "openai/gpt-4o"
  - "google/gemini-2.0-flash"
  - "glm/glm-4-flash"          # If GLM configured
  - "qwen/qwen-plus"           # If Qwen configured

selection_strategy:
  - Use default model if no preference (omit model field)
  - Or pass the model configured in the caller's context

Authentication (if server has password)

# With auth: -u opencode:$OPENCODE_SERVER_PASSWORD
curl -s -u opencode:$OPENCODE_SERVER_PASSWORD \
  -X POST http://localhost:4096/session/...

Agent selection (optional)

# Use the built-in 'plan' agent for read-only analysis
curl -s -X POST http://localhost:4096/session \
  -H "Content-Type: application/json" \
  -d '{"title": "...", "agent": "plan"}'

Built-in agents:

  • plan — restricted, read-only, suited for analysis tasks
  • build — full tool access (not appropriate for review-only)

Step 3B: Execute via CLI (Fallback)

Build the prompt using the bridge-commons Agent Prompt Template.

timeout {final_timeout} opencode run "{constructed_prompt}" \
  --format json \
  --model {provider/model}

Important: opencode (bare) opens the interactive TUI. Always use opencode run "..." for programmatic use.

For the Post-Analysis Protocol via CLI, use separate opencode run calls per round — no session continuity. Embed the full previous-round outputs and context packet in each Round N prompt (stateless context passing, same pattern as Gemini CLI).

CLI Error Handling

Exit codeMeaningAction
0SuccessParse JSON event stream for final message
124TimeoutReturn SKIPPED, skip_reason: timeout_after_{n}s
OtherCLI errorCapture stderr, return SKIPPED with detail

Output

See bridge-commons Output Schema. Bridge-specific fields:

{
  "bridge": "opencode",
  "model_family": "multi-provider",
  "connection_used": "native-dispatch | http-api | cli",
  "dispatch_mode": "multi-model | single-model",
  "models_configured": ["glm/glm-4-7", "kimi/moonshot-v1-8k", "qwen/qwen-plus"],
  "models_used": ["glm/glm-4-7", "kimi/moonshot-v1-8k"],
  "instances_spawned": 3,
  "instances_completed": 2,
  "intra_bridge_confirmed": 4
}
  • models_configured: full list from .bridge-settings.json
  • models_used: models that successfully completed (subset if any timed out)
  • instances_spawned: number of parallel executions launched
  • instances_completed: number that returned results (may be less than spawned)
  • intra_bridge_confirmed: count of findings confirmed by 2+ models within this bridge (before cross-bridge synthesis)

Output ID prefix: O (e.g., O001, O002). In multi-model mode, prefix per model: O-glm-001, O-kimi-001, etc. Merged findings use: O-merged-001.


Notes

  • HTTP API is preferred — use it when opencode serve is already running (lower overhead, session continuity)
  • opencode runopencode — bare opencode opens the interactive TUI; always use opencode run "..." for scripted use
  • Model format is provider/model — e.g., anthropic/claude-sonnet-4-20250514, not just claude
  • plan agent is the safe choice for review tasks (read-only mode)
  • 1.5× timeout multiplier always applies (provider routing overhead)
  • HALTED ≠ SKIPPED — HALTED requires user input before the review can proceed

Source

git clone https://github.com/mikeng-io/agent-skills/blob/master/skills/bridge-opencode/SKILL.mdView on GitHub

Overview

Bridge-opencode is a reference adapter that enables model-agnostic, multi-provider reviews by routing tasks through OpenCode. It’s designed for orchestrating skills to read via the Read tool, supports pre-flight checks, an HTTP API server path (preferred), and a CLI fallback, with embedded flags and model formats.

How This Skill Works

At runtime, the bridge selects the best execution path: native dispatch inside an OpenCode session, the HTTP API path, or a CLI path. It performs pre-flight validation, checks for provider authentication, and then routes the task through OpenCode to a configured provider, returning the results to the caller for seamless integration with orchestrating skills.

When to Use It

  • You need a second opinion from a different model family than the current executing skill.
  • OpenCode is configured in your environment and you want to route tasks through its multi-provider routing layer.
  • You want low-latency routing via the native OpenCode session (internal agent routing).
  • OpenCode isn’t available and you must fall back to the CLI path.
  • You are performing multi-model reviews (e.g., deep-council, deep-review, deep-audit) and want consistent OpenCode routing.

Quick Start

  1. Step 1: Run pre-flight checks to determine the best path (native dispatch, HTTP API, or CLI).
  2. Step 2: If native or HTTP API is available, route the task accordingly; if not, follow the advisory to install or configure OpenCode.
  3. Step 3: Re-run the task so the orchestrating skill consumes the OpenCode-backed result.

Best Practices

  • Verify an active OpenCode session (OPENCODE_SESSION_ID) before triggering the bridge.
  • Prefer the native dispatch path to minimize latency when inside an OpenCode session.
  • If using the HTTP API path, ensure the server port (default 4096) is reachable and respect OPENCODE_PORT if set.
  • When using the CLI path, ensure at least one provider is authenticated before proceeding.
  • Always surface advisory options clearly if a path cannot be established, rather than failing silently.

Example Use Cases

  • A deep-audit task is routed through native OpenCode dispatch inside the current session for a quick cross-check against the primary model.
  • A deep-review task is sent via the HTTP API path to the OpenCode server on port 4096 for cross-model validation.
  • A multi-model evaluation is performed by falling back to the CLI path when OpenCode is installed but not actively running.
  • An orchestrating skill detects no OpenCode session and uses the advisory path to install or start the server, then reruns the task.
  • An agent with no configured providers triggers the advisory flow to configure a provider and proceed with the review.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers