Use this skill when the user wants to convert a Prefect task that runs dbt Core commands — DbtCoreOperation block, ShellOperation running dbt CLI, run_dbt_build / run_dbt_test tasks, or DbtCloudJob — into an equivalent Orchestra pipeline task. Triggers: any mention of migrating or rewriting Prefect dbt tasks to Orchestra; any Prefect flow code importing from prefect_dbt; ShellOperation commands starting with 'dbt '.
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Converts Prefect dbt tasks into Orchestra pipeline YAML. Two dbt variants exist:
DbtCoreOperation, ShellOperation running dbt CLI): integration: DBT_CORE, integration_job: DBT_CORE_EXECUTEDbtCloudJob): integration: DBT, integration_job: DBT_RUNJOBThe commands list from Prefect is joined into a single semicolon-delimited string. Warehouse credentials and Git repo details go on the Orchestra dbt Core connection, not in YAML.
| Prefect construct | Orchestra field | Notes |
|---|---|---|
DbtCoreOperation(commands=[...]) | parameters.commands | Join list items with ; — e.g. 'dbt seed; dbt build;' |
| Python version | parameters.python_version | '3.11', '3.12', '3.13' or '3.14' — defaults to '3.12'. Carry the source project's version over when it's one of these; if it pins something older or newer, flag it rather than silently downgrading |
| pip / poetry / uv | parameters.package_manager | PIP, POETRY, or UV — infer from visible project files (poetry.lock/pyproject.toml → POETRY, uv.lock → UV, requirements.txt/Pipfile → PIP). If none of that is visible, don't silently guess PIP — see Gotchas |
| Git repo + profiles.yml / warehouse creds | connection: | Set up in Connectors → dbt Core |
--select, --exclude, --target flags | inline in parameters.commands | e.g. dbt build --select tag:daily --target prod; |
project_dir | parameters.project_dir | A real task parameter — the subdirectory holding dbt_project.yml. Carry the value over; null if the project is at the repo root |
DbtCloudJob(job_id=..., account_id=...) | integration: DBT, integration_job: DBT_RUNJOB, parameters.job_id | account_id goes on the Orchestra dbt Cloud connection |
ShellOperation(commands=["dbt build"]) | same as DbtCoreOperation | Treat identically |
dbt Core:
version: v1
name: dbt-flow
pipeline:
stage-001:
tasks:
task-001:
integration: DBT_CORE
integration_job: DBT_CORE_EXECUTE
name: dbt_daily_build
connection: data_dbt_bigquery_prod_12345
parameters:
commands: 'dbt seed; dbt build --select tag:daily --target prod;'
package_manager: PIP
python_version: '3.12'
project_dir: null # optional — subdirectory holding dbt_project.yml, e.g. 'dbt' in a monorepo
depends_on: []
condition: null
tags: []dbt Cloud:
version: v1
name: dbt-cloud-flow
pipeline:
stage-001:
tasks:
task-001:
integration: DBT
integration_job: DBT_RUNJOB
name: dbt_cloud_job
connection: dbt_cloud_prod_12345
parameters:
job_id: '123456'
depends_on: []
condition: null
tags: []DbtCoreOperation / ShellOperation → DBT_CORE; DbtCloudJob → DBTcommands list with '; ' and append trailing ; into parameters.commandsparameters.package_manager (PIP/POETRY/UV) to match project setup — if it can't be inferred, add a # MANUAL: comment flagging it for the user to confirm/select when they set up the dbt Core connection, rather than silently defaulting to PIPparameters.python_version ('3.11', '3.12', '3.13' or '3.14') — match the source project's Python version where it's supported, rather than defaulting to '3.12' regardlessproject_dir over to parameters.project_dir (a real task parameter — don't drop it); move profiles.yml and warehouse credentials to the Orchestra dbt Core connectionparameters.job_id to the numeric job ID string; set account_id on the connectionconnection: to the appropriate Orchestra connection namedepends_on: if this task follows a Fivetran sync or other upstream taskalerts: block if the Prefect flow had on_failure/on_completion hooksfrom prefect import flow
from prefect_dbt.cli import DbtCoreOperation
@flow
def dbt_flow():
with DbtCoreOperation(
commands=["dbt seed", "dbt build --select tag:daily --target prod"],
project_dir="dbt_project",
) as dbt_op:
dbt_op.run()version: v1
name: dbt-flow
pipeline:
stage-001:
tasks:
task-001:
integration: DBT_CORE
integration_job: DBT_CORE_EXECUTE
name: dbt_daily_build
connection: data_dbt_bigquery_prod_12345
parameters:
commands: 'dbt seed; dbt build --select tag:daily --target prod;'
package_manager: PIP
python_version: '3.12'
project_dir: dbt_project # from DbtCoreOperation(project_dir="dbt_project") in the source above
depends_on: []
condition: null
tags: []A dbt Core connection needs warehouse credentials, but they don't have to be re-typed into it. If the warehouse already exists as its own Orchestra connection — the Snowflake/Postgres/BigQuery connection the rest of the pipeline already uses — link it under Linked connections on the dbt Core connection's form rather than pasting the same password into that connection's Secrets. One credential, one place to rotate it.
Linked fields arrive as environment variables named <INTEGRATION>__<CONNECTION_ID>__<FIELD>: every part upper-cased, each run of non-alphanumeric characters collapsed to a single _, and the parts joined by a double underscore. <CONNECTION_ID> is the id the YAML's connection: field uses (it survives renames), and <FIELD> is the field's ID from that integration's Authentication parameters table. Read them in profiles.yml with dbt's env_var():
my_project:
target: prod
outputs:
prod:
type: snowflake
account: "{{ env_var('SNOWFLAKE__PROD_12345__SNOWFLAKE_ACCOUNT') }}"
user: "{{ env_var('SNOWFLAKE__PROD_12345__SNOWFLAKE_USER') }}"
password: "{{ env_var('SNOWFLAKE__PROD_12345__SNOWFLAKE_PASSWORD') }}"SNOWFLAKE__PROD_12345__SNOWFLAKE_PRIVATE_KEY instead of a password — check the integration's field IDs rather than assuming password.Full reference: Linked connections.
DbtCoreOperation.commands is a Python list — join with semicolons for Orchestra ('dbt seed; dbt build;'); a missing trailing ; can cause parse errorsproject_dir is a real task parameter — carry DbtCoreOperation(project_dir=...)'s value over to parameters.project_dir instead of dropping it. Only null it if the dbt project genuinely sits at the repo root.profiles.yml and warehouse credentials go on the Orchestra dbt Core connection, never in YAML; if the warehouse is already its own Orchestra connection, link it rather than copying its secrets across (see above)DbtCloudJob (Cloud) uses a different integration pair: integration: DBT, integration_job: DBT_RUNJOB, parameters: {job_id: "123456"}ShellOperation(commands=["dbt build"]) is treated identically to DbtCoreOperation--select, --exclude, and --target flags belong inside the commands string, not as separate parameterspackage_manager: don't just guess PIP and move on. Flag it instead:
package_manager: PIP # MANUAL: could not detect pip/poetry/uv from the source — confirm/select the correct package manager when setting up the dbt Core connectionSee prefect-alerts-to-orchestra for all notification patterns.
orchestra-hq/orchestra-skills
8f6c1bc
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.