Every company that puts an AI agent in front of business questions hits the same wall, and it is not the language model. It is context. "Revenue" has three definitions across three dashboards, "active customer" means 60 days to one team and 90 to another, and the agent, unaware of either, writes plausible SQL over raw tables and returns a number that looks right. Nobody can say where it came from.
A semantic layer solves half of this: define metrics, dimensions, relationships and rules once, and serve the same result to everyone. The other half, proving the number, is rarely solved. I built Cosmos Semantic to do both. It is open source under Apache 2.0: github.com/WiliamRosa/cosmos-semantic-platform.
Try it without installing anything: live demo of the console, with synthetic data from the example model.
What it is
A semantic layer with its own engine and a business ontology at its core. You define entities, metrics, concepts and business rules once, in YAML with the dbt Semantic Layer vocabulary. Any AI agent, application or person then gets the same number on any database: the engine generates and runs the SQL directly on your data source, and every answer carries its own proof.
| Multi-database | One model on Databricks, Snowflake, Oracle, SQL Server, Postgres, MySQL, MariaDB and DuckDB. The test suite compares the numbers across all of them on every change |
| Ontology and knowledge graph | A bilingual business glossary (SKOS), versioned business rules with owners and tests, and a graph of teams, systems and processes |
| Built for AI agents | A native MCP server. Agents find the concept in the glossary, ask for a governed metric, and the engine writes deterministic SQL: the same question gets the same answer, every time |
| Verifiable, explainable answers | An evidence envelope on every answer: expanded formula, rules applied, row filters, reference date and hashes. Months later, cosmos replay tells whether a number changed and why |
| Governance by design | Row filters from the user's identity (OIDC, Entra ID first), personal data blocked from the AI channel, an audit log of every query |
| Open, no lock-in | Apache 2.0, its own engine, and import from dbt, Power BI, Cube and Apache Ossie (the open semantic interchange standard, formerly OSI) |
Evidence on every answer
Most semantic layers stop at "the metric is defined in one place". In Cosmos, every answer comes with an evidence envelope:
evidence q_2eae279c2b6b494da485
model edb8d14a70cd1e35 engine 0.3.0
as of 2026-11-04 (America/New_York) source local (duckdb)
metric revenue = SUM(orders.amount)
lineage orders
sql eb5ca2c843244937 result 451c5e52d6f85089 (3 rows)
It records:
- the expanded formula;
- the business rules that applied, with owner, effective date and test status;
- the row filters applied to the user and the source the number came from;
- the reference date: "today" is pinned to the model's time zone, not to each server's clock;
- hashes of the model, the SQL and the result.
It is the lineage of the number, not just of the table.
On top of that evidence sit three tools I consider the heart of the project:
-
Reconciliation (
cosmos reconcile) compares a governed metric with the legacy SQL a team already uses and names the likely cause of each divergence. Examples: a different filter, rows multiplied by a join, integer division, a day cut in UTC instead of the business time zone. It is tested against a "zoo" of nine classic mistakes planted on purpose, plus a correct query as the control. -
Impact analysis (
cosmos impact) shows, before you change a rule or metric, everything that depends on it, who owns each part and who queried it. - Effective-dated rules: when "active customer" moved from 60 to 90 days, the rule kept both versions. A June query uses the rule in force in June, and the difference between the two is exactly the effect of the change.
The ontology as context for agents
What makes an agent right is not a longer prompt; it is structured business context. In Cosmos that context has three layers:
-
A glossary with labels and synonyms in English and Portuguese, exportable as SKOS/RDF for data catalogs. "Active buyers" resolves to
active_customer. - Business rules with owners, effective dates, versions and tests, which become reusable filters and dimensions.
- A knowledge graph of teams, systems and processes: who owns what, which system the data comes from, and which process depends on each metric.
The MCP server exposes it in five tools: search_concepts, explain, list_members, query and show_sql. Two guarantees hold on every channel:
- Row filters come from the user. The context comes from the identity provider's token and goes into the SQL. A regional manager's agent only sees that region.
- Personal data never reaches an agent. Columns classified as personal or sensitive cannot be grouped or filtered over the AI channel:
error: `customers.email` is personal data (LGPD) and never reaches AI agents,
neither as a grouping nor as a filter
AI suggests, the engine validates
cosmos suggest asks Claude for synonyms, descriptions and business rules. Nothing is applied automatically: each suggestion is compiled and run by the engine, then reviewed by a person. In the first run against the real API it accepted about 28 suggestions in roughly 30 seconds, nearly all good. It also proposed one wrong Portuguese synonym, which is exactly why a person reviews them.
The most useful result was something else. One suggested rule exposed a precedence bug in the engine: a substituted expression lost its parentheses and silently changed meaning. Hand-written tests had missed the case; the AI's suggestion found it, and it became a regression test. To me that is the right role for AI in data: it widens what you can test, but it does not have the last word.
Multi-database, verified
"Cross-platform" is easy to write and hard to prove. The whole suite runs against each source:
- the reference queries, compared with hand-written SQL;
- 80 randomized requests that must return exactly the same number on every database;
- reconciliation, model bootstrap and Power BI import.
Each database brought its own surprise, and several would change a number silently:
-
Databricks reports integers as
LONGin its catalog. - Snowflake divides integers with decimals, and the first day of the week depends on the session.
-
MySQL and MariaDB have no
DATE_TRUNC. -
Oracle's
CURRENT_DATEcarries the time of day, and itsDOUBLE PRECISIONis actually a decimal.
None of these show up in a demo. They show up when the same question must return the same number on different platforms, which is the guarantee a company with data in more than one place needs.
A console for people who decide
Not everyone who needs to trust a number opens a terminal. cosmos serve also serves a read-only web console, in English and Portuguese, for directors of data and AI and for process owners:
- Overview: metric health and ownership, the last check against legacy reports, and the questions agents answered.
- Process map: from source systems to metrics and rules, each part colored by health.
- Catalog: every metric, rule and concept in business words.
- Audited answers: each with a button that replays it.
- Usage and estimated cost per agent and per source.
Hands-on: from pip to the first number
Everything runs locally on DuckDB, with no server and no account:
pip install "cosmos-semantic[duckdb,testdata]"
cosmos init demo && cd demo
cosmos demo-data
cosmos query revenue average_order_value --by orders.status --evidence
cosmos explain rule:active_customer
cosmos init creates a project with the example model, an e-commerce with orders, items, payments, customers, products and sellers; cosmos demo-data generates synthetic data. To connect an agent, the project ships a development key, and in Claude Code a single claude mcp add is enough. For your own databases, install the extras you need, such as pip install "cosmos-semantic[databricks,snowflake,oracle]". The quickstart has the full walkthrough.
What it does not do yet
- No result cache.
- No SQL endpoint for Power BI and Excel to connect directly; paused on purpose until users say it is worth it.
- No managed service.
- The console's sign-in takes a pasted key or token; the identity provider's browser flow comes later.
The authoring format may still change before 1.0, always recorded in the changelog.
How to help
If you work with data and have fought a mismatched number, I would love you to try it with a model of your own, even if it is just importing a dbt project or a Power BI model to see whether the numbers match. Issues, criticism and pull requests are welcome in the repository, and Discussions is open for questions.

Top comments (0)