Describe a table
A model gives business meaning to a table. Before creating one, finish this sentence: “One row represents one ___.” For an orders table this might be one order; for order lines it is one line, which requires a different identity and aggregation check.
You need the Editor role or higher and a catalog table. The example below assumes your actual table contains order_id, ordered_at, and amount. Replace these with verified source columns.
Create the model
Section titled “Create the model”- In Catalog, open a table and select Describe this table. Its Source table, Label, and Name are filled in. You can also open Semantics → Models → New → Model and use Choose source table to search loaded tables; an empty Label and Name start from the table’s name.
- Check the Label and lower-snake-case Name, such as
orders, and describe what one row represents. The model’s name becomes read-only after creation. - In Columns, choose Use as for each column:
order_id: Row key. Exactly one field must identify each row.ordered_at: Time with a Day grain. Select Metric time on this row if it is the reporting date: Explore’s Metric time uses it for this model’s aggregates.amount: Sum → metric. In the Name column, enter a technical name such asrevenueand an optional label such as Revenue. Use Name, description, and options for advanced aggregation settings.
- A new model shows a suggested use for each column from Catalog keys, column names, and types. Apply suggestions applies them together; Dismiss suggestions leaves those columns unused. Adjust any use that does not match the business meaning. Not used columns are omitted from the saved definition and show no inputs until you choose a use. Filter columns and In use narrow a long table.
- Read Check, which checks Catalog and saved references without running a warehouse query. Local validation must pass; a Check problem does not block Save.
- Select Save. The model and its new Aggregate metrics are saved together: either all definitions succeed or none are saved. Existing metrics are preserved. When a new metric is created, its page opens. Select Explore to open a question with that metric selected, choose a reporting period, and select Run in Explore.
Use Category for fields such as region or status and Links to Model for a related model’s key. The target selector fills in the matching entity name; the physical column expression can differ. Existing model pages show the source table, row key, joins, and Metric time, then Columns grouped by use (keys, links, time, categories, aggregates) with unused columns collapsed, and the metrics and dashboards that use the model. Edit makes the same page editable, and Affects if saved shows dependent resources. Add aggregate metric opens a new metric on this model.
A column can have more than one use. For example, keep order_id as the Row key and use its row’s Add another use to add Count → metric with a different technical name. Add calculated field adds a row for a SQL expression such as amount_cents / 100.0.
The advanced field options retain Unique key, Natural key, Median, Sum of true values, a per-aggregate Metric time, and One value per period rules. A balance across dates often needs one value per period, Latest or Earliest, on a Time field instead of a sum over time. A shared aggregate can be used by several metrics; its row links to each one.
Ask the agent to inspect Catalog first and create the model only after it has confirmed the table’s grain and columns. Discover the Workspace, read workspace, and follow availableOperations to list workspace/semantic-models. Send the advertised SEMANTIC_MODEL_DEFINITION create and SEMANTIC_MODEL_CHECK check entries to monomer_describe before building the input. A monomer_create call has this shape; the UUIDs are illustrative and must be replaced with discovered workspace and connector IDs.
monomer_create input
{ "workspaceId": "0198ef28-2000-7000-8000-000000000001", "path": "workspace/semantic-models", "input": { "kind": "SEMANTIC_MODEL_DEFINITION", "definition": { "schemaVersion": 3, "name": "orders", "sourceRelations": [{"connectorId": "0198ef28-2000-7000-8000-000000000002", "schema": "analytics", "relation": "orders"}], "entities": [{"name": "order_id", "type": "primary", "expression": "order_id"}], "dimensions": [{"isPartition": false, "name": "ordered_at", "type": "time", "expression": "ordered_at", "granularity": "day"}], "measures": [{"name": "revenue", "aggregation": "sum", "expression": "amount"}], "aggregationTimeDimension": "ordered_at" }, "aggregateMetrics": [{"measure": "revenue", "name": "revenue", "label": "Revenue"}] }}The required aggregateMetrics list names the new metrics to create with the model in one transaction. Use [] to save only the model. Each saved definition gets one History entry. A rejected metric leaves the model unchanged and identifies the list field to fix. Model edits include the same required list alongside the definition patch.
Use monomer_check with action: "check" and input: {"kind":"SEMANTIC_MODEL_CHECK","definition":...} to check the model definition before saving. It saves nothing and contacts no warehouse; monomer_invoke rejects check. After creation, read result.path to verify the model and get its next operations. For an edit, describe the exact resource’s EDIT entry and keep patch and the required aggregateMetrics list at the top level.
Time fields and time zones
Section titled “Time fields and time zones”Queries group and filter time in the Workspace’s Reporting time zone. To do that correctly, Monomer needs to know what a Time field’s values mean. In agent definitions, this is the optional timeKind of a time dimension; the model editor offers the same choice as Date, Local time, or Instant.
timeKind | Meaning | Inferred from these column types |
|---|---|---|
date | A calendar date | date on every warehouse |
local | A wall-clock time with no time zone, read as a time in the Reporting time zone | PostgreSQL and Redshift timestamp (without time zone), Snowflake TIMESTAMP_NTZ, BigQuery DATETIME, Databricks TIMESTAMP_NTZ, Trino timestamp(p), and TIMESTAMP in the sample workspace’s DuckDB |
instant | An absolute moment, converted to the Reporting time zone before grouping | PostgreSQL and Redshift timestamp with time zone, Snowflake TIMESTAMP_LTZ and TIMESTAMP_TZ, BigQuery and Databricks TIMESTAMP, Trino timestamp(p) with time zone, and TIMESTAMP WITH TIME ZONE in the sample workspace’s DuckDB |
When the field’s expression is a plain column and Catalog knows its type, Monomer infers the kind; leave timeKind out. Declare it when:
- A column without a time zone stores UTC times, as many pipelines do. Declare
instant; Monomer then reads the column as UTC. - The expression is calculated, such as
TIMESTAMP_MILLIS(event_ms). Aninstantexpression must return a type with a time zone. For a calculation that produces UTC times without one, add the zone:(expr) AT TIME ZONE 'UTC'on PostgreSQL and Redshift,TIMESTAMP(expr, 'UTC')on BigQuery, orwith_timezone(expr, 'UTC')on Trino. - Catalog doesn’t know the column’s type, for example a Snowflake column typed plain
TIMESTAMP, whose meaning depends on account settings. - A column without a time zone stores local times of another zone. Convert it in the expression, such as
created_at AT TIME ZONE 'America/New_York'on PostgreSQL, which returns atimestamp with time zone, and declareinstant.
A field Monomer can’t infer and that has no declaration is treated as local, and Check warns Declare timeKind for this time dimension. Saving still works. A declaration that contradicts a known column type, such as local on a timestamp with time zone column or date on a timestamp column, is a Check error, and queries that use the model fail until you correct it.
This dimension reads a timestamp column without a time zone that holds UTC times. In a monomer_create or edit input, it is one entry in dimensions:
{"isPartition": false, "name": "created_at", "type": "time", "expression": "created_at", "granularity": "day", "timeKind": "instant"}The grain matters too: a field defined at day or coarser grain becomes a date in the Reporting time zone, and one defined at hour or finer grain becomes that zone’s wall-clock time. Prefer day grain unless you need hourly detail; see Known limitations.
Use one table through more than one connector
Section titled “Use one table through more than one connector”Start with one source table. If the same logical table is available through another connector, you can reuse the model and its metrics instead of duplicating their definitions. Examples include a warehouse migration, development and production environments, regional replicas, or a separate compute warehouse. Each connector has one source table on the model.
In the model editor, select Use another connector and choose the corresponding table. Show columns, Change, and Remove manage the existing sources. On the model page, Source table shows the first source in connector-name order; Also on N more connectors reveals the others. The calculation path lists every source separately. Numbers match only when these tables hold the same data.
Each query runs on one connector. Explore lets you choose from the connectors that can run the selected metrics, while each Dashboard query fixes its own connector. Multiple sources do not provide automatic load balancing.
Check the model
Section titled “Check the model”Saving a definition does not prove that its expressions produce the intended business number. Open its Aggregate metric, or create a metric if you saved the model with an empty aggregateMetrics list. Select Explore on the metric page and compare a small period against a known source total. The definition check does not execute a warehouse query. If the source table can’t be resolved, check its exact names and refresh Catalog. For related tables, link matching model keys.
History, delete, and restore
Section titled “History, delete, and restore”Every create, edit, and delete keeps the complete semantic model definition in History, with the person, time, and whether they used the Web app or an agent app. Explorer or higher can read History; Editor or higher can delete or restore a version.
Open the semantic model’s actions and select Delete. Review the dependent metrics and the warning that dashboards and pages using this model stop updating, then type its name to confirm. References stay in place: dependent queries can fail with the missing definition named. Existing Explore runs and their results remain available.
A deleted item in Activity opens its History with a Deleted state. Select Restore on the Deleted entry to restore the last recorded definition. Older versions with different content offer Restore this version. Older entries with the same content as the latest recorded definition have no restore control. The newest entry of a live definition also has no restore control. A deleted definition returns with its original ID. If a different definition already uses that name, restore is rejected; resolve the name conflict before trying again. Creating a new definition with a reused name gives it a new ID and separate History. History is retained when a definition is deleted and cannot be deleted from this screen.
Partition filters and snapshots
Section titled “Partition filters and snapshots”For a BigQuery table that requires a partition filter, add a dimension whose expression uses its partition column. Check keeps the connectors the model runs on and shows when a time range or partition filter is needed. A missing matching dimension appears as a Check issue; it does not prevent saving.
Snapshot partition is a separate dimension option for tables that repeat rows per date. It adds that
dimension to snapshot joins. It is not a way to declare a BigQuery partition key, and Monomer does not
turn it on automatically from Catalog metadata. In agent definitions, each dimension includes an explicit
"isPartition": false or true.