$npx -y skills add astronomer/agents --skill testing-dagsComplex DAG testing workflows with debugging and fixing cycles. Use for multi-step testing requests like "test this dag and fix it if it fails", "test and debug", "run the pipeline and troubleshoot issues". For simple test requests ("test dag", "run dag"), the airflow entrypoint
| 1 | # DAG Testing Skill |
| 2 | |
| 3 | Use `af` commands to test, debug, and fix DAGs in iterative cycles. |
| 4 | |
| 5 | ## Running the CLI |
| 6 | |
| 7 | These commands assume `af` is on PATH. Run via `astro otto` to get it automatically, or install standalone with `uv tool install astro-airflow-mcp`. |
| 8 | |
| 9 | --- |
| 10 | |
| 11 | ## Quick Validation with Astro CLI |
| 12 | |
| 13 | If the user has the Astro CLI available, these commands provide fast feedback without needing a running Airflow instance: |
| 14 | |
| 15 | ```bash |
| 16 | # Parse DAGs to catch import errors, syntax issues, and DAG-level problems |
| 17 | astro dev parse |
| 18 | |
| 19 | # Run pytest against DAGs (runs tests in tests/ directory) |
| 20 | astro dev pytest |
| 21 | ``` |
| 22 | |
| 23 | Use these for quick validation during development. For full end-to-end testing against a live Airflow instance, continue to the trigger-and-wait workflow below. |
| 24 | |
| 25 | --- |
| 26 | |
| 27 | ## FIRST ACTION: Just Trigger the DAG |
| 28 | |
| 29 | When the user asks to test a DAG, your **FIRST AND ONLY action** should be: |
| 30 | |
| 31 | ```bash |
| 32 | af runs trigger-wait <dag_id> |
| 33 | ``` |
| 34 | |
| 35 | **DO NOT:** |
| 36 | - Call `af dags list` first |
| 37 | - Call `af dags get` first |
| 38 | - Call `af dags errors` first |
| 39 | - Use `grep` or `ls` or any other bash command |
| 40 | - Do any "pre-flight checks" |
| 41 | |
| 42 | **Just trigger the DAG.** If it fails, THEN debug. |
| 43 | |
| 44 | --- |
| 45 | |
| 46 | ## Testing Workflow Overview |
| 47 | |
| 48 | ``` |
| 49 | ┌─────────────────────────────────────┐ |
| 50 | │ 1. TRIGGER AND WAIT │ |
| 51 | │ Run DAG, wait for completion │ |
| 52 | └─────────────────────────────────────┘ |
| 53 | ↓ |
| 54 | ┌───────┴───────┐ |
| 55 | ↓ ↓ |
| 56 | ┌─────────┐ ┌──────────┐ |
| 57 | │ SUCCESS │ │ FAILED │ |
| 58 | │ Done! │ │ Debug... │ |
| 59 | └─────────┘ └──────────┘ |
| 60 | ↓ |
| 61 | ┌─────────────────────────────────────┐ |
| 62 | │ 2. DEBUG (only if failed) │ |
| 63 | │ Get logs, identify root cause │ |
| 64 | └─────────────────────────────────────┘ |
| 65 | ↓ |
| 66 | ┌─────────────────────────────────────┐ |
| 67 | │ 3. FIX AND RETEST │ |
| 68 | │ Apply fix, restart from step 1 │ |
| 69 | └─────────────────────────────────────┘ |
| 70 | ``` |
| 71 | |
| 72 | **Philosophy: Try first, debug on failure.** Don't waste time on pre-flight checks — just run the DAG and diagnose if something goes wrong. |
| 73 | |
| 74 | --- |
| 75 | |
| 76 | ## Phase 1: Trigger and Wait |
| 77 | |
| 78 | Use `af runs trigger-wait` to test the DAG: |
| 79 | |
| 80 | ### Primary Method: Trigger and Wait |
| 81 | |
| 82 | ```bash |
| 83 | af runs trigger-wait <dag_id> --timeout 300 |
| 84 | ``` |
| 85 | |
| 86 | **Example:** |
| 87 | |
| 88 | ```bash |
| 89 | af runs trigger-wait my_dag --timeout 300 |
| 90 | ``` |
| 91 | |
| 92 | **Why this is the preferred method:** |
| 93 | - Single command handles trigger + monitoring |
| 94 | - Returns immediately when DAG completes (success or failure) |
| 95 | - Includes failed task details if run fails |
| 96 | - No manual polling required |
| 97 | |
| 98 | ### Response Interpretation |
| 99 | |
| 100 | **Success:** |
| 101 | ```json |
| 102 | { |
| 103 | "dag_run": { |
| 104 | "dag_id": "my_dag", |
| 105 | "dag_run_id": "manual__2025-01-14T...", |
| 106 | "state": "success", |
| 107 | "start_date": "...", |
| 108 | "end_date": "..." |
| 109 | }, |
| 110 | "timed_out": false, |
| 111 | "elapsed_seconds": 45.2 |
| 112 | } |
| 113 | ``` |
| 114 | |
| 115 | **Failure:** |
| 116 | ```json |
| 117 | { |
| 118 | "dag_run": { |
| 119 | "state": "failed" |
| 120 | }, |
| 121 | "timed_out": false, |
| 122 | "elapsed_seconds": 30.1, |
| 123 | "failed_tasks": [ |
| 124 | { |
| 125 | "task_id": "extract_data", |
| 126 | "state": "failed", |
| 127 | "try_number": 2 |
| 128 | } |
| 129 | ] |
| 130 | } |
| 131 | ``` |
| 132 | |
| 133 | **Timeout:** |
| 134 | ```json |
| 135 | { |
| 136 | "dag_id": "my_dag", |
| 137 | "dag_run_id": "manual__...", |
| 138 | "state": "running", |
| 139 | "timed_out": true, |
| 140 | "elapsed_seconds": 300.0, |
| 141 | "message": "Timed out after 300 seconds. DAG run is still running." |
| 142 | } |
| 143 | ``` |
| 144 | |
| 145 | ### Alternative: Trigger and Monitor Separately |
| 146 | |
| 147 | Use this only when you need more control: |
| 148 | |
| 149 | ```bash |
| 150 | # Step 1: Trigger |
| 151 | af runs trigger my_dag |
| 152 | # Returns: {"dag_run_id": "manual__...", "state": "queued"} |
| 153 | |
| 154 | # Step 2: Check status |
| 155 | af runs get my_dag manual__2025-01-14T... |
| 156 | # Returns current state |
| 157 | ``` |
| 158 | |
| 159 | --- |
| 160 | |
| 161 | ## Handling Results |
| 162 | |
| 163 | ### If Success |
| 164 | |
| 165 | The DAG ran successfully. Summarize for the user: |
| 166 | - Total elapsed time |
| 167 | - Number of tasks completed |
| 168 | - Any notable outputs (if visible in logs) |
| 169 | |
| 170 | **You're done!** |
| 171 | |
| 172 | ### If Timed Out |
| 173 | |
| 174 | The DAG is still running. Options: |
| 175 | 1. Check current status: `af runs get <dag_id> <dag_run_id>` |
| 176 | 2. Ask user if they want to continue waiting |
| 177 | 3. Increase timeout and try again |
| 178 | |
| 179 | ### If Failed |
| 180 | |
| 181 | Move to Phase 2 (Debug) to identify the root cause. |
| 182 | |
| 183 | --- |
| 184 | |
| 185 | ## Phase 2: Debug Failures (Only If Needed) |
| 186 | |
| 187 | When a DAG run fails, use these commands to diagnose: |
| 188 | |
| 189 | ### Get Comprehensive Diagnosis |
| 190 | |
| 191 | ```bash |
| 192 | af runs diagnose <dag_id> <dag_run_id> |
| 193 | ``` |
| 194 | |
| 195 | Returns in one call: |
| 196 | - Run metadata (state, timing) |
| 197 | - All task instances with states |
| 198 | - Summary of failed tasks |
| 199 | - State counts (success, failed, skipped, etc.) |
| 200 | |
| 201 | ### Get Task Logs |
| 202 | |
| 203 | ```bash |
| 204 | af tasks logs <dag_id> <dag_run_id> <task_id> |
| 205 | ``` |
| 206 | |
| 207 | **Example:** |
| 208 | |
| 209 | ```bash |
| 210 | af tasks logs my_dag manual__2025-01-14T... extract_data |
| 211 | ``` |
| 212 | |
| 213 | **For |