Views
Top-level view blocks that compose streams into a spreadsheet, with computed columns that run a graph for each row.
What it is. A spreadsheet over your streams. A view maps each stored stream row into a typed row, and can add computed columns whose value comes from running a workflow once per row.
Use it when you want to see and work with stream data as a table, or add a column that is calculated per row by a graph (for example, an AI enrichment or a lookup) rather than stored on the original stream.
Works with streams (the source rows) and workflows (the graph behind each computed column). A view is read/derived data: nothing in a .swirls file reads from a view. You see it in the Swirls Cloud UI as a spreadsheet, and read it through the API.
Views are declared at the top level. A view block names the streams it composes, defines a row schema, maps each source row with a columns @ts block, and optionally declares computed columns. Each computed column runs a graph once per row to produce that cell's value.
Views are materialized only in deployed projects (hosted on Swirls Cloud). The local CLI worker does not build views.
Top-level view block
| Field | Type | Required | Description |
|---|---|---|---|
label | string | No | Display name. Defaults to the view's name. |
description | string | No | Description. |
streams | list | Yes | Stream block names this view composes. Their rows become the view's rows. |
schema | @json { } or named schema | Yes | JSON Schema for one mapped (non-computed) row. |
columns | @ts { } | Yes | Maps one source stream row into the row shape (validated against schema). |
computed | block | No | Named computed columns, each running a graph per row. |
enabled | boolean | No | When false, the view is not materialized. |
Each computed column (inside computed { }):
| Field | Type | Required | Description |
|---|---|---|---|
graph | identifier | Yes | Workflow run once per row to compute this column. |
input | @ts { } | Yes | Maps the row into the graph's trigger input (returns an object). |
output | @ts { } | No | Maps the graph result into the cell value. Omit to store the graph output directly. |
computed is a block, not a key: value field — write computed { ... } with no colon, the same way versions { } is written inside a stream block.
view topic_dashboard {
label: "Topic dashboard"
description: "One row per stored topic, enriched with sentiment"
streams: [store_topic_tokens]
schema: @json {
{
"type": "object",
"required": ["topic", "tokens"],
"properties": {
"topic": { "type": "string" },
"tokens": { "type": "number" }
}
}
}
columns: @ts {
return {
topic: context.streams.store_topic_tokens.output.topic,
tokens: context.streams.store_topic_tokens.output.tokens
}
}
computed {
sentiment {
graph: enrich_topic
input: @ts {
return { topic: context.row.topic }
}
output: @ts {
return context.output.root.sentiment
}
}
}
}How rows are built
A view has one row per source stream row.
-
columnsruns once per source row. The originating row is available ascontext.streams.<streamName>.output(andcontext.streams.<streamName>.<version>.output, e.g..v1.output). Only the stream that produced the current row is present. Return the mapped row object — it is validated against the viewschema, exactly like a stream'sprepareis validated against its version schema. -
Computed columns each run a workflow once per row:
inputreceivescontext.row(the mapped row fromcolumns) plus the samecontext.streams.<name>. Return the object passed to the graph as its trigger input.outputreceivescontext.output(the completed graph's leaf node outputs, keyed by leaf node name, the same shape a streampreparesees) pluscontext.row. Return the cell value. Withoutoutput, the cell value is the graph's output directly.
Computed columns run real workflows
Every computed cell is a workflow execution. A view over a busy stream with computed columns can launch a large number of runs, so add computed columns deliberately.
- Cells move through
pending → running → completed → failed. The spreadsheet shows a loading state until each cell settles. - Computed-column runs are billed against
execution_credits, the same as workflows started by a trigger. When the org is over quota, the cell settles asfailedrather than running for free. - New rows materialize as the source workflow completes. Deploying a view backfills existing stream rows. Recompute is available from the cloud UI and re-runs computed columns idempotently per row.
Avoid execution loops
A computed column must not run a graph that writes back into a stream the same view composes. That would make every materialized row enqueue another graph run, which writes another row, forever.
The validator rejects this at deploy time:
View "X" creates an infinite execution loop: a computed column runs a graph that writes a stream this view (or a view it feeds) composes.
It catches both the direct case and chains across multiple views. Point computed columns at graphs that enrich or look things up — not at graphs that append to the view's own source streams.
Validation rules
- View names must match
^[a-zA-Z0-9_]+$; duplicate names error. streamsis required and non-empty; each entry must name a declared stream, and listing a stream twice errors.schemaandcolumnsare required;columnsmust be a non-empty@tsblock.- Each computed column needs a
graphnaming a declared workflow and a non-emptyinput; an emptyoutputerrors; duplicate computed column names error. - Execution-loop cycles are rejected (see above).