| name | sigma-workbooks |
| description | Build, edit, and iterate on Sigma workbook specs โ the JSON definition you POST to /v2/workbooks/spec, covering pages, layout, controls, charts, KPIs, tables, formulas, and sources. The Sigma OpenAPI is the source of truth for every shape and field; this skill adds navigation, style guidance, and proven recipes for effective dashboards. Use when the user wants to construct a dashboard from a spec, add or modify pages / elements / controls / formulas, validate a spec before submission, or work through the workbook spec lifecycle programmatically. Requires an SIGMA_API_TOKEN โ obtain via the sigma-api skill first. |
Sigma Workbooks (Spec via REST API)
This skill helps you build effective Sigma workbooks by navigating the Sigma OpenAPI and applying style guidance + proven recipes beyond what the OpenAPI alone teaches.
Scope
The workbook spec โ the JSON you POST to /v2/workbooks/spec defining pages, elements, sources, formulas, and layout. Lifecycle around the workbook (embeds, grants, materialization schedules, bookmarks, sharing) is a separate API surface and out of scope here.
Sources of truth
- Sigma OpenAPI โ canonical schema for every request/response shape and field.
https://help.sigmacomputing.com/openapi/sigma-computing-public-rest-api.json
- Existing workbooks on the user's org โ concrete working specs, accessible via
GET /v2/workbooks/{id}/spec.
Everything in this skill is commentary, style guidance, and recipes layered on top of those two sources. When this skill and the OpenAPI disagree, the OpenAPI wins. When a feature exists in the OpenAPI but isn't covered here, fetch the OpenAPI and use what it documents.
Consulting the OpenAPI
The OpenAPI is the source of truth. The field lists and examples in this skill are illustrative, not exhaustive โ when you need the complete, current shape of anything, query the spec. Fetch once per session and inspect with jq:
curl -sf https://help.sigmacomputing.com/openapi/sigma-computing-public-rest-api.json > /tmp/sigma-api.json
jq '.paths."/v2/workbooks/spec".post.requestBody.content."application/json".schema' /tmp/sigma-api.json
Element, source, control, and format shapes are inlined under that path and identified by their kind value (e.g. bar-chart, kpi-chart, join, warehouse-table) โ not by a top-level schema name. Navigate by the kind discriminator:
jq -r '[.. | objects | select(.properties.kind.enum) | .properties.kind.enum[0]] | unique[]' /tmp/sigma-api.json
jq --arg k bar-chart 'first(.. | objects | select((.allOf? and any(.allOf[]?; .properties?.kind?.enum==[$k])) or .properties?.kind?.enum==[$k]))
| {required: ([.allOf[]?.required // .required] | add | unique), properties: ([(.allOf[]?.properties // .properties) | keys[]] | unique)}' /tmp/sigma-api.json
jq --arg k bar-chart 'first(.. | objects | select((.allOf? and any(.allOf[]?; .properties?.kind?.enum==[$k])) or .properties?.kind?.enum==[$k]))' /tmp/sigma-api.json
WebFetch works for the JSON too. Either path is fine.
No curl/jq on the machine (e.g. Windows without WSL)? scripts/wb-rep.rb
ships a capabilities subcommand that does the same three queries with
pure-Ruby Net::HTTP + JSON.parse โ no external tools required:
ruby scripts/wb-rep.rb capabilities
ruby scripts/wb-rep.rb capabilities --kind bar-chart
ruby scripts/wb-rep.rb capabilities --kind bar-chart --field source
Why bother: the API ships new fields and viz configurations regularly, and this skill covers the common surface, not every field. If you want a capability and don't see it documented here, assume it may exist and check the spec before concluding it doesn't โ the kind query above answers in seconds.
Auth
Authenticate via the sigma-api skill first to populate $SIGMA_BASE_URL and $SIGMA_API_TOKEN.
Recommended Workflow
These are guidelines, not mandates โ but they prevent the failure modes that show up most often when drafting from scratch.
Schema drift signal: an error about request shape (invalid argument, unknown field, missing required field, unexpected property) usually means this skill is stale on that detail. Fetch the OpenAPI and compare; the canonical shape is there.
Step 0 โ Authenticate, capture user identity
USER_ID=$(curl -s -H "Authorization: Bearer $SIGMA_API_TOKEN" \
"$SIGMA_BASE_URL/v2/whoami" | jq -r '.userId')
HOME_FOLDER_ID=$(curl -s -H "Authorization: Bearer $SIGMA_API_TOKEN" \
"$SIGMA_BASE_URL/v2/members/$USER_ID" | jq -r '.homeFolderId')
If the user provided a target image (a screenshot, mockup, or PDF of a dashboard they want reproduced), pause here and load reference/workflows/from-image.md โ it adds explicit observation, description, and validation steps that have to happen before normal data discovery. The standard workflow alone tends to produce workbooks with the right vibe but the wrong shape when the input is visual.
Step 1 โ Find a reference workbook to study
Any existing workbook on the user's org doubles as a template. List and pick one with similar content:
curl -s -H "Authorization: Bearer $SIGMA_API_TOKEN" \
"$SIGMA_BASE_URL/v2/workbooks?limit=50" | jq '.entries[] | {workbookId, name}'
If no relevant workbook exists, pick any โ the goal is studying spec structure, not matching content. If the org has no workbooks at all, draft from scratch using the OpenAPI shapes + this skill's recipes.
Step 2 โ Study the reference spec
YAML is the canonical format for workbook specs in this skill โ easier to read, diff, and review than JSON. Sigma's API accepts both (Content-Type: application/yaml or application/json); Accept: application/yaml is the default on GET /v2/workbooks/<id>/spec. Use yq to inspect spec YAML the same way you'd use jq on JSON.
curl -s -H "Authorization: Bearer $SIGMA_API_TOKEN" \
"$SIGMA_BASE_URL/v2/workbooks/<reference-workbook-id>/spec" \
> /tmp/reference-spec.yaml
Look at source structure, column ID patterns, formula syntax, element naming, layout XML idioms. The pages array shape is exactly what you'll POST when creating.
Step 3 โ Discover data sources
Load reference/workflows/discover.md. Quick summary:
GET /v2/connections โ find the user's connection by name or type.
- Ask the user for the table path; verify with
POST /v2/connection/<id>/lookup.
- Discover columns directly via
GET /v2/connections/tables/{inodeId}/columns (full mechanics in reference/workflows/discover.md). Only fall back to asking the user when the endpoint doesn't return what's needed.
Never invent column names โ only use names returned by the API or supplied by the user.
Verify literal values before writing predicates. If your task involves filtering on a categorical column (e.g., CountIf([Status] = "active"), If([Type] = "sale", ...)), you need to know what values that column actually contains โ the /v2/connections/tables/{inodeId}/columns endpoint gives you names and types but not values. Run a SELECT DISTINCT <col> via any tool that reaches the warehouse โ an MCP server (warehouse or Sigma), a SQL CLI, or just ask the user. Don't guess literals. See reference/workflows/discover.md.
Step 4 โ Identify features and load only what you need
Map the user's request to the Reference Index below. State the features you identified, then read the listed reference files before drafting. If the user asks for a feature this skill doesn't cover, fetch the OpenAPI and inspect the relevant schema.
Step 5 โ Draft the spec to a local file
Write the spec YAML to disk (e.g., /tmp/workbook-spec.yaml). YAML is preferred over JSON in this skill โ easier to read, diff, and comment for human review. The API accepts either; pick YAML unless something downstream specifically needs JSON. Key rules:
- Every element needs a unique
id and a descriptive name.
- Every column needs a unique
id, a name, and a formula.
- Follow the formula reference rules in
reference/specification/formulas.md exactly โ most spec errors happen here.
- Write explicit
layout XML for multi-element workbooks. Auto-arrange (omitting layout) is acceptable only for single-element pages or a uniform stack of tables. See reference/specification/layout.md for the rubric.
- Start with 1โ2 pages. Add more later via update.
For create, the file must include top-level name, folderId, schemaVersion, and pages. description is optional. layout is technically optional but expected for multi-element workbooks. schemaVersion is usually 1 โ that's the current value; it may change in the future, so if the API rejects the spec on that field, check what your reference-workbook GET in Step 2 returned and use that instead. Full CRUD mechanics are in reference/workflows/crud.md.
Step 6 โ Validate the spec
Run the bundled validator first โ do not skip.
./scripts/validate-spec.sh /tmp/workbook-spec.yaml
Then do the manual formula pass and final shape checks per reference/workflows/validate.md. Fix everything reported before continuing.
Step 7 โ Create the workbook
curl -s -X POST -H "Authorization: Bearer $SIGMA_API_TOKEN" \
-H "Content-Type: application/yaml" \
-H "Accept: application/yaml" \
--data-binary @/tmp/workbook-spec.yaml \
"$SIGMA_BASE_URL/v2/workbooks/spec" > /tmp/create-response.yaml
WORKBOOK_ID=$(yq -r '.workbookId' /tmp/create-response.yaml)
cp /tmp/workbook-spec.yaml "/tmp/workbook-spec-${WORKBOOK_ID}.yaml"
Persist the spec after a successful create so subsequent PUT updates can start from it. Report both the workbook URL and the saved spec path.
If creation fails, read the error, fix the spec, re-validate, retry. See reference/workflows/validate.md for decoding cryptic errors.
Step 7b โ Verify the workbook actually compiles
Do not skip. A successful POST is necessary but not sufficient โ Sigma accepts specs whose formulas don't resolve, then surfaces the failures at query time by embedding the error as a string literal in the compiled SQL ('Unknown column "[X]"', 'Circular column reference to [Y]'). Affected elements render empty in the UI. Only Sigma's compiler knows whether your formula references actually resolve.
./scripts/verify-workbook.sh "$WORKBOOK_ID"
If any element reports [FAIL], fix the column formulas in the spec (most often a missing source prefix, a self-referencing column, or a friendly-name mismatch with the warehouse โ see reference/specification/formulas.md), PUT the corrected spec, and re-verify.
Step 8 โ Iterate
After initial creation, use PUT /v2/workbooks/<id>/spec to add pages or refine the workbook.
For anything beyond ~1 page / ~10 elements, switch to the element rep (reference/workflows/element-rep.md): scripts/wb-rep.rb pull <id> <dir> explodes the spec into one file per element so each edit touches a ~ยฝKB file instead of the whole spec, push handles drift-check + validation + PUT, and render exports page PNGs you can actually look at. The raw GET/PUT flow below remains fine for small workbooks and one-off tweaks.
IDs are preserved on CREATE. The id values you POST (pages, elements, columns) are kept verbatim, and layout elementId references stay valid โ so you can edit your saved spec and PUT it back directly. GET the current spec first only if you don't have your latest copy. See reference/workflows/crud.md.
curl -s -H "Authorization: Bearer $SIGMA_API_TOKEN" \
"$SIGMA_BASE_URL/v2/workbooks/<workbook-id>/spec" \
> /tmp/current-spec.yaml
curl -s -X PUT -H "Authorization: Bearer $SIGMA_API_TOKEN" \
-H "Content-Type: application/yaml" \
-H "Accept: application/yaml" \
--data-binary @/tmp/current-spec.yaml \
"$SIGMA_BASE_URL/v2/workbooks/<workbook-id>/spec" | yq .
cp /tmp/current-spec.yaml "/tmp/workbook-spec-<workbook-id>.yaml"
./scripts/verify-workbook.sh "<workbook-id>"
Step 9 โ Report back
Report the workbook URL and the saved spec path. Do not tack on generic "improvement ideas" or "next steps." Match the response to what was asked.
Surface follow-up items only when they're load-bearing, and name them concretely:
- Tradeoffs you made during the build โ dropped a chart, simplified a formula, skipped a control because the shape wasn't in your reference.
- Obvious gaps revealed by the column list โ e.g., the user asked for "sales by region" and the table has a
region_tier column that would make the breakdown richer. One sentence, named.
If none apply, just report the URL + spec path and stop.
Reference Index
The reference is feature-sliced โ don't read every file up-front. The index has three sections: elements (the visual / interactive pieces), sources (where each element gets its data), and cross-cutting (formulas, layout, formatting, validation, CRUD).
Elements
| File | When to load |
|---|
reference/specification/tables.md | Table element, tabular data, data grid, spreadsheet-style list. Also element-level filters (top N, limit, rank), groupings (pivot, group by), the pivot-table and editable input-table element kinds, and conditionalFormats (threshold-based cell coloring, on pivot/input tables). |
reference/specification/charts.md | Chart, graph, visualization, line / bar / column / stacked / grouped / combo / donut / pie / scatter / share-of / breakdown. Cartesian axes, color channel, trellis, trendlines, reference marks. |
reference/specification/maps.md | Map visualizations โ geography-map (GeoJSON shapes), point-map (lat/long bubbles), region-map (states / counties / countries). |
reference/specification/kpis.md | KPI, stat, big number, single value, metric card โ including layout / value styling, the comparison ฮ badge (comparisonColumn + comparison:{display:"delta"} โ spec-authorable and readback-stable; the house default), and the trend/sparkline block (still UI-bound). |
reference/specification/controls.md | Filter, dropdown, picker, multi-select, date range, date picker, text filter, number range, slider, segmented, hierarchy. Also the entry (write) text control shape used with buttons/actions. |
reference/specification/content-elements.md | The non-data elements โ text (Markdown + inline styling), image, divider, embed (external URLs). Titles, callouts, logos, rules, embedded content. |
reference/specification/input-tables.md | Operational supplement for input-table (spec shape lives in tables.md): write-connection requirement, the publish gate, reading data back via warehouse views, element endpoints for auditing, and migration patterns (Excel/planning models). |
reference/specification/styling.md | Load when building a dashboard from scratch. Design recipe library โ vetted color palette, hero header strip, gradient header/KPI cards + composite sparkline, KPI card row, section headers, divider rhythm, categorical chart colors. Turns a default-arrange workbook into a designed-looking one without UI editing. |
reference/specification/agents.md | Workbook AI agent, chat with your data, agent, chatbot, AI assistant. The workbook-top-level agents:[] array + page-level chat element; read-only analyst vs. write/action agent; org-feature gate + graceful degrade. |
Sources
| File | When to load |
|---|
reference/specification/sources-warehouse.md | Always โ load before drafting any spec. Warehouse-table source (Snowflake, BigQuery, Databricks, Redshift, Postgres/MySQL). |
reference/specification/sources.md | Reference another chart/table/element, derive from existing element, join, combine tables, data model / semantic-layer source, custom SQL, union, transpose, unpivot. |
Cross-cutting
| File | When to load |
|---|
reference/specification/schema.md | Always โ load before drafting any spec. Top-level shape, required fields, response-only fields to strip. |
reference/specification/formulas.md | Always โ load before drafting any spec. Formula syntax, qualification, special characters, the #1 mistake. |
reference/specification/formatting.md | Format, currency, percentage, date format, decimals โ column formatting. |
reference/specification/layout.md | Always load for multi-element workbooks. Layout XML, GridContainer/LayoutElement, container elements, tabbed containers (pack multiple views into one region โ spec-authorable, not UI-only), page visibility / background, auto-arrange fallback rules, when to write explicit layout vs. omit. |
reference/specification/example-full.yaml | A real multi-page reference spec (KPIs, charts, joins, controls, layout) โ copy shapes from when in doubt. |
reference/specification/comparative-kpi-card.yaml | Minimal clone-able comparative KPI card โ value + comparisonColumn + comparison:{display:"delta"}, the house-default comparative shape (see kpis.md). |
Workflows
| File | When to load |
|---|
reference/workflows/discover.md | Finding connections, tables, and column names. Load before composing a new spec. |
reference/workflows/composition.md | Open-ended design decisions โ calibrating workbook complexity to the request, when to ask the user, what to ask, surfacing structural choices in the final summary, and a few safe defaults (hidden source pages, ranked-table sort direction). Load before drafting anything when the prompt leaves significant design choices unmade. |
reference/workflows/actions.md | Buttons, write-back, insert-rows/clear-control/set-control-value effects, modals (open/close-overlay), the append-only-log pattern, and the masked-error catalog for input-table/control element kinds. Load when the user wants a button, a "log/save/submit" action, or a write-back workflow. |
reference/workflows/crud.md | POST / GET / PUT against the workbook spec endpoints. Load when creating, retrieving, or updating a workbook. |
reference/workflows/validate.md | Pre-submit + post-create validation. Load before any POST or PUT. |
reference/workflows/from-image.md | The user supplied a target image (screenshot, mockup, BI-tool export) to reproduce. Load before discovery โ it adds explicit observation and validation steps. |
reference/workflows/element-rep.md | Large or multi-page workbooks, parallel element work, or iterative refinement. scripts/wb-rep.rb explodes the spec into one small file per element (pull/status/push/render) so edits never drag the whole spec through context โ element-level semantics over the whole-spec API, plus PNG renders to inspect what you built. |
Quick Formula Rules
The single most common spec error is bare [column_name] references to warehouse columns. Full rules in reference/specification/formulas.md. Skeleton:
Outside the element โ use [SourceName/column_name]:
- Warehouse-table source:
SourceName = last segment of the path array (e.g., [ORDERS/Revenue])
- Another element:
SourceName = that element's name
- Join legs: prefix by the leg's
name, or by the join's top-level name for primarySource columns
Inside the same element โ use [column_name] (no prefix):
- References a column defined in this element by its
name field.
- A column cannot reference itself (circular reference error).
Troubleshooting
"I don't see this field in the skill"
Fetch the OpenAPI. The skill documents stable, common surface area; the API has more. See Consulting the OpenAPI above.
API schema mismatch (skill is stale)
A 400 about request shape โ invalid argument, unknown field, unexpected property, missing required field โ usually means the API moved past the skill. Fetch the OpenAPI (see Consulting the OpenAPI), diff the live shape for that kind, and retry once with the correction. Tell the user it looks like the skill is out of date and worth updating through whatever channel they installed it from; don't loop on retries.
401 Unauthorized
Sigma OAuth tokens expire after ~1 hour. Long workbook-building sessions (orchestrated batch conversions, multi-step iterations, anything that runs >50 minutes) will hit this mid-flight.
Ruby callers (any of the tableau-to-sigma/scripts/*.rb Sigma-touching scripts): use the Sigma REST wrapper at tableau-to-sigma/scripts/lib/sigma_rest.rb โ it does automatic 401-with-refresh-and-retry. Concretely:
require_relative 'lib/sigma_rest'
spec = Sigma.request(:get, "/v2/workbooks/#{id}/spec")
Bash / curl callers: re-run eval "$(scripts/get-token.sh)" to refresh manually. For long shell loops, wrap the curl in a small helper that retries once on 401:
sigma_curl() {
local resp code
resp=$(curl -sS -w '\n%{http_code}' -H "Authorization: Bearer $SIGMA_API_TOKEN" "$@")
code=$(echo "$resp" | tail -1)
if [ "$code" = "401" ]; then
eval "$(scripts/get-token.sh)"
resp=$(curl -sS -w '\n%{http_code}' -H "Authorization: Bearer $SIGMA_API_TOKEN" "$@")
fi
echo "$resp" | sed '$d'
}
If 401 persists after refresh, re-authenticate via sigma-api and verify SIGMA_BASE_URL, SIGMA_CLIENT_ID, SIGMA_CLIENT_SECRET.
403 Forbidden on workbook create
The credentials authenticated but aren't permitted to create workbooks here. Ask the user's Sigma admin to confirm the credential's permissions and folder access.
"Invalid column reference" or formula errors on creation
The most common spec issue. A bare [column_name] was used where [TABLE/column_name] is needed. See reference/specification/formulas.md for the full rules and reference/workflows/validate.md for the manual checklist.
"Unknown column" errors
The column name in the formula doesn't match what the warehouse actually has. Re-confirm the column names via GET /v2/connections/tables/{inodeId}/columns (raw warehouse names) and the readback (GET /v2/workbooks/<id>/spec, which shows Sigma's normalized friendly names). Use those names verbatim.
jq or yq not installed
jq is used for OpenAPI inspection (the OpenAPI is JSON). yq is used for workbook-spec inspection (specs are YAML).
jq: brew install jq (macOS) or apt install jq (Debian/Ubuntu).
yq: two different tools share this name โ the Go mikefarah/yq (brew install yq) and the Python pip install yq wrapper around jq. Reading works the same in both (yq -r '.workbookId' f.yaml), but in-place editing differs: mikefarah uses yq -i 'โฆ' f.yaml, while the Python wrapper needs yq -y -i 'โฆ' f.yaml. Run yq --help to see which you have and adapt.
Cryptic validation errors / silent bad data
See reference/workflows/validate.md for the full triage table (mapping Invalid kind: pages[0].elements[N]... style errors to the right spec file).