DagSmith — a visual DAG editor for Apache Airflow 3

Writing DAGs in Airflow is practically Python — which is great for data engineers, but poses an entry barrier for analysts, less technical team members, or anyone who just wants to quickly assemble a simple pipeline without digging into code. At the same time, no visual tool should become another silo — if an editor generates code that cannot be normally maintained in Git, code reviews, and CI, it makes no sense.
DagSmith is a plugin for Apache Airflow ≥ 3.1 that adds a full DAG editor to the standard Airflow UI — a canvas with operator blocks alongside a code editor, based on the premise that code is the source of truth, and the canvas is merely its visual representation.
The Challenge
The main challenge in building such a tool is not drawing the dependency graph itself — that is a solved problem (React Flow). The difficulty lies elsewhere:
- How to edit existing, hand-written DAGs (using DAG(...), @dag, @task, >>, chain(), nested TaskGroups) without overwriting formatting and comments untouched by the editor?
- How to handle dynamic constructs (loops generating tasks, .partial().expand()) that inherently lack a single, static graphical representation?
- How to build an operator palette without manually cataloging hundreds of classes from Airflow providers, which constantly change between versions?
- How to allow UI editing without the risk of the scheduler seeing an unfinished, unvalidatable .py file while it is being worked on?
The Solution
Two-way synchronization via libcst
Instead of generating a .py file from scratch with every change on the canvas, DagSmith parses the existing code using libcst and applies minimal, surgical modifications. As a result, code segments untouched by the user on the canvas remain byte-for-byte identical — including comments and formatting. Editing in the other direction (in code) automatically updates the canvas. Dynamic constructs that cannot be safely represented graphically appear as "code-only" blocks instead of breaking the parser.
Auto-generated operator palette
Installed provider packages are introspected at runtime — DagSmith analyzes operators, sensors, and their `__init__` signatures across the entire class hierarchy. Consequently, hundreds of blocks with typed parameter forms appear in the palette without any manual definition, and the palette is always aligned with the actually installed version of the providers.
Drafts and controlled deployment
Work in progress does not immediately go to the DAG files. Changes are saved as versioned drafts in the Airflow metadata database (autosave, history, diffs, restoring to previous versions). Only clicking Deploy — after validation — writes the actual .py file, complete with backup and conflict detection. The scheduler never sees unfinished work.
Teamwork
Each team can have its own directory within the DAG bundle and its own Git repository: editing is restricted to team members, DAG reassignment by admins, tagging DAGs by teams, and a Commit & push button (GitHub/GitLab), with an optional push on every deploy.
Architecture
DagSmith is a plugin registered via the `airflow.plugins` entry point — nothing needs to be manually copied to the plugins directory. The frontend is a single UMD bundle (React Flow + CodeMirror), compliant with the react-plugin contract from AIP-68 — the host (Airflow) provides React, everything else is packaged in the bundle, with no loading from CDNs. The backend is a FastAPI application running inside the Airflow api-server, communicating with the frontend via REST (`/dagsmith/api/v1`), authorized with the same JWT as the rest of the Airflow UI.
Airflow UI ─▶ react_app "DagSmith" (React Flow canvas + CodeMirror)
│ REST /dagsmith/api/v1 (Airflow JWT)
▼
FastAPI app inside the api-server
│ parse (libcst) / codegen / validation (subprocess)
┌────────────┴────────────┐
Save / autosave Deploy (validated)
▼ ▼
Airflow metadata DB .py files in the DAG bundle
(draft versions, (atomic write, backup,
canvas layout) conflict detection, git)Existing code is handled on three levels: DAGs created in DagSmith feature full visual editing with a saved layout; typical, hand-written DAGs (DAG(...), @dag, @task, >>, chain(), nested TaskGroups, edge labels) are also fully editable visually without disrupting formatting; dynamic constructs (loops generating tasks, .expand()) are shown as read-only blocks on the canvas, editable in the code view.
Security
Deployment is disabled by default — without explicitly enabling it, DagSmith operates strictly in read-only and draft mode. All endpoints are authorized by the Airflow Auth Manager, user code is executed solely in an isolated, time-limited subprocess, every file path is restricted to the bundle directory, and every deployment is logged for auditing.
Deploying DAGs from the UI is equivalent to executing arbitrary code in the Airflow environment — exactly the same as uploading a DAG file through any other means. `deploy_enabled` is recommended to be enabled only after setting up appropriate access control in the Airflow UI.
Configuration
[dagsmith]
deploy_enabled = True
# optional role / team division:
# editors = data-platform-team # who can create and edit drafts
# deployers = admin # who can save .py files
# admins = admin # who manages teams
# git_commit = True # commit to bundle checkout on deployRequirements
| Component | Required version |
|---|---|
| Apache Airflow | ≥ 3.1 (react_apps + fastapi_apps API required, no support for Airflow 2.x) |
| Python | ≥ 3.10 |
| Metadata database | PostgreSQL recommended (custom dagsmith_* tables) |
| File access | api-server needs write access to the bundle directory only during deploy; working on drafts does not require file access |
Results (Deployment Potential)
DagSmith is an open-source tool developed independently of any specific client deployment, so the figures below are realistic estimates of the benefits derived from the tool's architecture, rather than measured production data.
- Reduced time required for less technical users to assemble a simple DAG — thanks to a ready-to-use operator palette and typed forms instead of writing Python from scratch.
- Zero risk of "breaking" manually maintained DAG code — raw editing via libcst instead of full file regeneration preserves formatting and comments.
- Fewer production incidents thanks to the draft → validation → deploy model, which prevents the scheduler from seeing an unfinished file.