Support
Log In

Migrate from Omni

Convert your Omni shared model, topics, and views into governed Malloy semantic models

Omni's model spans layers — a shared model every workbook inherits, per-workbook extensions, and branches in between. Credible reads across all of them, reconciles the definitions into one canonical set, and rebuilds your analytical domain as governed Malloy.

What Credible Reads

Your Omni model — .view files (dimensions and measures over tables) and .topic files (views joined into queryable units, with AI context and default filters), authored in YAML. The agent works from those files directly, inventorying workbook-level extensions too — logic often lives there, not just in the shared model. Connecting Omni's MCP server or Model API is optional and adds live validation (and can round-trip the model files).

What Comes Across

The everyday modeling carries over. Here's how the bigger pieces land — and where they get better:

In OmniIn Credible
Shared model, topics, viewsMalloy sources (base + joined); import/export curate exposure
Dimensions & measuresCarried over, filtered and ratio measures included
Field-level sql: with ${…} refsResolved into Malloy expressions with explicit types
Logic split across shared / branch / workbook layersReconciled into one canonical definition per field
Model access controlsFine-grained access control in the model, versioned and enforced on every surface
ai_context and descriptions#(doc) / #(index), indexed by the AI Analytics Engine
Workbooks & dashboardsRebuilt as data apps or notebooks

The Migration Flow

Credible reads the shared model, topics, and workbook layers, translates views to sources and topics to joined sources, enriches with #(doc)/#(index) tags (seeded from ai_context), and — where you connect it — validates against Omni's query engine.

What Credible Handles

  • Logic split across layers — the "real" definition of a field may live in an un-promoted workbook model, not the shared model. Credible reconciles the shared, branch, and workbook layers into one canonical Malloy definition, resolving promotion lineage as it goes.
  • Field-level inline SQL — Omni encourages sql: with ${…} references and implicit typing. Credible resolves the references and makes Malloy types explicit.
  • Removable default filters belong in the query, not the model, so query-time defaults become part of a named view rather than a source-level filter.

Before & After

An Omni .view and .topic:

# order_items.view
views:
  - name: order_items
    sql_table_name: analytics.public.order_items
    dimensions:
      status:
        type: string
        sql: ${TABLE}.order_status
      value_tier:
        type: string
        sql: |
          CASE WHEN ${TABLE}.sale_price >= 100 THEN 'High'
               WHEN ${TABLE}.sale_price >= 25  THEN 'Medium'
               ELSE 'Low' END
    measures:
      total_revenue:
        description: Gross merchandise value across all order items
        sql: ${TABLE}.sale_price
        aggregate_type: sum
      completed_revenue:
        sql: ${TABLE}.sale_price
        aggregate_type: sum
        filters: { status: { is: Complete } }
      order_count:
        sql: ${TABLE}.order_id
        aggregate_type: count_distinct
# order_items.topic
topic:
  base_view: order_items
  label: Order Analysis
  ai_context: |
    Order-item level revenue and fulfillment. Use total_revenue for GMV and
    completed_revenue for recognized revenue; join users for customer demographics.
  joins:
    users:
  # a removable, query-time default — not baked into the model
  filters:
    order_items.status:
      is: Complete
source: order_items is conn.table('analytics.public.order_items') extend {
  primary_key: order_item_id
  join_one: users is conn.table('analytics.public.users') on user_id = users.id

  dimension:
    #(doc) Order item status
    #(index)
    status is order_status

    #(doc) Sale-price value bucket
    value_tier is
      pick 'High' when sale_price >= 100
      pick 'Medium' when sale_price >= 25
      else 'Low'

  measure:
    #(doc) Gross merchandise value across all order items
    # currency
    total_revenue is sum(sale_price)

    #(doc) Recognized revenue from completed items
    # currency
    completed_revenue is sum(sale_price) { where: status = 'Complete' }

    #(doc) Distinct orders
    order_count is count(order_id)

    #(doc) Average order value
    # currency
    avg_order_value is total_revenue / order_count

  view:
    #(doc) Revenue by month
    revenue_by_month is {
      group_by: created_at.month
      aggregate: total_revenue
    }
}

The topic's ai_context becomes #(doc) intent on the source and its views; the same physical view joined multiple ways in a topic becomes multiple named joins in Malloy.

More than a reformat. Definitions once split across shared, branch, and workbook layers collapse into one canonical, AI-discoverable model that composes into new questions. See what you gain →

Next Steps

On this page