> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paradime.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Trigger Bolt schedules from Airflow

> Trigger Paradime Bolt schedules from Apache Airflow DAGs using the Paradime dbt provider, wait for runs to finish, and download dbt run artifacts.

Use the Paradime Airflow provider to trigger Bolt schedules from your [Apache Airflow](https://airflow.apache.org/) DAGs, wait for runs to complete, and download dbt™ run artifacts, so Bolt runs fit into your broader orchestration.

The provider is published on the Astronomer Registry: [airflow-provider-paradime-dbt](https://registry.astronomer.io/providers/airflow-provider-paradime-dbt/versions/latest).

## Install

```bash theme={"system"}
pip install airflow-provider-paradime-dbt
```

Then create a Paradime connection in Airflow using an [API key](/developers/api-keys) (key, secret, and endpoint), and reference it with `conn_id`. See the [Airflow operator reference](/developers/paradime-cli/airflow-cli) for connection setup.

<Info>
  `ParadimeBoltDbtScheduleRunOperator` identifies the schedule with either `slug` (stable) or `schedule_name`, and also accepts `commands`, `branch`, and `retry_from_failure`.
</Info>

## Trigger a Bolt schedule

This DAG triggers a run for a Bolt schedule, checks the run's status, and extracts the dbt™ artifacts.

```python theme={"system"}
from airflow.decorators import dag  # type: ignore[import]

from paradime_dbt_provider.operators.paradime import ParadimeBoltDbtScheduleRunArtifactOperator, ParadimeBoltDbtScheduleRunOperator
from paradime_dbt_provider.sensors.paradime import ParadimeBoltDbtScheduleRunSensor

PARADIME_CONN_ID = "your_paradime_conn_id"  # Update this to your connection id
BOLT_SCHEDULE_SLUG = "your_schedule_slug"  # Update this to your schedule slug


@dag(
    default_args={"conn_id": PARADIME_CONN_ID},
)
def run_schedule_and_download_manifest():
    # Run the schedule and return the run id as the xcom return value
    task_run_schedule = ParadimeBoltDbtScheduleRunOperator(task_id="run_schedule", slug=BOLT_SCHEDULE_SLUG)

    # Get the run id from the xcom return value
    run_id = "{{ task_instance.xcom_pull(task_ids='run_schedule') }}"

    # Wait for the schedule to complete before continuing
    task_wait_for_schedule = ParadimeBoltDbtScheduleRunSensor(task_id="wait_for_schedule", run_id=run_id)

    # Download the manifest.json file from the schedule run and return the path as the xcom return value
    task_download_manifest = ParadimeBoltDbtScheduleRunArtifactOperator(task_id="download_manifest", run_id=run_id, artifact_path="target/manifest.json")

    # Get the path to the manifest.json file from the xcom return value
    output_path = "{{ task_instance.xcom_pull(task_ids='download_manifest') }}"

    task_run_schedule >> task_wait_for_schedule >> task_download_manifest


run_schedule_and_download_manifest()
```

## Trigger a Bolt schedule with custom commands

This DAG overrides the dbt™ commands the run executes at runtime, then checks the run's status and extracts the artifacts.

```python theme={"system"}
from airflow.decorators import dag  # type: ignore[import]

from paradime_dbt_provider.operators.paradime import ParadimeBoltDbtScheduleRunArtifactOperator, ParadimeBoltDbtScheduleRunOperator
from paradime_dbt_provider.sensors.paradime import ParadimeBoltDbtScheduleRunSensor

PARADIME_CONN_ID = "your_paradime_conn_id"  # Update this to your connection id
BOLT_SCHEDULE_SLUG = "your_schedule_slug"  # Update this to your schedule slug


@dag(
    default_args={"conn_id": PARADIME_CONN_ID},
)
def run_schedule_with_custom_commands():
    # Define the custom commands to run
    custom_commands = ["dbt run", "dbt test"]

    # Run the schedule with custom commands and return the run id as the xcom return value
    task_run_schedule = ParadimeBoltDbtScheduleRunOperator(task_id="run_schedule", slug=BOLT_SCHEDULE_SLUG, commands=custom_commands)

    # Get the run id from the xcom return value
    run_id = "{{ task_instance.xcom_pull(task_ids='run_schedule') }}"

    # Wait for the schedule to complete before continuing
    task_wait_for_schedule = ParadimeBoltDbtScheduleRunSensor(task_id="wait_for_schedule", run_id=run_id)

    # Download the manifest.json file from the schedule run and return the path as the xcom return value
    task_download_manifest = ParadimeBoltDbtScheduleRunArtifactOperator(task_id="download_manifest", run_id=run_id, artifact_path="target/manifest.json")

    # Get the path to the manifest.json file from the xcom return value
    output_path = "{{ task_instance.xcom_pull(task_ids='download_manifest') }}"

    task_run_schedule >> task_wait_for_schedule >> task_download_manifest


run_schedule_with_custom_commands()
```


## Related topics

- [Trigger Bolt schedules from Dagster](/products/bolt/external-triggers/dagster.md)
- [Bolt CLI](/developers/paradime-cli/bolt-cli.md)
- [Airflow](/integrations/airflow.md)
- [Triggers](/products/bolt/creating-schedules/trigger-types.md)
- [External Triggers](/products/bolt/external-triggers/index.md)
