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.invokefunctions.
Boundaries
- Prefer
forward:/expose:aliases overbridge.invoke; the escape hatches are for dynamic ids and one-offs, not the default path. bridge.invoke_asyncis fire-and-forget — it ignorestimeout_msand returnsnullimmediately (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
configurationworker'sbridgeentry (Console → Configuration → Workers → bridge), not documented here. bridge.invoke/bridge.invoke_async/ forward calls always collapse failures to abridge_errorcode, 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 remotefunction_idand wait for its return value (returned directly, no envelope); honors an optionaltimeout_ms(default30000).bridge.invoke_async— hand a remote call to the WebSocket send queue and returnnullimmediately;timeout_msis 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, thenIII_URL, thenws://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 whenIII_URLselects 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_functionis the name registered on the remote (defaults tolocal_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 registerslocal_functionon this engine so any caller reaches the remote'sremote_function;timeout_msoverrides the per-call deadline (default30000). 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.