Durable workflows.
One binary.
Just NATS.
dagnats runs graphs of tasks, agent loops and human approvals. It retries what fails and resumes after a crash, with NATS JetStream embedded in the same process. No Postgres, no Redis, no broker to run.
go install github.com/danmestas/dagnats/cmd/dagnats@latestApache-2.0 · Go · alpha, breaking changes possible
Everything a workflow engine needs. Nothing it has to depend on.
State is an event log in JetStream with snapshots in KV. Kill the process, start it again, and in-flight work picks up from the last event.
One binary, zero databases
Deploy is scp and serve. No migrations, no Redis to operate, no broker to configure.
Crash-safe by default
Every transition is an event in JetStream. A restart replays to the last one and carries on.
Agent steps are first-class
AgentLoop, Planner, Approval and WaitForEvent are step types, not patterns you rebuild per project.
Inspectable to the byte
Every event is a JSON message on a subject. Tail any run live from any terminal.
Bounded everywhere
No unbounded queues, retries or recursion. Every loop has a fixed upper limit.
Clusters when you need them
Three or five nodes, every stream replicated, routes over your private network. Leases and leader election built in.
From zero to a running workflow in four commands.
dagnats serve starts NATS, the orchestrator, the API, the console and the trigger system in one process. There is no step five.
$ go install github.com/danmestas/dagnats/cmd/dagnats@latest $ dagnats serve # one process, embedded NATS $ dagnats workflow register hello.json $ dagnats run start hello --watch ✓ greet completed 12ms ✓ run completed
All state lives in JetStream and KV. That is the whole system.
Each fire becomes an event on the history stream, deduplicated by message ID.
Timeouts, sleeps and retries are timers on a stream, not a scheduler you run.
Go workers in-process or anywhere on NATS; anything else over the HTTP bridge.
Compared to neighbors
| dagnats | Temporal | Hatchet | Inngest | |
|---|---|---|---|---|
| Stack | NATS only | Postgres + Cassandra | Postgres + RabbitMQ | Postgres + Redis |
| Binaries | 1 | ~5 | ~3 | hosted |
| Open source | yes | yes | yes | partial |
| Native agent steps | yes | no | yes | yes |
| SDKs | Go + HTTP bridge | many | 3 | 3 |
| Self-host | trivial | involved | moderate | n/a |
Open-source distributions as of writing. Approximate; orientation only.
What it is not
dagnats is young and single-tenant by design. There is one Go SDK plus an HTTP bridge; a native TypeScript or Python SDK is yours to write.
Skip it for sub-millisecond task routing (use a queue), for dependency-free batch jobs (use a worker pool), and where eventual consistency would surprise you (use a database with transactions).