Platform Pipelines Agents Human review Self-improvement Observability Deployment Security Use cases Compare Docs Pricing Roadmap Get early access

Millstream vs Temporal

Temporal is a durable execution platform: a workflow is ordinary code whose event history is replayed to rebuild its state after a failure. Millstream is a pipeline platform: a declarative graph of steps connected by persisted streams of items, where some steps are code, some are LLM agents and some wait for a person.


At a glance

Millstream Temporal
Definition pipeline.yaml: triggers, streams, steps, CEL conditions Workflow and activity code, with SDKs in Go, Java, TypeScript, Python and other languages
Unit of durable work One delivery of one item to one step One workflow execution and its event history
Durability mechanism A database item log with fenced leases; outputs publish when a delivery is done Replay of the workflow's event history through deterministic workflow code
Code changes mid-run Runs pinned to the content hash of their package; millstream rollback reactivates a revision Workflow code changes that affect in-flight executions need versioning
Agents Agent actions with output schemas, a sandbox, transcripts, budgets and evals Activities that call a model, written by you
Human decisions review builtin with an inbox, editable fields, reason codes and timeouts Signals and updates; the inbox and its UI are yours to build
Laptop millstream run: engine, node, SQLite, API and UI in one process The CLI's development server, with your workers beside it
Licence Apache-2.0 core, commercial edition MIT
Status Pre-release: M1 to M5 built and tested Released, widely used

Where the models differ

Steps read and write streams

Millstream steps never reference each other: they read and write named streams. Several crawlers writing one stream merge their output, several steps reading one stream each receive every item, and inserting a step means pointing it at an existing stream:

dedupe:
  action: dedupe
  in: listings.raw
  out: listings.unique
  config: { key: "item.addressNorm + ':' + string(item.surfaceM2)", window: 30d }

In Temporal the same per-item fan-out is modelled by you, as child workflows or as activities over batches. Millstream records each item with its parents, so the UI shows the lineage of any report back to the listing it came from, and millstream replay --step score --since 7d runs a week of past items through a changed step.

No determinism rules on your code

Millstream never replays action code. An action is any program that reads JSON lines on stdin and writes them on stdout, so it may read the clock, call the network or change between releases. Idempotency comes from deterministic item ids and an idempotencyKey per delivery, stable across retries and new on replay. The trade-off is explicit: delivery is at-least-once, and an external system enforces the key.

Agents, people and cost are part of the model

An agent step declares its model, tools, network allowlist, maxTurns and maxCostUsd in its manifest. Its answer is validated against an output schema before it goes anywhere, and its transcript is stored with the attempt. A pipeline's budget.runUsd and budget.dayUsd are enforced by reservation at dispatch, so an agent delivery is leased only while the budget has room. A review step parks items in an inbox and measures the intervention rate per step. In Temporal each of these is application code you write and maintain.


When to choose Temporal


Using them together

The two meet over HTTP. A Temporal activity can start a Millstream run through a webhook trigger, POST /hooks/<pipeline>/<trigger>, passing an Idempotency-Key header: a retried activity sending the same key gets back the run it already fired. In the other direction, a Millstream action declared with effects: external can start a Temporal workflow and use the delivery's idempotencyKey as the workflow id, so a retried delivery finds the workflow it started.


Next

Pipelines · How agents run · Roadmap