Skip to main content

Documentation Index

Fetch the complete documentation index at: https://iii.dev/docs/llms.txt

Use this file to discover all available pages before exploring further.

This page documents the wire-level protocol the engine and SDK workers exchange. Most projects use a language SDK (Node, Python, Rust, Browser) and never touch the protocol directly. The shapes below are the source of truth those SDKs serialize to.
Observability introspection (traces, logs, metrics, sampling rules, alerts, rollups) is owned end-to-end by the iii-observability worker.

Connection ports

The engine binds three ports of its own and runs alongside one more from the observability worker:
PortBound bySurface
3111engineREST API.
3112engineStream API (WebSocket; consumer-side stream subscriptions).
49134engineSDK WebSocket; this is what iii_sdk::register_worker opens.
9464iii-observability workerPrometheus metrics endpoint (typically exposed from the same container as the engine).
The console UI runs on 3113 and is launched separately by iii console.

Connection flow

A worker opens the SDK WebSocket (default ws://127.0.0.1:49134) and sends the registrations it holds in memory: each RegisterFunction, RegisterTrigger, and RegisterTriggerType it intends to expose. The worker then calls engine::workers::register to publish its own metadata (runtime, version, OS, PID, isolation), and the engine answers with a WorkerRegistered { worker_id } frame carrying the assigned UUID. The connection is bidirectional from that point on: the engine pushes InvokeFunction frames at the worker, and the worker pushes InvocationResult, additional registrations, or unregistrations back.

Message types

Every frame is a JSON object discriminated by message_type. The full set, defined on Message in engine/src/protocol.rs:
FrameDirectionPurpose
RegisterFunctionworker -> engineMake a function callable by function_id.
UnregisterFunctionworker -> engineDrop a previously registered function.
RegisterTriggerworker -> engineBind a function to a trigger instance.
UnregisterTriggerworker -> engineDrop a trigger binding.
TriggerRegistrationResultengine -> workerAck / error for a RegisterTrigger.
RegisterTriggerTypeworker -> engineDeclare a new trigger type the worker advertises.
RegisterServiceworker -> engineGroup related functions under a service id.
InvokeFunctionengine -> workerCall a registered function with a payload.
InvocationResultworker -> engineCarry the function’s result or error back.
WorkerRegisteredengine -> workerAcknowledge the worker, with the assigned worker_id.
Ping / PongbidirectionalLiveness; keeps idle connections from timing out.

RegisterFunction

{
  "message_type": "register_function",
  "id": "math::add",
  "description": "Add two numbers.",
  "request_format": {
    "type": "object",
    "properties": { "a": { "type": "number" }, "b": { "type": "number" } }
  },
  "response_format": { "type": "object", "properties": { "c": { "type": "number" } } },
  "metadata": { "owner": "math-team" },
  "invocation": null
}
id is required. description, request_format, response_format, and metadata are optional and feed the iii console and the agent-readable skills. invocation is reserved for external HTTP functions (HttpInvocationRef); leave it null for in-process handlers.

RegisterTrigger

{
  "message_type": "register_trigger",
  "id": "math::add@http",
  "trigger_type": "http",
  "function_id": "math::add",
  "config": { "api_path": "/math/add", "http_method": "POST" },
  "metadata": null
}
config is the per-trigger-type configuration; the shape is defined by whatever worker advertised that trigger_type (e.g. iii-http for http triggers). The engine responds with a TriggerRegistrationResult carrying an optional error: ErrorBody.

RegisterTriggerType

{
  "message_type": "register_trigger_type",
  "id": "webhook",
  "description": "HTTP webhook trigger",
  "trigger_request_format": { "type": "object", ... },
  "call_request_format": { "type": "object", ... }
}
trigger_request_format is the JSON Schema for the trigger’s per-binding config. call_request_format is the JSON Schema for the payload delivered to bound functions when the trigger fires.

InvokeFunction

{
  "message_type": "invoke_function",
  "invocation_id": "9f3c…",
  "function_id": "math::add",
  "data": { "a": 2, "b": 3 },
  "traceparent": "00-…",
  "baggage": "k=v,…",
  "action": { "type": "void" }
}
invocation_id is omitted on Void invocations (the worker has no result channel to reply on). traceparent and baggage carry W3C trace context. action is the routing flag (see Trigger actions below); absent / null means synchronous.

InvocationResult

Success:
{
  "message_type": "invocation_result",
  "invocation_id": "9f3c…",
  "function_id": "math::add",
  "result": { "c": 5 },
  "error": null,
  "traceparent": "00-…",
  "baggage": "k=v,…"
}
Failure:
{
  "message_type": "invocation_result",
  "invocation_id": "9f3c…",
  "function_id": "math::add",
  "result": null,
  "error": {
    "code": "invocation_failed",
    "message": "boom",
    "stacktrace": "TraceError: …"
  }
}
ErrorBody.code values the engine emits today include invocation_failed (handler threw), invocation_stopped (the owning worker disconnected mid-flight, so the engine cancels the in-flight call and surfaces this code to the caller), function_not_found, function_not_invokable, TIMEOUT (client-side timeout), FORBIDDEN (RBAC denial).

Trigger actions

InvokeFunction.action is tagged by type and lowercase-encoded on the wire:
Wire shapeMeaning
omitted / nullSynchronous; the worker replies with InvocationResult.
{ "type": "void" }Fire-and-forget; no invocation_id, no reply.
{ "type": "enqueue", "queue": "math" }Route through the named queue (provided by iii-queue).

Invocation lifecycle

For synchronous calls the engine assigns an invocation_id, forwards the InvokeFunction to the owning worker, and waits for the matching InvocationResult. For Void actions the engine forwards without an invocation_id and never expects a reply. For Enqueue the engine hands the invocation to the queue worker, which persists it and re-invokes the target function on a subscriber according to the queue’s retry policy.

Engine discovery functions

The engine registers a built-in set of functions under the engine::* namespace for introspection and worker lifecycle. Defined in engine/src/workers/engine_fn/mod.rs:
FunctionPurpose
engine::channels::createCreate a streaming-channel reader / writer pair.
engine::functions::listList every registered function (filterable by include_internal).
engine::workers::listList every connected worker with metrics.
engine::triggers::listList every registered trigger (filterable by include_internal).
engine::trigger-types::listList every registered trigger type with its config and call request schemas.
engine::workers::registerPublish the calling worker’s metadata (runtime, version, OS, PID, isolation).

Engine discovery triggers

TriggerFires when
engine::functions-availableA function is registered or unregistered.
engine::workers-availableA worker connects or disconnects.

Engine-collected metrics

These metrics are emitted by the engine regardless of which language SDK a worker uses. Names and units come from engine/src/workers/observability/metrics.rs.

Invocations

MetricInstrumentUnit
iii.invocations.totalcounterinvocations
iii.invocation.durationhistogramseconds
iii.invocation.errors.totalcountererrors

Workers

MetricInstrumentUnit
iii.workers.activegaugeworkers
iii.workers.spawns.totalcounterworkers
iii.workers.deaths.totalcounterworkers
iii.workers.by_statusgaugeworkers

Per-worker

MetricInstrumentUnit
iii.worker.memory.heap.bytesgaugebytes
iii.worker.memory.rss.bytesgaugebytes
iii.worker.cpu.percentgauge%
iii.worker.event_loop.lag.msgaugems
iii.worker.uptime.secondsgauges