Skip to content

Data Engineering Recipes

The data engineering recipes are copy-paste prompts for Claude Code, Codex, and Cursor covering dbt models, SQL pipelines, notebooks, and data tests. Every recipe follows the same contract: the agent reads the project through the dbt MCP server, builds only on a dev target, and returns dbt build output plus a row-level diff instead of SQL for a human to read.

It is for developers and analytics engineers who let an agent change a pipeline, and it guards against one failure: the model compiles, then the revenue dashboard moves because a join fanned out.

Which data engineering recipe fits your task?

Section titled “Which data engineering recipe fits your task?”
Your taskRecipeThe gate that proves it
Add or change a dbt modelBuild a dbt model test-firstUnit tests written before the SQL; dbt build on the model and everything downstream
Refactor a model without changing its numbersRefactor with a row-level diffaudit_helper comparison against production: zero changed rows
Clean up or productionize a Jupyter notebookKeep notebooks reviewablePaired .py diff plus pytest --nbval-lax on a clean kernel
Tune a slow warehouse query or plan a schema changeSQL optimization and migration patternsQuery plan and timing before and after; up, down, up on a copy

For ingestion jobs and APIs in Python, use the Python workflow recipes; for everything else, the AI Developer Cookbook.

Give the agent your data rules before any recipe

Section titled “Give the agent your data rules before any recipe”

Without rules, an agent runs dbt run against the default target and “fixes” a failing test by deleting it. Write the rules once, where each tool loads them:

## Data rules
- Never run dbt against the prod target. Use --target dev; the default target in profiles.yml is dev.
- Select only what changed: --select state:modified+ --defer --state prod-artifacts
- Never delete, disable, or loosen a data test (severity, where:, error_if) to make a build pass.
Report the failure and stop.
- Never SELECT raw columns tagged pii; profile them with counts and null rates only.
- After any change, run scripts/verify-dbt.sh and paste the full output in your summary.

Add the block to CLAUDE.md at the repository root. Claude Code loads it in every session, including headless claude -p runs.

prod-artifacts/ holds the last production manifest.json, so only your changes build. Before each run, download that manifest.json from your last production run’s CI artifacts into prod-artifacts/; state:modified and --defer fail without it.

Connect the dbt MCP server and the dbt agent skills

Section titled “Connect the dbt MCP server and the dbt agent skills”

The dbt MCP server from dbt Labs (PyPI dbt-mcp, requires Python 3.12 or 3.13) gives the agent lineage, node details, list, compile, and show. The dbt agent skills (dbt-labs/dbt-agent-skills) teach dbt conventions such as unit tests. The commands below disable the server’s run, build, test, clone, and docs tools, so every build goes through the gate script:

Terminal window
# Terminal, from the dbt project root. Requires uv and dbt on PATH (or set DBT_PATH).
claude mcp add dbt -e DBT_PROJECT_DIR="$PWD" -e DISABLE_TOOLS=run,build,test,clone,docs -- uvx dbt-mcp
# In the Claude Code prompt: install the skills as a plugin
/plugin marketplace add dbt-labs/dbt-agent-skills
/plugin install dbt@dbt-agent-marketplace

The show tool still runs SQL through profiles.yml, so the default target must be dev. For warehouse access outside dbt, see database MCP servers.

Write the expected rows before the SQL. dbt unit tests (unit_tests:, dbt Core 1.8 and later) assert the output for fixed input rows, so guessing cannot pass. This is the test-driven loop applied to SQL.

Refactor a dbt model without changing the numbers

Section titled “Refactor a dbt model without changing the numbers”

Data proves a refactor, not the diff. The audit_helper package (dbt Hub dbt-labs/audit_helper) compares the dev build with the production relation row by row. The prompt aggregates the result, because dbt show prints five rows by default and the macro returns at most 20 sample rows per status.

Agents edit .ipynb JSON poorly. Pair each notebook with a script via Jupytext (jupytext --set-formats ipynb,py:percent notebook.ipynb), let the agent edit the .py file, and prove the result with nbval on a clean kernel.

How do you verify agent-written data changes without reading every line?

Section titled “How do you verify agent-written data changes without reading every line?”

Put the gates in one script that every tool, human, and CI runs. It refuses prod and builds with zero rows before the real build:

#!/usr/bin/env bash
# scripts/verify-dbt.sh: dev target only. Delete the lines your project does not use.
set -euo pipefail
TARGET="${DBT_TARGET:-dev}"
if [ "$TARGET" = "prod" ]; then echo "refusing to run against prod"; exit 1; fi
SEL=(--select state:modified+ --defer --state prod-artifacts --target "$TARGET")
[ -d dbt_packages ] || dbt deps # needs network; skipped once packages are installed
dbt parse --warn-error --target "$TARGET"
dbt build "${SEL[@]}" --empty
dbt build "${SEL[@]}"
sqlfluff lint models/
pytest --nbval-lax notebooks/
echo "PASS all data gates"

Make the script executable once, so the allow rules below can call it without a bash prefix:

Terminal window
chmod +x scripts/verify-dbt.sh

A human signs off on two things only: the row-level comparison for any change to a model that feeds a dashboard or an export, and any --full-refresh of an incremental model. Both go in the pull request’s evidence bundle. To run the gates unattended, save this fix-until-green prompt as prompts/dbt-gates.txt:

Terminal window
# Terminal, on a trusted branch. Edits allowed; shell limited to the gate
# script; dbt MCP tools allowed (run/build/test/clone/docs are disabled on the server).
claude -p "$(cat prompts/dbt-gates.txt)" \
--allowedTools "Read,Grep,Glob,Edit,Bash(scripts/verify-dbt.sh),Bash(./scripts/verify-dbt.sh),mcp__dbt" \
--output-format json > dbt-gates.json

What breaks when agents write data pipelines?

Section titled “What breaks when agents write data pipelines?”