dagnats
A workflow engine for durable jobs and autonomous LLM coding pipelines. NATS is the only dependency. The deploy artifact is one Go binary.
| Project | dagnats — DAG workflow engine |
| Language | Go (module github.com/danmestas/dagnats) |
| Runtime deps | NATS JetStream (embedded) |
| Binaries | 1 (dagnats serve = orchestrator + API + triggers + NATS) |
| License | Apache-2.0 |
| Status | v0.1 · alpha · breaking changes possible |
Install install
$ go install github.com/danmestas/dagnats/cmd/dagnats@latest $ dagnats serve
That is the entire install. There is no step three. dagnats serve starts an embedded NATS server, the orchestrator, the API, and the trigger system in one process.
What it is overview
dagnats is a Go workflow engine. You describe work as a directed acyclic graph of tasks; dagnats runs the graph, retries failures, recovers from crashes, and reconstructs state from an immutable event log.
Its only infrastructure dependency is NATS JetStream, which is embedded in the same process. There is no Postgres to migrate, no Redis to monitor, no separate broker to configure.
Two audiences benefit. Backend engineers needing durable workflows that survive restarts get a single binary instead of a small fleet of services. Teams building autonomous coding pipelines get first-class step types — AgentLoop, Planner, Approval, WaitForEvent — that other engines treat as application-layer concerns.
Why you might want it why
- One binary, zero external databases. The deploy is
scp dagnats user@host && ./dagnats serve. No Postgres migrations. No Redis to operate. No broker. - Crash-safe by default. Workflow state is event-sourced into JetStream and snapshotted in KV. Kill the process, start it again, in-flight work resumes from the last event.
- Agent loops are first-class.
AgentLoop,Planner,Approval, and Continue-As-New are step types in the workflow language — not patterns you reimplement per project. - Inspectable. Every event is a JSON message on a stream.
nats sub "history.>"tails any workflow run live, in any terminal. - Bounded. No unbounded queues. No unbounded retries. No recursion. Every loop has a fixed upper bound. (TigerStyle — safety first.)
How it fits together architecture
All workflow state lives in NATS JetStream + KV — that is the entire system. There is no separate database.
Compared to neighbors comparison
| dagnats | Temporal | Hatchet | Inngest | |
|---|---|---|---|---|
| Stack | NATS only | PG + Cassandra | PG + RabbitMQ | PG + Redis |
| Binaries | 1 | ~5 | ~3 | hosted |
| OSS | 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 |
Comparison reflects open-source distributions as of writing. Approximate; orientation only.
What it is not limits
dagnats is young. It is single-tenant by design. There is one Go SDK plus an HTTP bridge for everything else; if you need a native TypeScript or Python SDK, you will be writing it.
Don't reach for it for sub-millisecond task routing (use a queue). Don't reach for it for embarrassingly-parallel batch jobs without dependencies (use a worker pool). Don't reach for it where eventual consistency would surprise you (use a database with transactions).
Get going start
$ 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
Walkthrough: /docs/get-started · Architecture: /docs/architecture · SDK reference: /docs/reference/sdk · Source: github.com/danmestas/dagnats.