omni-model-builder

SKILL.md

Omni Model Builder

Create and modify Omni's semantic model through the YAML API — views, topics, dimensions, measures, relationships, and query views.

Tip: Always use omni-model-explorer first to understand the existing model.

Prerequisites

export OMNI_BASE_URL="https://yourorg.omniapp.co"
export OMNI_API_KEY="your-api-key"

You need Modeler or Connection Admin permissions.

API Discovery

When unsure whether an endpoint or parameter exists, fetch the OpenAPI spec:

curl -L "$OMNI_BASE_URL/openapi.json" \
  -H "Authorization: Bearer $OMNI_API_KEY"

Use this to verify endpoints, available parameters, and request/response schemas before making calls.

Safe Development Workflow

Always work in a branch. Never write directly to production.

Step 1: Write YAML to a Branch

curl -L -X POST "$OMNI_BASE_URL/api/v1/models/{modelId}/yaml" \
  -H "Authorization: Bearer $OMNI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fileName": "my_new_view.view",
    "yaml": "dimensions:\n  order_id:\n    primary_key: true\n  status:\n    label: Order Status\nmeasures:\n  count:\n    aggregate_type: count",
    "mode": "extension",
    "branchId": "{branchId}",
    "commitMessage": "Add my_new_view with status dimension and count measure"
  }'

branchId is a UUID — retrieve it from the List Models endpoint with ?include=activeBranches. If the branch doesn't exist yet, Omni creates it.

Step 2: Validate

curl -L "$OMNI_BASE_URL/api/v1/models/{modelId}/validate?branchId={branchId}" \
  -H "Authorization: Bearer $OMNI_API_KEY"

Returns validation errors and warnings with message, yaml_path, and sometimes auto_fix.

Step 3: Merge the Branch

Important: Always ask the user for confirmation before merging. Merging applies changes to the production model and cannot be easily undone.

curl -L -X POST "$OMNI_BASE_URL/api/v1/models/{modelId}/branch/{branchName}/merge" \
  -H "Authorization: Bearer $OMNI_API_KEY"

If git with required PRs is configured, merge through your git workflow instead.

YAML File Types

Type Extension Purpose
View .view Dimensions, measures, filters for a table
Topic .topic Joins views into a queryable unit
Relationships (special) Global join definitions

Write with mode: "extension" (shared model layer). To delete a file, send empty yaml.

Writing Views

Basic View

dimensions:
  order_id:
    primary_key: true
  status:
    label: Order Status
  created_at:
    label: Created Date
measures:
  count:
    aggregate_type: count
  total_revenue:
    sql: ${sale_price}
    aggregate_type: sum
    format: currency_2

Dimension Parameters

See references/modelParameters.md for the complete list of 35+ dimension parameters, format values, and timeframes.

Most common parameters:

  • sql — SQL expression using ${field_name} references
  • label — display name · description — help text (also used by Blobby)
  • primary_key: true — unique key (critical for aggregations)
  • hidden: true — hides from picker, still usable in SQL
  • formatnumber_2, currency_2, percent_2, id
  • group_label — groups fields in the picker
  • synonyms — alternative names for AI matching (e.g., [client, account, buyer])

Measure Parameters

See references/modelParameters.md for the complete list of 24+ measure parameters and all 13 aggregate types.

Measure filters restrict rows before aggregation:

measures:
  completed_orders:
    aggregate_type: count
    filters:
      status:
        is: complete
  california_revenue:
    sql: ${sale_price}
    aggregate_type: sum
    filters:
      state:
        is: California

Filter conditions: is, is_not, greater_than, less_than, contains, starts_with, ends_with

Writing Topics

See Topics setup for complete YAML examples with joins, fields, and ai_context, and Topic parameters for all available options.

Key topic elements:

  • base_view — the primary view for this topic
  • joins — nested structure for join chains (e.g., users: {} or inventory_items: { products: {} })
  • ai_context — guides Blobby's field mapping (e.g., "Map 'revenue' → total_revenue")
  • default_filters — applied to all queries unless removed
  • always_where_sql — non-removable filters
  • fields — field curation: [order_items.*, users.name, -users.internal_id]

Writing Relationships

- join_from_view: order_items
  join_to_view: users
  on_sql: ${order_items.user_id} = ${users.id}
  relationship_type: many_to_one
  join_type: always_left
Type When to Use
many_to_one Orders → Users
one_to_many Users → Orders
one_to_one Users → User Settings
many_to_many Tags ↔ Products (rare)

Getting relationship_type right prevents fanout and symmetric aggregate errors.

Query Views

Virtual tables defined by a saved query:

schema: PUBLIC
query:
  fields:
    order_items.user_id: user_id
    order_items.count: order_count
    order_items.total_revenue: lifetime_value
  base_view: order_items
  topic: order_items

dimensions:
  user_id:
    primary_key: true
  order_count: {}
  lifetime_value:
    format: currency_2

Or with raw SQL:

schema: PUBLIC
sql: |
  SELECT user_id, COUNT(*) as order_count, SUM(sale_price) as lifetime_value
  FROM order_items GROUP BY 1

Common Validation Errors

Error Fix
"No view X" Check view name spelling
"No join path from X to Y" Add a relationship
"Duplicate field name" Remove duplicate or rename
"Invalid YAML syntax" Check indentation (2 spaces, no tabs)

Docs Reference

Related Skills

  • omni-model-explorer — understand the model before modifying
  • omni-ai-optimizer — add AI context after building topics
  • omni-query — test new fields
Weekly Installs
6
GitHub Stars
4
First Seen
12 days ago
Installed on
claude-code6
opencode4
antigravity4
github-copilot4
codex4
zencoder4