Business words¶
Not everyone who reads a story reads SQL. A finance lead does not want to see "order_cost: the total of supply_cost per order_id". They want "Order cost: the total of Supply cost per Order". Business words mode tells every story in your business's own words, and tucks the SQL and the technical names behind Show details.
It is deterministic, like the rest of the story engine: it needs no AI model and no network, and it gives the same answer every time.
Turn it on¶
In the web UI, open a model and choose Business words above its story. The choice is remembered in your browser. Technical switches back.
In business words you see:
- a title, which is the model's label, and a summary in plain sentences, such as "Orders brings together Staged orders and Order items into one row per Order"
- how it is built, as steps in business words (plain imports such as "Reads stg_orders." are left out)
- What you get: each column as a label and what it means
- Words used: the glossary definitions for the terms in the story
- a collapsed Show details that opens up the model name, file, SQL-ish steps, filters, and technical column names
Hover over, or tab to, a word with a dotted underline to read its definition. Press Enter or tap to keep it open, and Escape to close it.
On the command line:
openpipeline explain orders --business
openpipeline explain orders --business --json # includes the technical story too
Write a glossary¶
A glossary is a list of terms in openpipeline.yml, next to rules:. Each term names
a column, model, source, or seed and says what the business calls it.
glossary:
- name: customer_id # a column, model, source or seed name
label: Customer
definition: The person who placed the order. # optional
aliases: [user_id] # optional: other names that mean the same thing
- name: orders
label: Orders
definition: One row per order placed in a shop.
| Field | Required | What it means |
|---|---|---|
name |
yes | The model, column, source, or seed name. A source table can be written as source.table or, if no model has the same name, just table. Case does not matter. |
label |
yes | What your business calls it. |
definition |
no | What it means, in a sentence. Shown on hover and in Words used. |
aliases |
no | More names that use the same label and definition, such as user_id for customer_id. |
The Glossary tab lists every term.
Labels from dbt's own YAML¶
A model or a column can carry its label in dbt's meta:
models:
- name: customers
meta:
label: Customers
definition: One row per person who has signed up.
columns:
- name: lifetime_value
meta:
label: Lifetime value
meta works the same way when OpenPipeline reads files and when it reads
target/manifest.json. A column label applies to every column with that name. If
the same name has a label in openpipeline.yml and in meta, the
openpipeline.yml entry wins (a definition it leaves out is filled in from meta).
If two models give the same column different labels, the first is kept and a
warning says so.
Names you do not list¶
Anything without a term still gets a readable label, worked out from its name:
| Name | Label |
|---|---|
order_items_subtotal |
Order items subtotal |
customer_id |
Customer ID |
is_food_order |
Is food order |
stg_orders, fct_orders, dim_customers |
Orders, Orders, Customers |
claims__medical_claim (Tuva style) |
Medical claim |
The common dbt prefixes stg_, int_, fct_, fact_, dim_, base_, src_, and
mart_ are dropped from model names (not from column names), and for a name written
namespace__part only the part after the last double underscore is used. When two
models would end up with the same label, such as orders and stg_orders, the
prefixed one is told apart ("Staged orders"), as is a source table ("Raw orders").
A label you write in the glossary is never changed.
A column description from dbt is used as the column's definition when the glossary has none.
Warnings¶
Mistakes never stop OpenPipeline. They show up as warnings in the project banner and on the Glossary tab:
- a term without a
nameis skipped - a term without a
labelis kept, with a label worked out from its name - a name or alias used twice keeps the first term
What is and is not replaced¶
Labels are put in by recognising names in the story, not by searching and replacing
text. A word counts as a name when it is snake_case or is the name of a model,
source, or column. Quoted values such as 'completed' are never touched, nor are
function and macro names such as date_trunc(. The words the story itself uses
("the total of", "per") are never mistaken for column names, so a column called
total still reads correctly.
Suggestions from AI agents¶
Agents can call the MCP tool propose_glossary_term with a name, a label, and a
definition. It files a proposal that edits openpipeline.yml,
keeping every other line, comment, and rule in the file. Nothing is written until a
person accepts it in the UI. If the name already has a term, the proposal updates
its label and definition and keeps its aliases.
Agents can also read the glossary with list_glossary, and explain returns a
business view next to the technical story.
From the API¶
| Method and path | What it returns |
|---|---|
GET /api/models/{name}/business-story |
The story in business words. The technical story is inside it as technical. |
GET /api/glossary |
{"terms": [...], "warnings": [...]} |
See the HTTP API.