Quickstart

Five minutes, no credentials, no server. Everything below runs against a local DuckDB file that Ontologiq creates for you.

Install

Requires Python 3.11 or newer.

pip install "ontologiq[serve]" ontologiq-duckdb

The serve extra adds the MCP server and the action runtime. If you only want the compiler, pip install ontologiq is enough.

Scaffold a project

ontologiq init shop
cd shop

You get a small e-commerce ontology:

shop/
├── ontologiq.yml          # project config: name, adapter, connection, seeds
├── objects/
│   ├── customer.yml       # identity, properties, state, relations
│   └── order.yml          # …and a governed action
├── seeds/
│   └── ecommerce.sql      # demo fixtures, so there is data to look at
├── .gitignore             # target/, *.duckdb, .ontologiq/
└── README.md

Build

ontologiq build
compiled 2 views → target/
seeded: 2 statements
build OK: customer, order ready to query

build runs four steps: validate the YAML and every expression in it, compile it to target/, apply the seed fixtures, and run the resulting views into DuckDB.

Look at a record

ontologiq show customer --key 1
customer #1
  customer_id: 1
  email: ada@example.com
  full_name: Ada Lovelace
  country: UK
  lifetime_value: 1240.50
  state: active

state is not a column in the source table. It was computed from the predicates you declared:

state:
  active: last_seen >= now() - 90d
  churned: last_seen < now() - 90d
  else: prospect

Ask for a customer who has not been seen in months and you get churned. Ask for an order and you also get the actions it accepts:

ontologiq show order --key 102
order #102
  order_id: 102
  total: 54.00
  placed_at: 2026-07-29 11:10:57
  state: open
actions:
  cancel — roles: support; approval required; requires: state == 'open'

Query the views yourself

The compiled views are ordinary SQL, sitting in your warehouse:

duckdb ecommerce.duckdb -c 'SELECT "state", count(*) FROM "customer" GROUP BY 1'
┌──────────┬──────────────┐
│  state   │ count_star() │
├──────────┼──────────────┤
│ active   │            3 │
│ churned  │            1 │
│ prospect │            1 │
└──────────┴──────────────┘

Nothing is hidden: target/views/customer.sql contains exactly the SELECT that was applied.

What was generated

target/
├── views/
│   ├── customer.sql       # the SELECT, in your adapter's dialect
│   └── order.sql
├── catalog.json           # the whole graph: objects, states, relations, actions
└── mcp/manifest.json      # the tools an AI agent will see

target/ is generated and gitignored. The YAML is the source of truth.

Next