Airflow Sketcher plugin and DAG factory for Excalidraw-based DAG authoring.
Project description
Airflow Sketcher
Airflow Sketcher is an Airflow 3.1+ plugin to build Airflow DAGs from Excelidraw drawings.
What is included
src/airflow_sketcher/dag_factory.py: Excalidraw to Airflow DAG parser/importer.src/airflow_sketcher/plugins/builder.py: Airflow plugin exposing the Excalidraw builder UI.src/airflow_sketcher/sitecustomize.py: optional startup hook for importer registration.examples/airflow/: thin wrapper files that can be mounted into an Airflowdags/andplugins/folder.tests/: unit tests and real.excalidrawfixtures.
Local development
With uv (recommended)
uv sync --all-extras
uv run python -m unittest discover -s tests
With traditional venv
python3 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
python3 -m unittest discover -s tests
Plugin functionality
The AirflowSketcherPlugin adds an Excalidraw-based DAG builder page to the Airflow UI under /airflow-sketcher.
Key capabilities:
- Renders an interactive Excalidraw canvas in Airflow for creating and editing DAG diagrams.
- Saves diagrams as
.excalidrawfiles in the AirflowDAGS_FOLDER. - Enforces safe filenames (letters, numbers,
.,_,-) and prevents path traversal. - Auto-appends the
.excalidrawextension when omitted. - Loads existing scenes and preserves selected visual app state (for example grid and viewport settings).
- Derives DAG metadata (such as
dag_idandschedule) fromdag:text blocks in the drawing. - Resolves a diagram for an existing DAG by checking DAG params (
excalidraw_source_file) first, then scanning.excalidrawfiles. - Registers the Excalidraw importer at startup so saved diagrams can be translated into Airflow DAG objects.
How to open the plugin
You can open the builder in two ways:
- Dedicated icon/view:
Open the Airflow top navigation entry named
Airflow Sketcher(with the plugin icon). This opens the builder home at/airflow-sketcher/. - From a DAG created by this plugin:
Open DAG details and click the
Builderexternal view. It opens/airflow-sketcher/?dag_id=<your_dag_id>and tries to load the corresponding.excalidrawsource file.
First DAG
Create a very simple DAG with two empty tasks in the builder UI:
- Open Airflow and navigate to
/airflow-sketcher. - Add one text element for DAG metadata with this content:
dag:
dag_id=first_two_tasks
schedule=@daily
- Draw two rectangles (each rectangle is a task).
- Add text inside the first rectangle:
task_a
- Add text inside the second rectangle:
task_b
- Draw an arrow from
task_atotask_b. - Save as
first_two_tasks.excalidraw.
Notes:
- You do not need to set
classfor this example. If omitted, tasks default toEmptyOperator. - If no
dag_idis provided in thedag:block, the file name (without extension) is used as the DAG ID.
Examples
1. The simplest DAG (two empty tasks)
Use these text blocks:
dag:
dag_id=1_simple_two_tasks
schedule=@daily
Task rectangle 1:
task_a
Task rectangle 2:
task_b
Then draw one arrow: task_a -> task_b.
In the Airflow UI, it should look like:
2. DAG with BashOperator and PythonOperator
Use these text blocks:
dag:
dag_id=2_bash_and_python
schedule=@daily
vars:
def greet(**kwargs):
print("hello from python task")
Task rectangle 1:
bash_task
class = operators.bash.BashOperator
bash_command = 'echo "hello from bash"'
Task rectangle 2:
python_task
class = operators.python.PythonOperator
python_callable = greet
Then draw one arrow: bash_task -> python_task.
In the Airflow UI, it should look like:
Example files
Ready-to-use .excalidraw files are available in examples/excalidraw/:
Supported sections and task attributes
The parser reads specific text blocks from the Excalidraw scene.
dag: section
Use a text element starting with dag: and put one key=value pair per line.
Supported keys:
dag_id: explicit DAG identifier.schedule: DAG schedule string (for example@dailyor cron expression).
If dag_id is omitted, the importer uses the .excalidraw filename (without extension). If schedule is omitted, it defaults to None.
Example:
dag:
dag_id=my_first_dag
schedule=@daily
imports: section
Use a text element starting with imports: to declare Python imports used by tasks.
- Only Python import statements are supported in this block.
import ...andfrom ... import ...are both supported.- Imported names are available when evaluating task attributes (for example
class,python_callable,op_args,op_kwargs). - You can use multiple
imports:blocks in the same diagram.
Default import behavior:
- No custom project modules are imported automatically. Add them in
imports:when needed. - Python builtins are available when evaluating attribute values.
- For the
classattribute only, theoperators.prefix is treated as shorthand forairflow.providers.standard.operators..- Example:
class = operators.bash.BashOperatorresolves toairflow.providers.standard.operators.bash.BashOperator.
- Example:
- If
classis omitted, the task defaults toairflow.providers.standard.operators.empty.EmptyOperator.
Example:
imports:
from airflow.providers.standard.operators.bash import BashOperator
import shared_funcs
vars: section
Use a text element starting with vars: to define Python variables/functions reused in task attributes.
- Contents are executed as Python code.
- Names defined here are available when evaluating task attributes (for example
python_callable=my_func).
Example:
vars:
def my_func(**kwargs):
print("hello")
Task text format (inside each rectangle)
Each task rectangle is configured by its associated text content.
Supported attributes:
- First non-empty line: task id (required), for example
task_a. class(optional): operator class path or imported symbol.- Default when omitted:
operators.empty.EmptyOperator.
- Default when omitted:
- Any other
key=valuelines are passed as operator keyword arguments.
Attribute values support:
- Python literals (strings, numbers, booleans, lists, dicts).
- Names imported or defined in
vars:. - Multi-line Python snippets. If a snippet is statements plus a final expression, that expression becomes the value. You can also assign to
resultand that value is used.
Example:
task_python
class = operators.python.PythonOperator
python_callable = my_func
op_kwargs = {"name": "world"}
Airflow integration
Install the package into your Airflow image or environment, then expose the thin wrapper files from examples/airflow/ inside the Airflow plugins/ and dags/ directories.
Installation
From PyPI:
pip install airflow-sketcher
From sources (editable/development mode):
# With uv
uv pip install -e .
# With pip
pip install -e .
Typical setup
- Install the package (see above).
- If you are not installing with
pip, copy the wholeairflow_sketcherpackage directory into Airflow'splugins/folder (for example asplugins/airflow_sketcher/). - Copy
examples/airflow/plugins/excalidraw_builder_plugin.pyinto Airflow'splugins/folder. - Copy
examples/airflow/plugins/sitecustomize.pyinto Airflow'splugins/folder if you want automatic importer registration at process startup. - Copy
examples/airflow/dags/airflow_dag_generator.pyinto Airflow'sdags/folder if you want a Python entrypoint that re-exports the factory symbols.
Testing strategy
The unit tests install lightweight Airflow stubs when Apache Airflow is not installed. That keeps parser and factory coverage runnable in a plain Python environment while still allowing the same package to run under real Airflow.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file airflow_sketcher-0.1.0.tar.gz.
File metadata
- Download URL: airflow_sketcher-0.1.0.tar.gz
- Upload date:
- Size: 20.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c70a988c675cbe4b933664005b15d7b394da20fd6add2da83bf7da04a8e428a7
|
|
| MD5 |
d93cfa81b737c66345ed5a5bc7336cab
|
|
| BLAKE2b-256 |
13de07d45bd8abd08cd8bec8634aa2bd724a977b2d9c119d2428722235a0f205
|
File details
Details for the file airflow_sketcher-0.1.0-py3-none-any.whl.
File metadata
- Download URL: airflow_sketcher-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8806c8dfad9c6be7251276c79c820e63c80ccf158dfa7d049cde0e6122d93cc
|
|
| MD5 |
d60b3edd5809f2f0661dea856dd71483
|
|
| BLAKE2b-256 |
62ab6c4e612116466b3c823507faeddd2ed171b1fcaca763282130713f9e234b
|