Creating DAGs with an AI Agent
Ask an AI client to write an Airflow DAG, check the code it produces, and publish the DAG to Airflow. Airflow MCP uses two steps, review and then upload, so AI-written code can't reach Airflow until you approve it.
About the review-and-upload process
Airflow MCP will not allow an AI client to write Airflow DAG code straight into Airflow. Publishing a DAG uses two tools:
| Step | Tool | What happens | Changes Airflow? |
|
reviewDagForUpload |
Saves the proposed DAG Python code to a temporary staging file on
the Data Access Gateway node. Returns a short-lived
reviewToken. |
No |
| 2. Upload | uploadDag |
Uses the reviewToken to upload the approved file
to Airflow's /dags/upload REST endpoint. |
Yes |
You approve the code and the file name between these two steps.
uploadDag is labeled destructive because it can
overwrite an existing DAG file with the same name.
Before you begin
- An administrator has turned on Airflow MCP, and your AI client is connected.
- You have permission to upload DAGs in Airflow.
- The DAG file is no larger than the upload limit. The default is 10 MB, set
by
mcp.airflow.dag-upload-max-size-bytes. - Your AI client asks for approval before it runs tools that change or delete data. Most clients do this by default for tools labeled destructive.
Creating and publishing an Airflow DAG
- Describe the DAG you want.
Include the schedule, tasks, dependencies, and any connections, variables or pools it should use. For example:
"Write an Airflow DAG named
daily_sales_etlthat runs every day at 02:00. It should run a Spark job, then a data quality check, and email the team if the check fails. Use the existingspark_defaultconnection." - Ask the client to stage the DAG for review.
The client calls
reviewDagForUploadwith the proposed code and file name. It gets back areviewToken. At this point, nothing has been sent to Airflow. - Check the code and file name.
Review the code the client shows you, and check:
- File name:make sure it is what you expect and won't
overwrite a DAG you want to keep. Use
listDagsorgetDagto see if a DAG with that name already exists. - Imports and operators: watch for
BashOperator,PythonOperatoror other operators that run shell commands or any Python code. - Connections, variables and pools: make sure they exist and are the correct ones.
- Schedule and catchup: check the schedule, the
start_date, and whethercatchupcould start a lot of backfill runs. run_as_user: check that it's not set, or set to a user who's allowed to start the DAG. If it doesn't match the user who starts the DAG through Airflow MCP, the run is rejected.- Secrets: make sure there are no passwords, tokens or keys written into the code.
- File name:make sure it is what you expect and won't
overwrite a DAG you want to keep. Use
- Approve or ask for changes.
- If you need changes, tell the client what to fix. It stages the new
version with
reviewDagForUploadand gets a newreviewToken. Check the new version before you approve it. - If the code is correct, approve the file name and the code.
- If you need changes, tell the client what to fix. It stages the new
version with
- Upload the DAG.
The client calls
uploadDagwith thereviewToken. When your client asks you to approve this tool call, check that the file name matches what you reviewed, then approve it. - Check that Airflow loaded the DAG.The Airflow DAG Processor has to read the new file before the DAG shows up, so it can take a short time to appear. Ask the client, for example:
-
"Is
daily_sales_etllisted now?" (listDagsorgetDag) -
"Are there import errors for
daily_sales_etl?" (listImportErrors) -
"Show me the source of
daily_sales_etl." (getDagSource) Compare it with the code you approved.
-
- Optional: run it for the first time
New DAGs may be paused, depending on your Airflow settings. Ask the client to unpause the DAG (
unpauseDag) or start a test run (triggerDagortriggerDagAndWait). If the run fails, ask the client to look into it withdiagnoseDagRun.
Example conversation
| You | The AI client |
"Write a DAG that copies yesterday's files from
/data/landing to
/data/archive every night at
01:00." |
Writes the DAG code and calls
reviewDagForUpload with the file name
nightly_archive.py. Shows you the code and
the file name. |
"Use the default_pool and set retries to
2." |
Changes the code, calls reviewDagForUpload
again, and shows you the new version. |
| "Looks good. Upload it." | Asks you to approve uploadDag, then calls it
with the reviewToken. |
| "Did it load?" | Calls listImportErrors and
getDag, and confirms the DAG is there and
paused. |
| "Unpause it and run it once now." | Calls unpauseDag, then
triggerDagAndWait, and reports the
result. |
What the client actually does depends on the client and the model.