Home Insight and Narrative Documenting a dbt model with an LLM: what to automate and what to write yourself

Documenting a dbt model with an LLM: what to automate and what to write yourself

A line between the documentation an LLM should generate wholesale and the sentences only the person who built the model can honestly write.

By Tomas Rivera, a data journalist and insight-communication coach · Published 18 June 2026 · 8 min read · Reviewed against our editorial standards

ADVERTISEMENT

Every analytics engineer has inherited a model with 60 columns and a description: field that just repeats the column name. customer_id is documented as "The customer id." This is worse than nothing, because it looks like documentation and passes the linter while telling a downstream analyst exactly zero things they did not already know.

LLMs are genuinely good at killing that specific problem. They are also capable of generating a fresh, more convincing version of it at scale. The skill in 2026 is knowing which parts of dbt documentation are mechanical translation and which parts encode judgment that lives only in your head.

The two kinds of documentation in a dbt model

Split every doc string into two buckets. The first describes what the code does: this column is a cast of that source field, this model joins orders to customers on customer_id, this metric sums line-item revenue. All of that is recoverable from the SQL itself. An LLM reading the compiled model can write it accurately, and you should let it.

The second describes what the code means and why it is the way it is: that revenue_net excludes tax and shipping because Finance defines it that way, that the is_active flag uses a 30-day window chosen to match the marketing team's definition and not the product team's, that this model silently drops test accounts via a filter three CTEs up. None of that is in the SQL. The LLM will either omit it or, worse, guess. That bucket is yours.

Automate the mechanical layer, and gate it

The tooling here is mature. dbt Cloud's assistant will draft column descriptions from a model's compiled SQL. dbt-osmosis propagates column documentation and tests down through the DAG so you write a description once at the source and it flows to every model that inherits the column. Cursor or Claude Code pointed at your models/ directory will fill in YAML for a whole folder in one pass.

The move that makes this safe is treating generated docs as a pull request, never a direct write. I have teams run the generator into a branch, then review the diff like any other code review. Two rules on that review. Reject any description that merely restates the column name, even if the LLM padded it with words. And reject any description that asserts business meaning the model cannot prove, because that is the model hallucinating semantics from a name. If a column is called mrr, the LLM will happily write "Monthly recurring revenue in USD" when your grain is actually quarterly and the currency is mixed. The name lied to the model, and the model believed it.

Give the model your definitions, don't ask it to infer them

The quality jump comes from context. An LLM staring at raw SQL infers meaning; an LLM handed your semantic layer or a glossary translates it. If you run dbt's semantic layer or a metrics spec, feed those definitions into the prompt so the generated column descriptions reference the canonical metric rather than a guess.

A prompt I use for a batch pass, run against a single model at a time:

Here is the compiled SQL for the model `fct_subscriptions`
and our metrics glossary (attached).

For each column, write a one-sentence description that:
- states the grain and unit where relevant
- references a glossary term by name if one applies
- does NOT restate the column name
- writes [BUSINESS-RULE?] if the column's meaning depends on
  a filter or business rule you cannot verify from the SQL

Do not invent currency, timezone, or definitional details.

That [BUSINESS-RULE?] tag is the whole trick. It converts the model's uncertainty into a checklist of exactly the sentences you need to write yourself. When it flags churned_at with the tag, that is your cue to document that churn is defined as 30 days past due, not the cancellation timestamp, a distinction no reader will guess and no LLM can recover.

Sentences that must come from you

A short list of documentation that an LLM should never author unassisted, because getting it wrong causes real downstream errors:

You can absolutely draft these with the LLM as a writing partner, pasting in the facts and letting it tighten the prose. What you cannot do is let it originate the facts.

Model-level docs and the description that gets read

Column docs get skimmed; the model-level description gets read when someone is deciding whether to trust the table. This is where an LLM makes a good ghostwriter and a bad author. Give it three or four bullet points you wrote, the model's purpose, its grain, its main gotcha, and its refresh cadence, and ask it to turn them into a tight paragraph. It will produce something cleaner than most of us write under deadline. The judgment is in your bullets; the polish is the model's job.

Resist the urge to let it write the mermaid-diagram-in-prose lineage description. Your DAG already is the lineage, rendered better than any paragraph. Documentation should add what the graph cannot show.

Keep it from rotting

Generated docs decay the moment the SQL changes and nobody re-runs the generator. Two habits keep them honest. Put the doc-generation step in CI so a model change with stale docs shows up in review, and add a dbt test or a simple check that fails when a description exactly equals its column name, which catches both the lazy human default and the lazy LLM default. Documentation that is enforced is documentation that survives; everything else is a snapshot of what was true the day someone ran the tool.

The honest summary: let the LLM write the layer that restates your code, because it does that faster and more consistently than you will. Reserve for yourself every sentence that encodes a decision, an exclusion, or a definition, because those are the sentences a future analyst will trust blindly, and they need to be true.

dbtdocumentationllmdata-modeling

A note on shelf life. AI products change fast. This guide deliberately focuses on the parts that stay true — how to judge a tool, what the trade-offs are — rather than ranking products that will have changed by the time you read it. Prices and feature claims should always be checked against the provider before you rely on them.