Configure a managed iii engine through worker-compose.yaml or a directly supervised engine through config.yaml. Use for engine ports, RBAC via the rbac-proxy worker, observer limits, streams, sandboxes, and configuration storage.
86%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
iii has two engine configuration modes. Do not mix them.
The presence of engine: means that Compose owns the engine process. Engine worker values are
direct mappings; there is no nested config: field.
namespace: orders
engine:
url: ws://127.0.0.1:49134
registration_namespace_grace_ms: 5000
workers:
configuration:
adapter:
name: fs
config:
directory: ./config
iii-worker-manager:
host: 127.0.0.1
port: 49134
iii-http-functions: {}
iii-stream:
host: 127.0.0.1
port: 3112
iii-sandbox:
auto_install: true
containers: {}Start it with:
iii compose --namespace orders-daemon --up --file worker-compose.yamlengine.url defaults to ws://127.0.0.1:49134 and uses Compose's ${VAR:-default} expansion.
engine.workers stays opaque until the engine reads the generated YAML, so its values use
${VAR:default} and retain numeric types. Compose materializes an owner-only config under
<project-dir>/.iii/compose/<daemon-namespace>/ and removes it after clean shutdown. With
III_COMPOSE_STATE_DIR, it uses <state-root>/<project-slug>/<daemon-namespace>/. Changing engine:
requires restarting Compose. Do not combine a managed file with explicit --engine.
Allowed engine worker base names are:
configurationiii-worker-manageriii-http-functionsiii-streamiii-sandboxUse #instance for another instance of an allowed worker. iii-engine-functions,
iii-telemetry, and iii-observability are injected automatically and must not be declared.
HTTP, cron, queue, state, pubsub, bridge, application, and custom workers belong under
containers:. Add registry packages with:
iii trigger -n orders-daemon compose::add worker=stateSince 0.25 the engine reads an optional top-level observers: section (iii-observe explains the
model). Every key is optional; these are the defaults:
observers:
local_dispatch: true # let SDKs run a worker's own functions in-process
max_per_connection: 1024 # observers one connection may own (LIMIT_EXCEEDED)
max_per_function: 4096 # observers one function may have (LIMIT_EXCEEDED)
max_observe_depth: 8 # deeper activations are dropped (LOOP_GUARD)
observer_grace_ms: 30000 # suspended observers of a disconnected worker wait this long
disposed_retention_ms: 3600000 # a worker back after the grace period is told they were disposed
owner_ack_timeout_ms: 30000 # an unacknowledged add fails with OWNER_TIMEOUT
activation_timeout_ms: 30000 # an unanswered activation frees its slot and counts as TIMEOUT
default_max_in_flight: 64 # max_in_flight of an observer that sets none
max_queue_per_observer: 1024 # queued activations beyond max_in_flight (then OVERFLOW)config.yaml it sits next to workers:. In a managed Compose file it goes under
engine.observers and is passed through as written.observers.local_dispatch: false turns off in-process calls for every worker.engine::observers::list({ function_id?, namespace?, worker? }) and
engine::observers::get({ id }) (results are filtered to functions the caller may invoke).
engine::observers::dispose({ id }) is allowed for the observing worker and unrestricted callers.iii.observer.activations.total{function_id,delivery},
iii.observer.dropped.total{function_id,reason}, iii.observers{state},
iii.observer.reports.total{function_id},
iii.observer.activation.failures.total{function_id,reason}; locally dispatched calls are counted
in iii.invocations.total with dispatch="local".rbac-proxyKeep the engine port internal and put the rbac-proxy worker in front of it when
untrusted workers, browsers, or agents need to connect:
iii trigger -n orders-daemon compose::add worker=rbac-proxyrbac-proxy opens its own WebSocket port, speaks the worker protocol verbatim, and at the boundary
authenticates each connection (rbac.auth_function_id), gates every invocation and trigger binding
(rbac.expose_functions, plus allowed_functions / forbidden_functions from the auth result),
namespaces a session's registrations (function_registration_prefix), runs
middleware_function_id and the registration hooks, and filters engine::* discovery results to
what the caller may invoke. Its settings live in the configuration worker under id rbac-proxy:
host: 0.0.0.0
port: 49200 # the public RBAC port
engine_url: ws://127.0.0.1:49134 # the trusted internal engine listener
rbac:
auth_function_id: my-project::auth-function
expose_functions:
- match("api::*")RBAC is mandatory on untrusted networks: only the proxy's port may face one, never the engine port,
and a public proxy must always set auth_function_id. Full schema: https://workers.iii.dev/workers/rbac-proxy.
Observers under RBAC (0.25 engine): creating one requires that the session may invoke both the
observed function and the target, or it fails with FORBIDDEN. The engine's rbac: settings
accept on_observer_registration_function_id, a hook with the same contract as
on_trigger_registration_function_id: an object answer may rewrite function_id,
target_function_id, args, filters, and metadata; any other answer denies with FORBIDDEN.
Sessions with a middleware_function_id get no local dispatch, so the middleware always runs.
Check the rbac-proxy worker's docs for the version that forwards the observe messages.
Keep list-shaped config.yaml only when systemd, Kubernetes, or another supervisor owns the
engine:
workers:
- name: configuration
config:
adapter:
name: fs
config:
directory: ./config
- name: iii-worker-manager
config:
host: 127.0.0.1
port: 49134Start the engine and external Compose daemon separately:
iii --config config.yaml
iii compose --namespace orders-daemon --engine ws://127.0.0.1:49134 --up --file worker-compose.yamlThe external Compose file must omit engine:. III_URL may replace --engine. Direct config
expansion uses ${VAR:default} and accepts only the same five engine-owned worker types. Any
project worker stops startup/reload with UNSUPPORTED_CONFIG_WORKERS.
127.0.0.1; expose only the rbac-proxy port.rbac.auth_function_id on every public proxy and keep expose_functions narrow.compose::status for process ownership and engine::workers::list for live connections.iii ps to find iii processes on the machine, including orphaned workers, and iii kill --orphans, --port or --compose to stop them.compose::add never edits engine: or restarts the engine.engine: maps, direct config.yaml, engine-owned workers, ports,
adapters, RBAC via rbac-proxy, or engine lifecycle selection.config.yaml or iii worker.iii-core-primitives; for observer code and filters, use
iii-observe.iii-hq/iii
618a6fb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.