OrionBelt Semantic Layer
Motor API-first e servidor MCP que transforma definições declarativas de modelos YAML em SQL otimizado para Postgres, Snowflake, ClickHouse, Dremio e Databricks
Documentação
OrionBelt® Camada Semântica e de Contexto, Mecanismo de Regras e Sidecar Semântico
Defina suas métricas uma vez em YAML. Deixe agentes e ferramentas de BI consultá-las sem nunca tocar no seu esquema.
Um sidecar semântico: ele acompanha os sistemas que você já executa, em vez de substituí-los.
Peça a um LLM para escrever SQL contra um esquema estrela bruto e, mais cedo ou mais tarde, ele junta duas tabelas de fatos e entrega um número de receita inflado por um fator de oito. Parece correto. Ninguém percebe.
OrionBelt é uma camada semântica e de contexto com um mecanismo de regras, e roda como um sidecar semântico. Você declara dimensões, medidas, métricas e junções em YAML versionado. OrionBelt os compila em SQL específico por dialeto por meio de uma AST real, e roteia consultas multi-fato por meio de um planejador de Camada de Fatos Composta que bloqueia os caminhos de junção que produzem armadilhas de leque. Agentes e ferramentas de BI pedem "Total Revenue" by "Country". Eles nunca veem um nome de tabela.
Nenhuma ferramenta de BI no meio. Sem bloqueio de runtime. Aponte para o que você já tem.
Quatro formas de entrada
O mesmo modelo atende a todas as superfícies que você já usa. Quatro delas, e um modelo por trás de todas as quatro:
| Superfície | Porta | Fala | Conecte-se com |
|---|---|---|---|
| PostgreSQL wire | 5432 | Protocolo Postgres | DuckDB via ATTACH, Tableau, Dremio como fonte federada, Power BI, Superset, DBeaver, Metabase, psql |
| Arrow Flight SQL | 8815 | gRPC + Arrow | DuckDB via adbc_scanner, Tableau e Power BI por meio dos drivers Flight SQL JDBC/ODBC, clientes ADBC (Python, Go, Java) |
| REST | 8000 | HTTP + JSON | seu código, notebooks, curl e os 8 drivers PEP 249 (que compilam aqui e executam diretamente no warehouse) |
| MCP | stdio / HTTP | Model Context Protocol | agentes de IA: Claude, Cursor, Copilot, Windsurf |
Ambas as superfícies SQL falam OBSQL, então SELECT "Region", "Total Sales" FROM sales_model é a mesma consulta, independentemente de qual você usou para entrar. ADBC é como você usa a superfície Flight SQL, em vez de uma quinta superfície própria, e DuckDB é um cliente que pode usar qualquer uma das superfícies SQL.
Oito formas de saída
Compila para BigQuery, ClickHouse, Databricks, Dremio, DuckDB/MotherDuck, MySQL, PostgreSQL e Snowflake. O warehouse por trás do modelo é independente da superfície à sua frente: qualquer uma das quatro superfícies, contra qualquer um dos oito dialetos.
Aqui está a consulta TPC-DS 98. Duas medidas sobre a mesma coluna, idênticas exceto por uma linha: Class Revenue está fixada em uma granularidade mais grossa do que a consulta pede.
measures:
Store Sales Amount:
columns: [{dataObject: Store Sales, column: Ext Sales Price}]
aggregation: sum
Class Revenue:
columns: [{dataObject: Store Sales, column: Ext Sales Price}]
aggregation: sum
grain: {mode: FIXED, keepOnly: [Class]} # <- pin to Class, ignore query grain
metrics:
Revenue Ratio:
expression: "{[Store Sales Amount]} * 100.0 / {[Class Revenue]}"
Essa única linha grain é o que se torna SUM(...) OVER (PARTITION BY "Class") abaixo.
A consulta nomeia conceitos de negócio. Sem tabelas, sem junções, sem SQL:
select:
dimensions: [Item ID, Item Description, Category, Class, Current Price]
measures: [Store Sales Amount, Revenue Ratio]
where:
- {field: Category, op: inlist, value: [Sports, Books, Home]}
- {field: Order Date, op: between, value: ["1999-02-22", "1999-03-24"]}
pip install orionbelt-semantic-layer
obsl compile tpcds.obml.yml -q Q98.yml -d duckdb
WITH "base" AS (
SELECT
"Item"."i_item_id" AS "Item ID",
"Item"."i_item_desc" AS "Item Description",
"Item"."i_category" AS "Category",
"Item"."i_class" AS "Class",
"Item"."i_current_price" AS "Current Price",
CAST(SUM("Store Sales"."ss_ext_sales_price") AS DECIMAL(18, 2)) AS "Store Sales Amount",
SUM("Store Sales"."ss_ext_sales_price") AS "Class Revenue"
FROM "main"."store_sales" AS "Store Sales"
LEFT JOIN "main"."item" AS "Item"
ON "Store Sales"."ss_item_sk" = "Item"."i_item_sk"
LEFT JOIN "main"."date_dim" AS "Date"
ON "Store Sales"."ss_sold_date_sk" = "Date"."d_date_sk"
WHERE
"Item"."i_category" IN ('Sports', 'Books', 'Home')
AND "Date"."d_date" BETWEEN '1999-02-22' AND '1999-03-24'
GROUP BY ALL
)
SELECT
"Item ID" AS "Item ID",
"Item Description" AS "Item Description",
"Category" AS "Category",
"Class" AS "Class",
"Current Price" AS "Current Price",
"Store Sales Amount" AS "Store Sales Amount",
"Store Sales Amount" * 100.0 / NULLIF(SUM("Class Revenue") OVER (PARTITION BY "Class"), 0) AS "Revenue Ratio"
FROM "base" AS "base"
ORDER BY
"Category" ASC,
"Class" ASC,
"Item ID" ASC,
"Item Description" ASC,
"Revenue Ratio" ASC
Você não escreveu o caminho de junção, a função de janela sobre um agregado, a proteção NULLIF ou um único nome de tabela. Altere -d duckdb para -d snowflake e os mesmos dois arquivos compilam para Snowflake, ou para qualquer um dos oito dialetos.
Isso é verificado, não presumido. 40 consultas TPC-DS são construídas contra um único modelo OBML e comparadas linha por linha com o SQL de referência de cada mecanismo: 39 de 40 correspondem no DuckDB em sf=1, 37 de 40 no ClickHouse em sf=10. Cada uma das diferenças restantes remonta a uma variante de referência, em vez de um erro de compilação, e cada uma é documentada. Veja a varredura ou as consultas em examples/tpcds_queries/.
Onde o OrionBelt se encaixa
OrionBelt é um sidecar, não uma plataforma. Ele compila um modelo YAML em SQL correto e o expõe pelos protocolos que você já usa. Ele não executa um cluster, não possui seu cache nem pede que você adote uma nuvem.
Use OrionBelt quando:
- Agentes consultam seus dados e um número silenciosamente errado é inaceitável. Consultas multi-fato passam por um planejador de Camada de Fatos Composta que bloqueia caminhos de junção com armadilhas de leque, em vez de somar silenciosamente através deles.
- Você quer suas definições de métricas em YAML revisável, sem JavaScript ou Python na camada de modelo.
- Sua ferramenta de BI deve se conectar pelo driver Postgres que ela já possui, sem novo conector para instalar e sem runtime de fornecedor no caminho.
- Você faz self-host, em mais de um mecanismo, e quer um único modelo que compile para todos eles.
Use outra coisa quando:
- Você precisa de pré-agregação e cache ajustados para dashboards de alta concorrência em escala. Cube tem anos de endurecimento de produção lá que o OrionBelt não tem.
- Suas métricas já vivem no dbt e seu time está satisfeito lá. MetricFlow as mantém onde estão.
- Você quer uma linguagem de análise exploratória em vez de uma camada de serviço. Malloy é um ajuste melhor.
Experimente a demonstração ao vivo com um modelo pré-carregado, ou abra o notebook Colab e execute-o contra dados TPC-H.
O que é uma Camada de Contexto?
Uma camada semântica diz ao consumidor como calcular um número: qual tabela, qual junção, qual agregado. Uma camada de contexto também diz o que o número significa e o que o negócio espera dele, em uma forma que um agente pode consultar em vez de adivinhar. No OrionBelt, esse contexto vive no mesmo modelo que as métricas:
- Regras de negócio declaram condições sobre as dimensões, medidas e métricas do modelo: quem conta como cliente de alto valor, quais categorias não devem vender com prejuízo. O mecanismo de regras compila cada regra para a consulta que relata seus membros ou violações, e avalia uma regra ou todas por REST, MCP, CLI (
obsl rules evaluate) e UI. - Mapeamentos de conceitos externos vinculam objetos de dados, dimensões, medidas, métricas e regras aos conceitos que sua organização já governa (schema.org, FIBO, um vocabulário interno), com proveniência.
- O grafo OBSL expõe cada modelo carregado como RDF, para que seus artefatos, junções, regras e links de conceitos possam ser consultados com SPARQL.
- Linhagem mostra do que uma dimensão, medida, métrica, regra ou consulta é construída, até as tabelas e junções que o planejador escolheu, como JSON, Mermaid ou Turtle vinculado ao grafo OBSL, na API, na CLI (
obsl lineage) e na UI. - Descrições, sinônimos e proprietários em cada artefato dão aos agentes o vocabulário que os usuários realmente falam.
Agentes alcançam tudo isso por MCP e REST, ao lado das ferramentas de consulta, para que o mesmo modelo que calcula um número também possa explicá-lo. A próxima seção mostra regras e links de conceitos em um modelo.
Significado, não apenas métricas
Um modelo que só sabe que Vendas Totais é uma soma ainda deixa o agente adivinhando o que é um cliente de alto valor, ou se uma categoria vendendo com prejuízo é um bug ou um fato. Desde a 2.30, o modelo carrega isso também, e é isso que torna o OrionBelt uma camada de contexto além de uma camada semântica: regras de negócio, links para as ontologias que sua organização governa e o próprio modelo como um grafo RDF dão ao agente o significado por trás dos números, não apenas os números.
Regras de negócio são condições sobre as próprias dimensões, medidas e métricas do modelo, sem SQL. O mecanismo de regras compila cada uma para a consulta que relata suas descobertas: os membros de uma regra de classificação ou elegibilidade, as violações de uma regra de validação ou restrição.
rules:
Non-Negative Margin:
type: validation
severity: error
description: Every product category must sell for at least what it cost
grain: [Product Category]
condition: {field: Gross Margin, op: ">=", value: 0}
Esta regra lê uma métrica, então é agregada: ela se torna um HAVING na granularidade da categoria pelo mesmo planejador de qualquer consulta, incluindo multi-fato. POST /v1/rules/{name}/evaluate retorna as categorias infratoras para esta regra, e POST /v1/rules/evaluate executa todas as regras em um único relatório.
Links de ontologia amarram artefatos aos conceitos que sua organização já governa, como relações de mapeamento SKOS com proveniência:
ontology:
prefixes:
schema: "https://schema.org/"
dataObjects:
Products:
externalConceptMappings:
- concept: schema:Product
relation: exact
justification: curated
Links nunca mudam o SQL. Eles mudam o que pode ser perguntado: cada modelo carregado também é um grafo RDF, então "quais artefatos significam um schema.org Product" é uma consulta SPARQL, e a API de descoberta responde o mesmo por REST (/concept-mappings, seu /namespaces e a lista de lacunas /unmapped).
Para um agente, essa é a diferença entre adivinhar e consultar. Por MCP, list_rules, evaluate_rule e find_concept_mappings ficam ao lado de execute_query como ferramentas.
Guias: Regras de Negócio, Mapeamentos de Conceitos Externos, Grafo OBSL e SPARQL.
Conteúdo
Quatro formas de entrada · O que é uma Camada de Contexto? · Significado, não apenas métricas · Experimente em 30 segundos · Claude Desktop / MCP · Por que OrionBelt? · Recursos · Exemplo · Documentação · Roadmap · Comercial · Desenvolvimento
Experimente em 30 Segundos
Opção A: Demonstração ao Vivo (sem instalação)
Abra a Demonstração ao Vivo — UI Gradio com um modelo de exemplo pré-carregado. Cole uma consulta, escolha um dialeto, veja o SQL instantaneamente.
Explorador de API: Swagger UI | ReDoc
Quer experimentar a superfície PostgreSQL wire? O Cloud Run é somente HTTPS, então a demonstração pública não pode expor as portas 5432 (pgwire) ou 8815 (Flight SQL). Inicie a mesma demonstração localmente em dois comandos — ela inclui o conjunto de dados DuckDB
orionbelt_1_commerceembutido e a superfície OBSQL completa:docker run --rm -d --name orionbelt-demo \ -p 8080:8080 -p 5432:5432 -p 8815:8815 \ -e PGWIRE_ENABLED=true \ -e FLIGHT_ENABLED=true \ ralforion/orionbelt-semantic-layer-api:latest # REST + UI Gradio: http://localhost:8080/ui # pgwire (qualquer psql / DBeaver / Tableau / Power BI): psql "host=localhost port=5432 user=obsl dbname=orionbelt_1_commerce sslmode=disable" \ -c 'SELECT "Client Name", "Total Sales" LIMIT 5' # Teste rápido do Flight SQL: uv run python examples/obsql.py 'SELECT "Client Name", "Total Sales" LIMIT 5' docker stop orionbelt-demoO contêiner vem com
PGWIRE_AUTH_MODE=trust(padrão), então é seguro paralocalhost, mas não é seguro expô-lo à internet pública. Para implantações expostas, definaAUTH_MODE=api_key(incluído na v2.12.0): o pgwire então negocia SCRAM-SHA-256 (ou texto claro sobre TLS) contra o armazenamento de chaves compartilhado.
Opção B: Google Colab (sem instalação)
— Notebook interativo com dados TPC-H: explore o modelo, compile consultas entre dialetos, execute contra DuckDB e veja os resultados. Requer runtime Python 3.12.
Opção C: Instalar do PyPI
pip install orionbelt-semantic-layer
Em seguida, cole em um REPL Python:
from orionbelt.parser import ReferenceResolver, TrackedLoader
from orionbelt.compiler.pipeline import CompilationPipeline
from orionbelt.models.query import QueryObject, QuerySelect
model_yaml = """
version: 1.0
dataObjects:
Orders:
code: ORDERS
columns:
Price: { code: PRICE, abstractType: float }
Country: { code: COUNTRY, abstractType: string }
dimensions:
Country:
dataObject: Orders
column: Country
resultType: string
measures:
Total Revenue:
resultType: float
aggregation: sum
expression: "{[Orders].[Price]}"
"""
loader = TrackedLoader()
raw, source_map = loader.load_string(model_yaml)
resolver = ReferenceResolver()
model, result = resolver.resolve(raw, source_map)
query = QueryObject(select=QuerySelect(dimensions=["Country"], measures=["Total Revenue"]))
pipeline = CompilationPipeline()
output = pipeline.compile(query, model, "postgres")
print(output.sql)
Saída:
SELECT
"Orders"."COUNTRY" AS "Country",
CAST(SUM("Orders"."PRICE") AS NUMERIC(18, 2)) AS "Total Revenue"
FROM ORDERS AS "Orders"
GROUP BY "Orders"."COUNTRY"
Nenhum arquivo env é necessário — o pipeline de compilação é sem estado.
Inicie os servidores:
orionbelt-api # REST API on :8000 (Swagger UI at /docs, Gradio UI at /ui)
orionbelt-ui # standalone Gradio UI on :7860 (connects to API on :8000)
FLIGHT_ENABLED=true orionbelt-api # API + Arrow Flight SQL on :8815 (DBeaver, Tableau, Power BI)
PGWIRE_ENABLED=true orionbelt-api # API + PostgreSQL wire on :5432 (Tableau, DBeaver, Superset, psql, Dremio source)
Opção C2: Instalar com uv
uv pip install orionbelt-semantic-layer
uv run orionbelt-api # REST API on :8000 (Swagger UI at /docs, Gradio UI at /ui)
uv run orionbelt-ui # standalone Gradio UI on :7860 (connects to API on :8000)
FLIGHT_ENABLED=true uv run orionbelt-api # API + Arrow Flight SQL on :8815 (DBeaver, Tableau, Power BI)
PGWIRE_ENABLED=true uv run orionbelt-api # API + PostgreSQL wire on :5432 (Tableau, DBeaver, Superset, psql, Dremio source)
Use a CLI obsl (sem servidor necessário — compila em processo):
obsl validate model.yaml # lint a model (exit 1 on error, CI-friendly)
obsl compile model.yaml -q query.json -d snowflake # print the generated SQL
obsl compile model.yaml --sql 'SELECT "Region", "Sales" FROM model' # ... or from an OBSQL string
obsl describe model.yaml # overview of data objects + artefacts
obsl diagram model.yaml # Mermaid ER diagram
obsl convert obml-to-osi model.yaml # OBML -> OSI (and osi-to-obml)
obsl execute -q query.json --server http://host # run against a deployed model (omit MODEL)
Veja o guia da CLI para todos os comandos.
Teste a superfície Flight SQL sem uma ferramenta de BI:
uv run python examples/obsql.py 'SELECT version()'
uv run python examples/obsql.py 'SHOW TABLES'
uv run python examples/obsql.py 'SELECT "Region", "Total Sales" FROM sales LIMIT 5'
# Multi-model deployment? Pick the model with -m:
uv run python examples/obsql.py -m sales 'SHOW TABLES'
uv run python examples/obsql.py --list # discover loaded models via REST
Experimente OBSQL em 30 segundos
OBSQL — OrionBelt Semantic QL — é a superfície SQL que ferramentas de BI e humanos realmente escrevem. Rótulos simples, marcadores MEASURE(), ou wrappers de agregação correspondentes; validação de correspondência de agregação; WITH ROLLUP / WITH CUBE; sem escape para SQL bruto do warehouse. Mesma linguagem sobre Arrow Flight SQL (v2.4+) e PostgreSQL wire (v2.5+):
PGWIRE_ENABLED=true uv run orionbelt-api &
# Every BI tool already ships a Postgres ODBC/JDBC driver — point yours at :5432
psql "host=localhost port=5432 user=obsl dbname=sales sslmode=disable" \
-c 'SELECT "Region", "Total Sales" LIMIT 5'
# All three measure forms compile to the same vendor SQL:
psql "..." -c 'SELECT "Region", "Total Sales" FROM sales LIMIT 5' -- bare
psql "..." -c 'SELECT "Region", MEASURE("Total Sales") FROM sales LIMIT 5' -- explicit marker
psql "..." -c 'SELECT "Region", SUM("Total Sales") FROM sales LIMIT 5' -- matching aggregate
Consulte a referência OBSQL para a gramática completa.
Opção D: Docker
Estágio 1 — Início com zero configuração (modelos carregados posteriormente via API ou UI):
docker run -p 8080:8080 ralforion/orionbelt-semantic-layer-api
Abra http://localhost:8080/docs para explorar a API.
Estágio 2 — Configuração realista com docker compose:
# docker-compose.yml
services:
api:
image: ralforion/orionbelt-semantic-layer-api:2.32.0
ports: ["8080:8080"]
env_file: .env
volumes:
- ./models:/app/models:ro
environment:
MODEL_FILES: /app/models/my-model.obml.yml
ui:
image: ralforion/orionbelt-semantic-layer-ui:2.32.0
ports: ["7860:7860"]
environment:
API_BASE_URL: http://api:8080
docker compose up -d
Consulte .env.template para a referência completa de variáveis de ambiente.
Notas sobre Docker:
API_SERVER_HOSTjá está0.0.0.0dentro do contêiner — nenhuma substituição necessária.- MCP via stdio não funciona no Docker. Use o cliente MCP HTTP para implantações conteinerizadas.
- Monte modelos em
/app/models(ou qualquer caminho) e definaMODEL_FILES(caminhos separados por vírgula) para pré-carregar na inicialização.- Para produção, fixe uma tag de versão (
:2.32.0) em vez de:latest.
Claude Desktop / MCP
O servidor MCP é um cliente fino separado que delega para a API REST:
Adicione ao seu claude_desktop_config.json do Claude Desktop:
{
"mcpServers": {
"orionbelt": {
"command": "uvx",
"args": ["orionbelt-semantic-layer-mcp"]
}
}
}
Também funciona com Copilot, Cursor e Windsurf. Consulte o repositório MCP para opções completas de configuração.
Por que OrionBelt?
| OrionBelt | dbt Semantic Layer | Cube | Malloy | |
|---|---|---|---|---|
| Formato do modelo | Somente YAML (OBML) | Python + YAML | JavaScript | DSL personalizado |
| Geração de SQL | Baseado em AST (seguro contra injeção) | Templates de string | Templates de string | Compilador |
| Multi-dialeto | 8 dialetos, sem lock-in em tempo de execução | dbt Cloud obrigatório | Cube Cloud ou self-host | Focado em BigQuery |
| Consultas multi-fato | Star Schema + planejador CFL (prevenção de fan-trap) | Limitado | Pré-agregações | Joins automáticos |
| Superfície de integração | API REST + MCP + UI Gradio | API dbt Cloud | REST + GraphQL | Extensão VS Code |
| Implantação | Self-host em qualquer lugar, binário único | SaaS (Cloud) | SaaS ou self-host | Biblioteca |
| Licença | BUSL-1.1 (converte para Apache 2.0) | Apache 2.0 | AGPL / proprietária | MIT |
| Significado de negócio no modelo | Regras compiladas na consulta que reporta suas descobertas; links SKOS para uma ontologia externa | Testes de dados em nível de coluna; meta de forma livre | meta de forma livre (ai_context) | Anotações, não interpretadas |
Recursos
Modelagem Semântica
- Formato OBML — modelos semânticos baseados em YAML com objetos de dados, dimensões, medidas, métricas e joins
- Consultas entre esquemas — modela objetos de dados em múltiplos bancos de dados e esquemas em um único modelo
- Filtros estáticos de modelo — condições WHERE obrigatórias embutidas no modelo, aplicadas automaticamente com extensão de join
- Regras de negócio —
rulesdeclarativos sobre dimensões, medidas e métricas (classificação, elegibilidade, validação, restrição) sem SQL; compilados na consulta que reporta suas descobertas, testados um a um ou todos de uma vez em um relatório, listados e avaliados na aba Regras de Negócio da UI - Grafo OBSL e SPARQL — exportação de grafo RDF e consulta SPARQL somente leitura para cada modelo carregado; mapeamentos de conceitos externos vinculam objetos de dados, dimensões, medidas e métricas a uma ontologia de negócio (FIBO, schema.org, um glossário corporativo) como correspondências SKOS
- Interoperabilidade OSI — conversão bidirecional entre OBML e o formato Open Semantic Interchange, agora desenvolvido como Apache Ossie (incubando)
Compilação SQL
- 8 dialetos SQL — BigQuery, ClickHouse, Databricks, Dremio, DuckDB/MotherDuck, MySQL, Postgres, Snowflake
- Geração baseada em AST — AST SQL personalizado garante SQL correto e seguro contra injeção (não templates de string)
- Star Schema e CFL — resolução automática de joins com Composite Fact Layer para consultas multi-fato
- Tipos de dados e precisão — embrulho automático de CAST com renderização de tipos específica do dialeto e limitação de precisão
- Formatação de exibição — padrões de formato numérico (
#,##0.00,0.00%) em medidas/métricas com renderização ciente de localidade - Configurações de fuso horário — detecção automática do fuso horário da sessão do banco com fallback
defaultTimezonee serialização ISO 8601 - Validação sqlglot — verificação de sintaxe pós-geração em todos os dialetos suportados
Superfície de Integração
- API REST — endpoints FastAPI para gerenciamento de modelos, validação, compilação e execução
- Servidor MCP — cliente fino separado para Claude, Copilot, Cursor, Windsurf
- Integrações de IA — LangChain, OpenAI Agents SDK, CrewAI, Google ADK, Vercel AI SDK, n8n, ChatGPT
- UI Gradio — interface web interativa para edição de modelos, teste de consultas e diagramas ER
- DB-API 2.0 + Flight SQL — drivers PEP 249 e servidor Arrow Flight SQL para DBeaver, Tableau, Power BI; acompanha
examples/obsql.py, um pequeno CLI de terminal para testar a superfície Flight sem uma ferramenta de BI - DuckDB como cliente (v2.27.1+) — um shell DuckDB simples consulta a camada, em qualquer superfície.
ATTACH ... (TYPE postgres)monta o modelo como uma tabela (SELECT ... FROM obsl.sales.model, umSET pg_use_text_protocol = trueprimeiro); a extensão da comunidadeadbc_scannerfaz isso via Flight SQL com Arrow o caminho todo. Medidas governadas fazem join com tabelas locais e chegam emCREATE TABLE AS. Guia - Protocolo PostgreSQL Wire (v2.5.0+) — superfície nativa de protocolo Postgres em
:5432. Toda ferramenta de BI já inclui um driver ODBC/JDBC Postgres, então o lado do usuário é "aponte sua conexão existente para OBSL e pronto" — Tableau, DBeaver, Superset, Power BI,psqlsimples, e Dremio como fonte Postgres federada (Dremio → OBSL → opcionalmente de volta ao lakehouse do Dremio, círculo completo)
API voltada a Agentes
- Saúde do modelo no carregamento — todo carregamento de modelo retorna um bloco
healthcom dataObjects órfãos, riscos de fan-trap e dimensões inalcançáveis — agentes pulam a segunda chamada defensiva - Endpoint de plano de consulta —
POST /query/planretorna o entendimento do planejador (escolha do planejador, tabelas físicas, caminho de join,would_compile) sem compilar SQL ou executar;include_database_explainopcional adiciona o EXPLAIN bruto do warehouse - Avisos estruturados — toda lista
warningsna API usa uma forma estável{code, severity, message, path, hint, context}com uma taxonomia de códigos documentada; agentes ramificam em códigos em vez de analisar mensagens - Recuperação difusa
/find— quando uma busca não produz correspondências exatas ou de sinônimos, fallback determinístico de Levenshtein + trigrama retorna candidatos próximos com pontuações e razões - Exemplos de modelo — bloco OBML opcional
examples:de consultas canônicas;GET /examples(com filtragem?intent=) dá aos agentes descoberta em uma única ida e volta do que um modelo foi projetado para responder
Cache de Resultados Orientado a Frescor
- Contratos de frescor no nível da fonte — declare blocos
refresh:em entradasdataObject(intervalo / heartbeat / estático); o cache deriva TTLs de consulta dos contratos das tabelas físicas que uma consulta tocou, não de suposições do chamador - Invalidação por heartbeat — um
POST /v1/heartbeatpara uma tabela física invalida toda consulta em cache que depende dela, em todos os dataObjects e sessões - Metadados DuckDB + resultados Parquet — cache com suporte a arquivos com serialização precisa de tipos, expiração preguiçosa, varredura de capacidade LRU; opcional via
CACHE_BACKEND=file - Inverte o padrão Cube/dbt/Looker — contratos vivem na fonte, não na abstração semântica; uma única fonte de verdade em todo cubo/explore/consulta salva que lê a tabela
Experiência do Desenvolvedor
- Erros com posição na fonte — erros de validação reportam linha e coluna exatas do YAML
- Diagramas ER — diagramas Mermaid interativos com zoom e download (MD/PNG/Turtle)
- Gerenciamento de sessões — sessões com escopo TTL e isolamento de modelo thread-safe
- JSON Schema — esquema completo OBML e de consulta para autocompletar na IDE (
yaml-language-server)
Exemplo
Definir um Modelo Semântico (OBML)
# yaml-language-server: $schema=https://raw.githubusercontent.com/ralforion/orionbelt-semantic-layer/main/schema/obml-schema.json
version: 1.0
dataObjects:
Customers:
code: CUSTOMERS
database: WAREHOUSE
schema: PUBLIC
columns:
Customer ID: { code: CUSTOMER_ID, abstractType: string }
Country: { code: COUNTRY, abstractType: string }
Orders:
code: ORDERS
database: WAREHOUSE
schema: PUBLIC
columns:
Order Customer ID: { code: CUSTOMER_ID, abstractType: string }
Price: { code: PRICE, abstractType: float }
Quantity: { code: QUANTITY, abstractType: int }
joins:
- joinType: many-to-one
joinTo: Customers
columnsFrom: [Order Customer ID]
columnsTo: [Customer ID]
dimensions:
Country:
dataObject: Customers
column: Country
resultType: string
measures:
Revenue:
resultType: float
aggregation: sum
expression: "{[Orders].[Price]} * {[Orders].[Quantity]}"
dataType: "decimal(18, 2)"
Compilar via API REST
# Create a session
curl -s -X POST http://localhost:8080/v1/sessions | jq .session_id
# -> "a1b2c3d4"
# Load the model
curl -s -X POST http://localhost:8080/v1/sessions/a1b2c3d4/models \
-H "Content-Type: application/json" \
-d '{"model_yaml": "..."}' | jq .model_id
# -> "abcd1234"
# Compile a query
curl -s -X POST http://localhost:8080/v1/sessions/a1b2c3d4/query/sql \
-H "Content-Type: application/json" \
-d '{"model_id":"abcd1234","query":{"select":{"dimensions":["Country"],"measures":["Revenue"]}},"dialect":"postgres"}' \
| jq -r .sql
SQL gerado (Postgres)
SELECT
"Customers"."COUNTRY" AS "Country",
CAST(SUM("Orders"."PRICE" * "Orders"."QUANTITY") AS NUMERIC(18, 2)) AS "Revenue"
FROM WAREHOUSE.PUBLIC.ORDERS AS "Orders"
LEFT JOIN WAREHOUSE.PUBLIC.CUSTOMERS AS "Customers"
ON "Orders"."CUSTOMER_ID" = "Customers"."CUSTOMER_ID"
GROUP BY "Customers"."COUNTRY"
Altere dialect para bigquery, clickhouse, databricks, dremio, duckdb, mysql ou snowflake para SQL específico do dialeto.
UI Gradio
- Compilador SQL — editores de modelo OBML e consulta lado a lado com realce de sintaxe, seletor de 8 dialetos, compilação com um clique com saída SQL formatada e explicação da consulta
- Execução de consultas — executa consultas compiladas contra um banco conectado, visualiza resultados com formatação numérica ciente de localidade, painel de metadados de resposta, download TSV e cópia para área de transferência (requer
QUERY_EXECUTE=true) - Diagrama ER — diagrama ER Mermaid interativo com zoom, alternância de colunas e download (MD/PNG/Turtle)
- Grafo de ontologia — visualização interativa vis-network do grafo OBML (objetos de dados, dimensões, medidas, métricas, joins) com camadas alternáveis e espaçamento de nós ajustável
- Regras de negócio: as regras do modelo com estatísticas; clique em uma linha para selecioná-la, mostre sua definição OBML, teste-a ou teste todas as regras em um relatório
- SPARQL: SELECT / ASK somente leitura sobre o grafo OBSL do modelo, em um editor com realce de sintaxe SPARQL e uma galeria de exemplos prontos para executar
- Barra de ferramentas do editor — botões de limpar, desfazer, refazer, enviar, baixar e copiar em todos os editores de código
- Importação/Exportação OSI — converte entre formatos OBML e OSI
- Modo claro/escuro — alterna via botão no cabeçalho, estado persistido entre sessões
Modo embutido — a UI é montada em /ui no servidor da API:
pip install orionbelt-semantic-layer && orionbelt-api
# -> UI at http://localhost:8000/ui
Modo autônomo — execute API e UI como processos separados:
orionbelt-api # API on :8000
orionbelt-ui # UI on :7860 (connects to API on :8000)
API_BASE_URL=http://remote-api:8080 orionbelt-ui # point UI to a remote API
Documentação
| Tópico | Link |
|---|---|
| Site completo da documentação | ralforion.com/orionbelt-semantic-layer |
| Instalação | getting-started/installation |
| Início rápido | getting-started/quickstart |
| Docker e implantação | getting-started/docker |
| Desenvolvimento | getting-started/development |
| Formato de modelo OBML | guide/model-format |
| Linguagem de consulta | guide/query-language |
| Dialetos SQL | guide/dialects |
| Métricas período a período | guide/period-over-period |
| Análise de tendências (rank / lag / lead / ntile, médias móveis particionadas, agregados estatísticos) | guide/trend-analysis |
| Pipeline de compilação | guide/compilation |
| Grafo OBSL e SPARQL | guide/obsl |
| Regras de negócio | guide/business-rules |
| Mapeamentos de conceitos externos | guide/concept-mappings |
| Interface Gradio | guide/ui |
| Integrações de IA | guide/integrations |
| Interoperabilidade OSI | guide/osi |
| Endpoints da API REST | api/endpoints |
| Drivers DB-API e Flight SQL | drivers |
| Arquitetura | reference/architecture |
| Configuração | reference/configuration |
| Exemplo prático do modelo de vendas | examples/sales-model |
| Saída multi-dialeto | examples/multi-dialect |
| Multi-fato: vendas e devoluções | examples/multi-fact |
| Benchmark TPC-DS | examples/tpcds |
| Notebook de início rápido | examples/quickstart.ipynb |
| Comparação: visão geral | comparison/ |
| Comparação: vs. dbt Semantic Layer | comparison/dbt |
| Comparação: vs. Malloy | comparison/malloy |
| Comparação: vs. LookML / Looker | comparison/lookml |
| Comparação: vs. Cube | comparison/cube |
| Comparação: vs. AtScale | comparison/atscale |
Status e roteiro
| Status | Área |
|---|---|
| Lançado | 8 dialetos SQL, API REST, servidor MCP, interface Gradio, drivers DB-API, Flight SQL, protocolo wire PostgreSQL (v2.5.0+) — Tableau / DBeaver / Superset / Power BI / psql / Dremio como fonte Postgres federada, OBSL/SPARQL, interoperabilidade OSI v0.2 com validação bidirecional de esquemas, integrações de IA (LangChain, CrewAI, ADK, etc.), herança e extensão de modelos, tipos de dados e precisão numérica, configurações de fuso horário, sobreposições de contexto de grão e filtro, Análise de tendências — janelas rolantes particionadas, MetricType.WINDOW para rank/lag/lead/ntile, 9 agregados estatísticos (CORR, COVAR_, REGR_, STDDEV_, VAR_), Autenticação unificada (v2.12.0) em REST / Flight / pgwire / UI — AUTH_MODE=api_key com armazenamento de chaves compartilhado, pgwire SCRAM-SHA-256 + texto claro, Resolução de Composabilidade de Artefatos (ACR, v2.14.0): um endpoint composables que, dada a consulta até o momento, retorna quais dimensões / medidas / métricas ainda podem ser adicionadas (incluindo candidatos CFL), potencializando a construção guiada de consultas |
| Planejado | Autenticação OIDC / SSO e escopos de autorização por token, CLI para automação e CI/CD, geração de visões DDL (CREATE VIEW a partir de consultas), dialetos adicionais, integrações adicionais de ferramentas de BI, camada de pré-agregação / materialização |
Ofertas comerciais
O OrionBelt Semantic Layer tem código-fonte disponível sob BUSL-1.1 até sua conversão para Apache-2.0 — a distribuição gratuita tem paridade total na superfície v2.6 lançada e é de nível de produção para uso auto-hospedado. Para equipes que desejam suporte de produção, um runtime gerenciado ou termos de análise embarcada, a RALFORION oferece:
- Licença de análise embarcada — termos de relicenciamento para distribuir OBSL dentro de um produto comercial
- Oferta de nuvem comercial — runtime OrionBelt gerenciado com SLAs
- Recursos empresariais — capacidades adaptadas para implantações corporativas
- Consultoria e suporte — implementação, modelagem e suporte de produção
Entre em contato com RALFORION d.o.o. para obter detalhes.
Projeto complementar
OrionBelt Analytics
Um servidor MCP baseado em ontologias que analisa esquemas de bancos de dados relacionais e gera ontologias RDF/OWL. Junto com o OrionBelt Semantic Layer, ele permite que assistentes de IA naveguem pelo seu cenário de dados por meio de ontologias e compilem SQL analítico seguro e ciente de dialetos.
Desenvolvimento
Contribuindo para o OrionBelt ou executando a partir do código-fonte:
git clone https://github.com/ralforion/orionbelt-semantic-layer.git
cd orionbelt-semantic-layer
uv sync # install all deps (dev, docs, ui, flight, drivers)
uv run orionbelt-api # start API on :8000
# Quality
uv run pytest # run tests
uv run ruff check src/ # lint
uv run ruff format src/ tests/ # format
uv run mypy src/ # type check
# Docs
uv sync --extra docs && uv run mkdocs serve # docs on :8080
# CI workflows
./scripts/check-action-pins.sh # verify every Action pin
./scripts/check-action-pins.sh --offline # skip the upstream tag lookups
Fixação do GitHub Actions
Cada uses: em .github/workflows é fixado a um SHA de commit de 40 caracteres
em vez de uma tag, porque uma tag como v7 é um rótulo móvel: ela executa
qualquer commit para o qual seu proprietário a apontou quando o job inicia. O
comentário # vX.Y.Z ao lado de cada SHA nomeia a versão exata de patch da qual esse SHA foi
cortado, e ela precisa ser uma versão de patch, pois uma tag principal se move a cada
atualização upstream.
Fixar define qual código é executado, mas torna a referência ilegível, então
scripts/check-action-pins.sh mantém o SHA e seu comentário honestos. Ele percorre
cada linha uses: e exige um SHA de commit, um proprietário de sua lista de permissões ALLOWED_OWNERS
e um comentário de versão de patch exata, então resolve essa tag upstream
com git ls-remote e falha quando o commit que ela nomeia não é o fixado.
Ações de contêiner devem ser fixadas por digest; ações locais ./ são ignoradas.
--offline verifica apenas o formato do SHA e do comentário, sem chamadas de rede.
A verificação é executada como o job pins no CI e como o primeiro passo após o checkout nos
workflows que publicam (Docker, PyPI, docs), para que uma tag nunca possa enviar
artefatos construídos por etapas cujas fixações nunca foram verificadas. Adicionar um proprietário a
ALLOWED_OWNERS é uma decisão deliberada: um SHA correspondente à sua própria tag não diz
nada sobre se essa ação pertence a este repositório.
Licença
Copyright © 2026 RALFORION d.o.o.
OrionBelt® é uma marca registrada da RALFORION d.o.o.
Licenciado sob a Business Source License 1.1 (SPDX: BUSL-1.1). O Trabalho Licenciado será convertido para Apache License 2.0 em 2030-03-16.
Trabalhos de terceiros redistribuídos pelo OrionBelt e seus termos estão listados em THIRD_PARTY_NOTICES.md.
Ao contribuir para este projeto, você concorda com o Contrato de Licença de Contribuidor.
Para consultas de licenciamento comercial, entre em contato: licensing@ralforion.com