Every run is its event log
State is rebuilt from an append-only log of events and never edited in place. What runs next is a pure function of that history, so a restarted server rebuilds a run from its events and carries on.
With plain scripts: state lives in memory or in rows that get overwritten, so a crash mid-step loses the work or repeats it.
orchestrate-core · Orchestrator::evaluate
Declarative flow, script steps when you need them
Add a Python, Rhai or shell task to any step’s tool pipeline. It gets the playbook’s retry and backoff policy, its start and result land on the event log, large outputs are kept as durable references, and credentials arrive by keychain alias instead of living in the script.
With plain scripts: a script that dies halfway leaves no record of what ran, retries are hand-rolled, and credentials sit in env files or code.
orchestrate-core · PipelineTask
Agents work inside a playbook
An agent step uses the same closed set of tool kinds and the same five policy actions as any other step. It can pick among the routes the playbook declares, only the server starts a step, and every step it runs is recorded on the log. Agents reach MCP servers over HTTP.
With plain scripts: an agent that writes and runs its own script has no fixed set of actions, nothing outside it deciding what runs next, and no durable record of what it did.
server · playbook policy validation
Scale in mid-step without dropping work
On shutdown a worker stops claiming, finishes what it is running, then leaves. A command that was never acknowledged goes to another worker, and a redelivered event is recognised by its id instead of being appended twice. Worker pools autoscale on the command backlog.
With plain scripts: a queue and a cron job either lose the job that was running when a pod went away, or run it again and record it twice.
worker · drain on SIGTERM
One fenced path for every write
Every change to the event log goes through a single fenced chokepoint, and the Rust compiler enforces that no other path exists. With leader election on, a writer that has lost its lease is refused. The log is EHDB, NoETL’s own event store: each append is synced to disk before it returns, and sealed parts are uploaded to object storage.
With plain scripts: naive leader election lets a paused old leader keep writing after it has lost the lease, and two writers corrupt the history.
ehdb · FencedEngine::write
Delivery is at-least-once: redelivered events are deduplicated by id within a bounded window, and steps that call external systems should be written to tolerate a retry.