A curated collection of Agent Skills for working with dbt, to help AI agents understand and execute dbt workflows more effectively.
71
89%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Groups and access modifiers work together to organize models by team ownership and control which models can reference each other.
Groups represent domains of resources owned by a specific team. They make ownership explicit — when something breaks, you know who to contact.
Groups can be defined in a standalone YAML file or alongside model definitions:
# models/_groups.yml (or any .yml file in your models directory)
groups:
- name: finance
owner:
name: Firstname Lastname
email: finance@jaffleshop.com
slack: finance-data
github: finance-data-team
- name: product
owner:
email: product@jaffleshop.com
github: product-data-teamOwner requirements: At least name or email is required. Other properties (slack, github) are optional.
Three ways to assign a model to a group:
1. In model YAML (recommended for individual models):
models:
- name: fct_orders
config:
group: finance2. In dbt_project.yml (recommended for directory-level assignment):
# dbt_project.yml
models:
my_project:
marts:
finance:
+group: finance
marketing:
+group: marketing3. In SQL config block:
-- models/marts/finance/fct_orders.sql
{{ config(group='finance') }}
select ...Groups apply to: models, seeds, snapshots, tests, analyses, metrics, semantic models, and saved queries.
Access modifiers control which models can ref yours:
| Access | Who Can Reference | Use Case |
|---|---|---|
private | Same group only | Internal implementation details, rapidly changing models |
protected | Same project (or installed as a package) | Standard intra-project models (this is the default) |
public | Any group, package, or project | Stable APIs intended for cross-team or cross-project consumption |
Important: access is a config property and must be nested under config: in YAML property files. Placing it as a top-level model property breaks the Fusion engine. The same applies to group — always co-locate them under config:.
# ✅ CORRECT
models:
- name: fct_orders
config:
group: finance
access: public
# ❌ WRONG — breaks Fusion
models:
- name: fct_orders
access: public # not under config:
group: finance # not under config:In dbt_project.yml at the directory level, use the + prefix:
models:
my_project:
staging:
+access: private
+group: platform
marts:
+access: protectedOr in SQL:
{{ config(access='public', group='finance') }}protected — all models in a project can reference each other regardless of groupprivate models trigger a DbtReferenceError if referenced from outside their grouppublic models are the only models visible to other projects via cross-project ref()public — attempting this causes a parsing errorAccess and contracts are complementary:
| Access Level | Contract Recommended? | Why |
|---|---|---|
public | Yes | Consumers outside your project depend on schema stability |
protected | Optional | Useful for high-criticality intra-project models |
private | No | Internal models change frequently; contracts add friction |
# models/_groups.yml
groups:
- name: finance
owner:
email: finance-data@company.com
- name: marketing
owner:
email: marketing-data@company.com
# models/marts/finance/_finance_models.yml
models:
- name: fct_revenue
config:
group: finance
access: public # Other projects can ref this
contract:
enforced: true
columns:
- name: revenue_id
data_type: varchar
- name: amount
data_type: numeric(38, 2)
- name: recorded_at
data_type: timestamp_ntz
- name: int_revenue_daily
config:
group: finance
access: private # Only finance group can ref this
# models/marts/marketing/_marketing_models.yml
models:
- name: fct_campaigns
config:
group: marketing
access: protected # Same project can ref, other projects cannotIn this setup:
fct_revenue is available to anyone (public, contracted)int_revenue_daily is only available within the finance groupfct_campaigns is available to all models in the same project but not to other projectsfct_campaigns tries to ref('int_revenue_daily'), dbt raises a DbtReferenceErrorprivate for new models and widen access only when there's a real consumerpublic with a contract — a public model without a contract is a liabilitydbt_project.yml when your directory structure mirrors team ownership| Mistake | Fix |
|---|---|
| Not assigning a group to private models | private access requires a group — dbt errors without one |
Making everything public | Only public-ify models that are intentional cross-team APIs |
| Creating groups that don't map to real teams | Groups need an owner who can respond when things break |
Relying on protected (default) when private is more appropriate | Be intentional — protected is permissive within the project |
Expecting access to control database permissions | Access modifiers are a dbt concept — manage database permissions separately |
Placing access or group as top-level model properties in YAML | Nest under config: — top-level placement breaks Fusion |
evals
skills
dbt
skills
adding-dbt-unit-test
references
answering-natural-language-questions-with-dbt
building-dbt-semantic-layer
configuring-dbt-mcp-server
fetching-dbt-docs
scripts
running-dbt-commands
troubleshooting-dbt-job-errors
references
using-dbt-for-analytics-engineering
working-with-dbt-mesh
dbt-extras
skills
creating-mermaid-dbt-dag
dbt-migration
skills
migrating-dbt-core-to-fusion
migrating-dbt-project-across-platforms