Skip to main content

bridge

Connect this engine to another iii engine over a long-lived WebSocket so functions call across the boundary. Wire stable ids with `forward:`/`expose:`; `bridge.invoke` is the ad-hoc escape hatch.

Source facts

Repository
iii-hq/workers
Last source activity
August 28, 2026 at 22:59
Detected SKILL.md language
English
Stars
114
Forks
26

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
bridge
tags
bridge, websocket, remote, cross-engine, invoke
description
Connect this engine to another iii engine over a long-lived WebSocket so functions call across the boundary. Wire stable ids with `forward:`/`expose:`; `bridge.invoke` is the ad-hoc escape hatch.
# bridge The `bridge` worker connects this iii engine to another iii instance over `iii-sdk` so functions on either side can call across the boundary. It keeps a local/control WebSocket to this engine, selected by `--url`, `III_URL`, or the local default. A separate WebSocket connects to the remote target selected by `config.url` and reconnects when that value changes. Both connections stay open for the worker's lifetime. There are no trigger types. The worker is configuration-driven. The primary surface is two list-shaped config fields (`forward` and `expose`) that wire stable function ids on both sides; once configured, callers reach across the bridge by invoking those stable ids with the normal `iii.trigger({ function_id, payload })` — no bridge-specific call shape. Two functions (`bridge.invoke`, `bridge.invoke_async`) are also registered as ad-hoc escape hatches for the rare case where the remote function id is dynamic at runtime. Install it with `iii trigger compose::add worker=bridge`. This is a standalone replacement for the engine’s legacy built-in bridge service: it must not run on the same engine, since both register the same `bridge.invoke` / `bridge.invoke_async` ids (plus any forward/expose ids) — the worker refuses to boot while the legacy built-in remains connected. ## When to Use - Two iii engines need to call each other's functions over a stable, long-lived connection. - You want a remote function to appear as a local id (`forward:`) so the bridge is invisible at the call site. - You want to expose specific local functions to a remote engine (`expose:`). - The remote function id is dynamic, or you are prototyping / probing connectivity — reach for the ad-hoc `bridge.invoke` functions. ## Boundaries - Prefer `forward:` / `expose:` aliases over `bridge.invoke`; the escape hatches are for dynamic ids and one-offs, not the default path. - `bridge.invoke_async` is fire-and-forget — it ignores `timeout_ms` and returns `null` immediately (the SDK requires a function to return a value; a later remote rejection is never surfaced to the caller). - Forward aliases and exposed ids are operator-wired per deployment through the `configuration` worker's `bridge` entry (Console → Configuration → Workers → bridge), not documented here. - `bridge.invoke` / `bridge.invoke_async` / forward calls always collapse failures to a `bridge_error` code, regardless of the remote's real error — a successful async return only means the message was queued, not that the remote ran. Expose calls are the exception: they forward the local function's real error code/message/stacktrace untouched. ## Functions - `bridge.invoke` — call a remote `function_id` and wait for its return value (returned directly, no envelope); honors an optional `timeout_ms` (default `30000`). - `bridge.invoke_async` — hand a remote call to the WebSocket send queue and return `null` immediately; `timeout_ms` is ignored and no remote response is surfaced. Both take `{ function_id, data?, timeout_ms? }`. Reach for them only when a `forward:` alias is wrong or impossible; for repeated calls to the same `(local, remote)` pair, configure a `forward:` alias and call the local id instead. Failures return a stable `code` (`deserialization_error` for a malformed input, `bridge_error` otherwise). ## Configuration Configuration lives in the `configuration` worker's `bridge` entry (hot-reload — no restart needed for most changes): - The local/control engine connection uses `--url`, then `III_URL`, then `ws://127.0.0.1:49134`. This is where the worker registers and receives local invocations. - `url` — WebSocket URL of the remote target. Set it explicitly when `III_URL` selects a non-default local/control engine. Changing it reconnects to the new remote. - `expose: [{ local_function, remote_function? }]` — functions on this engine the remote may call; `remote_function` is the name registered on the remote (defaults to `local_function`). Newly added entries register live on the current remote connection. - `forward: [{ local_function, remote_function, timeout_ms? }]` — local aliases that proxy outbound to a remote function. The worker registers `local_function` on this engine so any caller reaches the remote's `remote_function`; `timeout_ms` overrides the per-call deadline (default `30000`). Newly added entries register live. Removing a `forward`/`expose` entry does not un-register its handler (the SDK has no unregister): the function id stays callable but returns a `bridge_error` until the worker restarts. For backward compatibility, a missing remote `config.url` still falls back to `III_URL`, then `ws://0.0.0.0:49134`. In Compose or another supervised setup, always set `config.url` so this legacy fallback cannot point the remote target back at the local/control engine.
View on GitHub