skip to content
$worker

bridge

v0.1.7-rc.3

Bridge two iii engines — expose local functions on a remote engine and invoke/forward remote functions locally.

iiiverified
16 installs0 in 7d0 today
install
$iii trigger compose::add worker=bridge@0.1.7-rc.3
binarylicense: Apache-2.0bridgeenginefederationremotewebsocket
  • macOS: arm64 · x64
  • Linux: arm64 · armv7 · x64

exact versions are immutable; binary and bundle artifacts are digest-pinned.

skill doc

SKILL.md

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 worker add 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.