SWIRLS_
Memory

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

FieldTypeRequiredDescription
labelstringNoDisplay name. Defaults to the view's name.
descriptionstringNoDescription.
streamslistYesStream block names this view composes. Their rows become the view's rows.
schema@json { } or named schemaYesJSON Schema for one mapped (non-computed) row.
columns@ts { }YesMaps one source stream row into the row shape (validated against schema).
computedblockNoNamed computed columns, each running a graph per row.
enabledbooleanNoWhen false, the view is not materialized.

Each computed column (inside computed { }):

FieldTypeRequiredDescription
graphidentifierYesWorkflow run once per row to compute this column.
input@ts { }YesMaps the row into the graph's trigger input (returns an object).
output@ts { }NoMaps 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.

  • columns runs once per source row. The originating row is available as context.streams.<streamName>.output (and context.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 view schema, exactly like a stream's prepare is validated against its version schema.

  • Computed columns each run a workflow once per row:

    • input receives context.row (the mapped row from columns) plus the same context.streams.<name>. Return the object passed to the graph as its trigger input.
    • output receives context.output (the completed graph's leaf node outputs, keyed by leaf node name, the same shape a stream prepare sees) plus context.row. Return the cell value. Without output, 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 as failed rather 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.
  • streams is required and non-empty; each entry must name a declared stream, and listing a stream twice errors.
  • schema and columns are required; columns must be a non-empty @ts block.
  • Each computed column needs a graph naming a declared workflow and a non-empty input; an empty output errors; duplicate computed column names error.
  • Execution-loop cycles are rejected (see above).

Further reading

  • Streams: the source rows a view composes
  • Workflows: the graph behind each computed column
  • Context: context.streams, context.row, context.output
  • Syntax: @ts / @json blocks

On this page