build-model
Skill3 starsChanged 31 days agoMITView on GitHub
Builds a new dbt model from existing upstream models, following the repository's own naming, key, testing, documentation, and SQL conventions. Use when creating a staging, intermediate, fact, or dimension model, or when adding its tests and documentation.
4 other projects use a version of this.
Adopted by
Most recently taken up by
- maxencefaldor/brickytheir own version, first seen Nov 8, 2026
- nikhilw/structured-agentic-workflowtheir own version, first seen Nov 6, 2026
- daloopa/investingtheir own version, first seen Oct 8, 2026
- link7373/agentic-bi-teamtheir own version, first seen Sep 23, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- daloopa/investing★ 488same name
- maxencefaldor/bricky★ 20same name
- nikhilw/structured-agentic-workflow★ 7same name
- link7373/agentic-bi-team★ 4same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository24 other files it gives its agents.
- analytics-requirementsSkill
- api-pipelineSkill
- bi-modelSkill
- data-model-reviewSkill
- data-profileSkill
- data-quality-investigationSkill
- dbt-healthSkill
- explain-data-codeSkill
- freshness-investigationSkill
- incremental-modelSkill
- metric-definitionSkill
- migration-planSkill
- model-documentationSkill
- model-testsSkill
- project-profileSkill
- pr-reviewSkill
- refactor-modelSkill
- rename-modelSkill
- semantic-layerSkill
- source-setupSkill
- sql-reviewSkill
- trace-lineageSkill
- validate-dbtSkill
- yaml-maintenanceSkill
The file
We split this skill into the rules it gives an agent
10 rules. 0 are common, 10 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 4 edited versions we read keep these.
10
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 23
Create a staging, intermediate, fact, or dimension model from named upstream models or sources.
- Distinctive: line 24
Add the surrogate key, documentation, and tests that this repository would expect alongside a new model.
- Distinctive: line 25
Do not use this skill to design a warehouse from nothing, or to guess at columns that no upstream model exposes.
- Distinctive: line 34
Default silently to Work mode and build the model.
- Distinctive: line 42
Check candidate keys for the target grain.
- Distinctive: line 45
Write the model in the repository's SQL style, with CTE structure, comma placement, keyword case, and indent width taken from the profile …
- Distinctive: line 47
Document the model where this repository documents models, following its YAML strategy and filename pattern, and write descriptions in …
- Distinctive: line 48
Add the tests this repository attaches to a primary key, plus relationship tests where the repository uses them, plus any test justified by …
- Distinctive: line 58
Ask when two grains are genuinely plausible, which typically means a one-to-many join sits between two entities the request could …
- Distinctive: line 110
Never embed credentials, connection strings, or sampled row values in a model or its documentation.
“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- Generated by scripts/build_targets.py from src/skills. Edit the source and rebuild; changes made here are overwritten. -->Self-contained install.
<skill-dir>is the directory holding this file: substitute its absolute path in the commands below and run them from the repository root. Read<skill-dir>/references/operating-rules.mdbefore acting; it holds the toolkit's always-on rules, which this install cannot load on its own. This install has no safety hooks, so the approvals those rules describe rest on you and the agent rather than on an enforced gate.
Build Model
Produce the model a teammate familiar with this repository would have written. Infer everything the repository states; ask only for correctness-critical business or runtime facts it cannot establish.
First decision: is this a new model, and is its grain settled?
This workflow creates models. A request to change an existing model's logic or output is not a build: if that model is published (contract, public access, or read by a semantic model, metric, BI file, or exposure), the stop rule in data safety applies and the response is a plan with the consumers it affects, not an edit.
Settle this before writing anything. Read the inputs' keys and the join paths between them, then apply Determining grain below. If two grains survive, the response is # Grain Decision Needed and no model, documentation, or test file is written. Only a settled grain leads to # Model Build. A request phrased as "build" or "create" does not settle it, and neither does the entity named in the request or in the model's conventional name: when the inputs are at two grains, a request for an "X fact" fits both.
When the model computes a business measure (a rate, ratio, KPI, or status), also settle its definition: search the repository's docs, glossary, and existing models for that measure. If two live documents define it differently for the period the model covers, and the request does not choose between them knowingly, the response is # Definition Decision Needed and no file is written. The request choosing knowingly means it names the newer definition, or names the older one while acknowledging the revision. Naming the older one without mentioning a documented revision that applies to these periods is a premise, not a choice, even when the intent sounds clear or a document still permits the older measure with a label. Say what each definition counts, roughly how far apart the numbers land, and who already relies on each, then ask one direct question.
When to use
- Create a staging, intermediate, fact, or dimension model from named upstream models or sources.
- Add the surrogate key, documentation, and tests that this repository would expect alongside a new model.
- Do not use this skill to design a warehouse from nothing, or to guess at columns that no upstream model exposes.
Required context
Obtain:
- The target model's purpose and the upstream models or sources it draws from.
- The convention profile, from
.ae/project.ymlor fresh inference.
Default silently to Work mode and build the model. In Learn mode, explain each modeling decision as it is made. In Assessment mode, evaluate a submitted model without writing or repairing it.
Build procedure
- Establish the convention profile before naming anything. Prefixes, directories, surrogate key implementation, YAML strategy, test defaults, and SQL style all come from the repository, not from a question. When the requested layer has no prefix evidence, inspect neighboring final models, their directories, materializations, and upstream references before choosing a default. An established unprefixed final layer (for example
orders.sqlbesidecustomers.sql) is a convention, not an absence. - Inspect every named upstream model: its SQL, its documented columns, its tests, and what it references in turn. A column that no upstream model exposes does not exist, however natural its name.
- Determine each input's grain from its declared primary key, its uniqueness tests, or its aggregation. Where an input's grain is undeclared and untested, treat it as an assumption and record it.
- Determine the target grain, and stop here if two grains survive. Derive candidate grains from the keys of the inputs and the join paths between them, then apply the rule below. When the rule says to ask, the build ends at this step and you return the grain decision instead of a model. Do not continue to step 5 with an unresolved grain.
- Check candidate keys for the target grain. A single column that is unique at the target grain is the key; otherwise the key is the smallest column combination that is, and that combination is what the surrogate key hashes.
- Identify fanout risk and resolve it in the SQL, not in a caveat. A join from a coarser input to a finer one multiplies the coarser input's rows, so any measure carried from the coarser side is inflated. A warning in prose does not fix a column that a consumer will sum. Choose one: leave the coarser measure out of the finer-grain model and keep it in a model at its own grain, allocate it across the finer rows by an explicit and documented rule, or carry it on exactly one row per coarser key and null it elsewhere. Say which you chose and why. Selecting the coarser measure unchanged alongside a note that it should not be summed is the failure, not the mitigation.
Check when each joined input loads (its source description, freshness configuration, and the README's schedule), not only its keys. When a dimension loads later than the fact, the newest facts have no match yet: an inner join drops them and a bare left join leaves a null that a split-by-attribute report shows as a blank bucket. Left join, label the missing attribute with the project's unknown-member convention (or an explicit
'unknown') in the model, and say which rows get the label and when they fill in. - Write the model in the repository's SQL style, with CTE structure, comma placement, keyword case, and indent width taken from the profile rather than from preference.
- Generate the surrogate key with the implementation the repository already uses. Do not introduce a hashing macro or package that the project does not have.
- Document the model where this repository documents models, following its YAML strategy and filename pattern, and write descriptions in business terms. Reuse an existing docs block for any column that has one (
{{ doc('<name>') }}) instead of writing new prose. - Add the tests this repository attaches to a primary key, plus relationship tests where the repository uses them, plus any test justified by a specific risk you identified.
- Validate that every
refandsourceresolves to a model or source that exists in this project, and that every column selected exists upstream. - Check what the new model inherits. A directory's block in
dbt_project.ymlapplies to every model placed there, so a new model silently acquires that materialization and those platform settings. Read the block for the directory you are writing into and confirm each inherited key is valid for the model you built: a partition column must exist in the model, a cluster or sort column must exist, an incremental strategy needs a unique key, and a file format must suit the grain. Override explicitly what does not fit, and say what you overrode and why. Overriding the materialization does not clear the rest of the block, which is the trap: a dimension placed beside a partitioned event fact will still try to partition on a date column it does not have. - Report what was created, what needs approval, which conventions were applied, and what remains unverified.
Determining grain
Grain is the one decision the repository frequently cannot make for you, so treat it deliberately:
- Proceed without asking when a single grain is consistent with both the join path and the requested measures, and say which grain you chose in the output.
- Ask when two grains are genuinely plausible, which typically means a one-to-many join sits between two entities the request could reasonably be about. Present the candidates concretely, one row per order against one row per order item, rather than asking an open question.
- Requested measures often settle it. A measure that is additive only at the coarser grain implies the coarser grain, and building at the finer grain would double count it.
- A model whose grain cannot be stated in a single sentence is not ready to be written.
When two grains survive, asking is the deliverable. Return the grain decision and write no model file. Naming the alternative in a caveat and then building anyway is not asking; it hands over a finished model whose grain the requester never chose, which is the outcome this step exists to prevent.
A request to create the files does not settle the grain. Most requests are phrased as instructions to build, and a column list that spans both a header and its lines is evidence of ambiguity rather than a decision. Stopping to ask one question is the faster path for the requester, because a model built at the wrong grain has to be found, understood, and rebuilt after its numbers have already been quoted.
Failure modes
- Asking for a naming convention, directory, test set, or SQL style the repository already demonstrates.
- Selecting a column that exists in the request but not in any upstream model.
- Joining a coarser fact to a finer one and carrying the coarser measure through without aggregation, including when a warning about summing it accompanies the unchanged column.
- Treating a request to create files, or a column list spanning two grains, as having settled which grain the model should represent.
- Introducing a surrogate key implementation the project does not use, or hashing a column set that is not unique at the target grain.
- Adding uniqueness tests to a key that the join path cannot guarantee is unique.
- Joining an attribute from a dimension that loads after the fact and leaving the newest rows null, with an explicit label offered as a follow-up instead of applied.
- Documenting the implementation rather than the meaning, so the description restates the SQL.
- Writing files into a directory the repository does not use for that layer.
- Inventing
fct_ordim_because a legacy project expresses its final layer through unprefixed business names. - Accepting a directory's inherited
dbt_project.ymlconfiguration without checking that its partition, cluster, sort, or incremental settings are valid for the model's own columns.
Evidence required
Name the grain and the evidence for it. Cite the upstream file and column for every field selected, the test or declaration establishing each input's key, and the convention and its support count for every naming, style, or test decision. State plainly which assumptions are untested.
Output contract
There are two contracts, and the first decision selects which one applies.
When two grains survive, return # Grain Decision Needed, with: The question, naming both candidates as one row per X against one row per Y, followed by a grain diagram as described in <skill-dir>/references/diagrams.md; What each choice implies for the requested measures, including which become non-additive; Conventions already inferred, with support counts, so the answer does not have to be re-supplied; Inputs and their keys; What will be built once the grain is chosen. Create no model, documentation, or test file in this branch. This is a complete, successful response, not a refusal.
When two documented definitions survive, return # Definition Decision Needed, with: each definition, its document by file and line, and what it counts; roughly how far apart the numbers land, from figures in the repository when it has any; who already relies on each; what will be built once one is chosen; and, last, one direct question. Create no file in this branch.
When the grain is resolved, return # Model Build with: Changed, including every path; Why, including grain, inputs, keys, and conventions and what ruled the other grain candidate out, and for a business measure every documented definition you found (file and line) with the request's words that choose among them knowingly; Verified, including tests and static reference checks; Remaining uncertainty. Never print Mode: Work or internal skill routing.
List conventions as applied decisions with their support counts, not as questions. Keep Open risks for assumptions a warehouse query would have to settle.
Verification
- Confirm every
refandsourcenames a resource that exists in this project. - Confirm the surrogate key hashes a column combination that is unique at the stated grain.
- Confirm each selected column exists in the cited upstream model.
- Confirm every column named by an inherited or declared partition, cluster, or sort key exists in the model being written.
- Re-read the generated SQL against the profile's style conventions before finishing.
- Hand the completed scope to
validate-dbt, which plans the smallest selector and asks before any warehouse-capable command. Building the model itself never runs dbt.
Safety/privacy
- Static construction only. Never execute dbt, query a warehouse, or call MCP to build a model.
- Creating a new model file, a new documentation file, or a new test file is additive and permitted; report every path created.
- Explicitly requested reversible SQL/YAML/test/documentation edits may proceed without a second approval. Contract changes, renames, deletions, and edits outside the requested scope require preview, blast radius, and approval.
- Never embed credentials, connection strings, or sampled row values in a model or its documentation.
What not to assume
Do not assume an undeclared key is unique, that an upstream model's grain matches its name, that a one-to-many join is safe, that the requested measures are additive at the chosen grain, that a documented column is populated, or that passing tests upstream imply correctness at the new grain.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

