Continuum stores operator-facing metadata on continuum_runs.attributes, a JSONB
map set when a run starts or updated later by surrounding application code.
{:ok, run_id} =
Continuum.start(MyApp.OrderFlow, %{order_id: "ord_123"},
attributes: %{region: "eu", order_type: "subscription"}
)
:ok = Continuum.set_attributes(run_id, %{customer_tier: 4})Attributes are not journaled workflow history. They are metadata for dashboards, operators, and application read paths, and workflow code cannot read them during replay.
Structured Queries
Use Continuum.query/1 with a closed :where spec:
{:ok, page} =
Continuum.query(
where: [
{:eq, :state, :suspended},
{:eq, [:attributes, "region"], "eu"},
{:gte, :started_at, ~U[2026-06-01 00:00:00Z]}
],
order_by: {:desc, :started_at},
page: 1,
per_page: 50
)Supported run fields are :id, :run_id, :state, :workflow, :started_at,
and :completed_at. Supported operators are :eq, :neq, :lt, :lte, :gt,
:gte, and :in for run fields. Attribute filters support :eq and :neq on
paths like [:attributes, "region"].
per_page is capped at 100. Continuum.get_run/2 loads a single run by id.
Indexing
The v0.5 migration adds a GIN index on continuum_runs.attributes. Attribute
updates merge JSON-encodable map data into the existing metadata and do not append
events.