engine.placement runs on a worker process of a named pool instead of on the server that orchestrates the run. Retries, error routing, timeouts, pause and skip, checkpoints and status work as they do for a local node.
Remote workers are an optional part of the build and are off by default.
When to use it
Place a node on a worker when it is heavy, must run close to a resource (a private network, a database, a GPU host), or should not compete with the engine for CPU and memory. The server that admits and tracks runs is called the control plane. It still sees every message of a placed node, so placement moves the work, not the data path.How it works
- Workers connect out to the control plane over a persistent connection, so a worker needs no inbound port.
- A worker registers with a shared token, its id, its pools, the plugin types it may run and its capacity.
- A registration or a lease renewal keeps the worker listed for
yukta.workers.lease(default15s). A worker that misses it is dropped. Workers renew every third of the lease. - For each attempt at a node, the control plane opens one channel to a chosen worker. The node’s input messages go down it and the output comes back, with back-pressure in both directions. A cancel on the control plane cancels the attempt on the worker.
- The worker runs the real plugin and sends heartbeats while it works, which restart the node’s idle clock.
Selection rule
For each attempt the control plane picks a worker that:- Is connected and not draining.
- Serves the node’s pool.
- Lists the node’s plugin type in its
yukta.workers.plugin-types. - Has a free slot: its capacity minus the larger of the slots it reports and the attempts the control plane has already sent it.
retry policy applies.
Placing a node
Addplacement to the node’s engine object. A placement without pool uses the pool default.
This workflow node calls an internal service and runs on a worker in the private-net pool, with up to three attempts:
What can be placed
A workflow that places a node needs a control plane built with the workers switch. Without it, preparing the workflow fails with an error that names the switch.
Failure and retry
- A worker that disappears in the middle of an attempt fails that attempt with an error that names the worker. The engine’s retry can land on another worker.
- Delivery is at-least-once. If a worker dies after the effect and before the attempt completes, the effect can happen twice. Make placed plugins idempotent on the message id. See Checkpoints and resume.
- A worker that reports bad input keeps that meaning and is not retried. Every other error class arrives as a generic execution error that carries the class name in its text, so
retryOnandnoRetryOnrules that match on the original class do not see it. - Messages cross as plain JSON values. Types that exist only inside the worker are not preserved.
- Run budgets and rate limits (for example for
LLM_CALL) are counted inside each worker process, not for the run as a whole. - Live log lines written by the plugin on the worker do not reach the execution’s log stream.
Drain on stop
A worker that stops first tells the control plane that it is draining, so it receives no new attempts. It then waits up toyukta.workers.drain-timeout (default 30s) for the attempts it is running. Anything still running after that fails when the connection closes, and the engine retries it on another worker. A rolling restart of workers therefore does not cut off attempts that finish within the timeout.
If a worker loses the control plane, it reconnects with a pause that grows from 1 second to 30 seconds and does not give up.
Security
- Token. Every worker presents the shared
yukta.workers.token. The control plane compares it in constant time and refuses a wrong one. - Mutual TLS. Without TLS the connection is plain TCP. To encrypt it and authenticate both sides, give the control plane a certificate and require a client certificate, and give each worker its own:
- The worker verifies the control plane’s host name against its certificate.
- A worker runs only the plugin types it lists. A worker with an empty
yukta.workers.plugin-typesruns nothing. A compromised control plane cannot make a worker run a type it was not started with. - The plugin runs inside the worker process. The worker’s own settings and environment apply: the process allow-list, the LLM and MCP filters, the variable allow-list and the secret environment variables. Configure each worker as carefully as the control plane. See Security.
- Run the same build on the control plane and on workers. The messages between them carry no version.
Roles and build switches
The same executable is a control plane or a worker, chosen by settings:
A worker is a full Yukta process. When you run several on one machine, give each its own
server.port.
yukta.workers.plugin-types. See Deployment.
Settings
Observing workers
yukta.workers (connected workers) and yukta.worker.slots (free slots across them) show capacity. Alert when free slots stay at zero while nodes fail with “No connected worker”.
With high availability, list every control plane in each worker. A standby refuses registration with “this server is not the leader”, and the worker ends up on the leader.