Airflow compatibility
AutoAir supports Apache Airflow 3.0 or newer, below 4, on Python 3.10 to 3.14. Airflow 3.4 itself requires Python 3.11 or newer, so on Python 3.10 pip installs Airflow 3.3 at most; AutoAir keeps supporting Python 3.10 with Airflow 3.0 to 3.3. In plugin mode AutoAir runs inside Airflow's Python environment, so every extra has to resolve against the versions Airflow pins. Most extras install everywhere; two gaps come from Airflow itself.
Extras per Airflow version
| Extra | 3.0 | 3.1 | 3.2 | 3.3 | 3.4 (pre-release) |
|---|---|---|---|---|---|
all (see Extras) | yes | yes | yes | yes | yes |
mcp | yes | no | yes | yes | yes |
sqlite | yes (SQLAlchemy 1.4) | yes | yes | yes | yes |
postgres, kb-pgvector | yes (SQLAlchemy 1.4, psycopg2) | yes | yes | yes | yes |
ai, ai-* | yes | yes | yes | yes | yes |
otel, collab, collab-redis, standalone, format, shell, yaml, git | yes | yes | yes | yes | yes |
CI installs exactly these combinations: the Airflow 3.1 job runs without mcp and its MCP tests are skipped with the reason; every other job installs all,mcp,sqlite,postgres,kb-pgvector. The versions tested are 3.0.6, 3.1.8, 3.2.2, 3.3.2 and 3.4.0b2.
The required test jobs hold Airflow's core dependencies to the versions in Airflow's own constraints file for that release. scripts/airflow_constraints.py derives those pins: it keeps the pins of the packages apache-airflow-core and apache-airflow-task-sdk depend on directly, drops the ones that conflict with AutoAir's requirements together with the pins that depend on a dropped package, and lists both in the job summary. A separate, non-blocking job (nox -s "fresh(3.x)") installs without them, as a plain pip install does, and reports an upstream release that breaks Airflow or AutoAir.
The pins behind it
What apache-airflow-core requires, and what a fresh resolver picks today:
| Airflow | SQLAlchemy | FastAPI | Starlette (resolved) | Pydantic |
|---|---|---|---|---|
| 3.0.6 | >=1.4.49,<2.0 (1.4.54) | >=0.115 | 1.x | >=2.11 |
| 3.1.8 | >=1.4.54 (2.x) | >=0.116,<0.118 | <0.49 (0.48) | >=2.11 |
| 3.2.2 | >=2.0.48 | >=0.129 | >=1.0.1 | >=2.11 |
| 3.3.2 | >=2.0.50 | >=0.129,<0.137 | >=1.0.1 | >=2.11 |
| 3.4.0b2 | >=2.0.50,!=2.1.0 | >=0.129,<0.137 | >=1.3.1 | >=2.12 |
- MCP on Airflow 3.1. Every FastMCP 4 release requires Starlette 1.0.1 or newer. Airflow 3.1 caps FastAPI below 0.118, and those FastAPI releases cap Starlette below 0.49, so
autoair[mcp]cannot be resolved next to Airflow 3.1. Older FastMCP lines are not an option: FastMCP 3 and 2 are built on themcpSDK 1.x andhttpx(AutoAir usesmcp2.x andhttpx2), and the newest FastMCP 3 releases need Starlette 1.0.1 as well. - FastAPI on Airflow 3.2. Airflow 3.2 sets no upper bound on FastAPI, but its execution API does not build with FastAPI 0.156.1 or newer (
PydanticUserError: Model 'TITerminalStatePayload' needs a discriminator field): every task call fails, including AutoAir's DB-mode test runs. Airflow's 3.2 constraints file pins FastAPI 0.136. When you resolve Airflow 3.2 without that file, add"fastapi<0.137"(the cap Airflow 3.3 declares) to the install command. AutoAir itself needs onlyfastapi>=0.115and does not upgrade an installed FastAPI. - SQLAlchemy on Airflow 3.0. Airflow 3.0 keeps SQLAlchemy below 2.0. AutoAir's SQL state backends and the pgvector store use only APIs that SQLAlchemy 1.4 and 2.x share, so the
sqlite,postgresandkb-pgvectorextras accept SQLAlchemy 1.4.49 or newer and use whatever Airflow has installed.
Airflow 3.4
Airflow 3.4.0 is not final yet; CI tests the newest pre-release (3.4.0b2) in a job that may fail without blocking. What changes for AutoAir on 3.4:
| Change in Airflow 3.4 | What AutoAir does |
|---|---|
Plugin views can be scoped with applies_to | plugin.dag_tab_tags (for example ["autoair"]) shows the AutoAir tab only on DAGs with one of those tags. Empty (the default) keeps the tab on every DAG page, where a hand-written DAG can be imported. Before 3.4 the setting is ignored and logged. |
PUT /parseDagFile/{file_token} answers 403 for a file with no registered DAG unless the caller has the REPARSE_ALL view (admins by default) | A deploy to a local folder still succeeds when Airflow refuses the reparse request (verified against 3.4.0b2: 403 for a user without that view, also for a viewer on a registered DAG; a second request while one is queued gets 409, which AutoAir reports as "reparse already requested"). The deploy message names the refusal and says that Airflow picks the file up on its next bundle refresh, instead of reporting that Airflow could not be contacted. |
An up_for_retry task instance carries the upcoming try number; the failed try is try_number - 1 | The run panel's log view, the AI troubleshooter, the AI fix action and the MCP get_task_log tool open the failed try's log, not the upcoming try that has no log yet (retry_try_is_next in GET /api/airflow/capabilities). |
Task groups that depend on each other in a cycle are deprecated (TaskGroupCycleDeprecationWarning); Airflow 3.5 is planned to reject them | Validation reports a task_group_cycle warning on every Airflow version, naming the groups and tasks involved. |
| Python 3.10 support removed | See the first paragraph: Python 3.10 users stay on Airflow 3.3. |
ui_translations, also new in 3.4, overrides or adds strings of Airflow's own UI namespaces. Airflow shows plugin menu and tab names as they are configured, without a translation lookup, so it cannot translate the DAG Builder and AutoAir labels; set plugin.nav_name and plugin.dag_tab_name instead. AutoAir's own screens follow the language chosen in Airflow's UI.
MCP next to Airflow 3.1
Without autoair[mcp] the plugin keeps working; only MCP is off:
GET /autoair/api/metareportsmcp_enabled: falseandmcp_unavailable_reason, which names the Starlette conflict;- the admin panel's Features tab shows
mcpas not installed with the same reason, and it cannot be switched on; /autoair/mcp/is not mounted.
To give agents MCP anyway, run the MCP server from a separate environment or container that does not contain Airflow 3.1:
- Standalone MCP server. Install
autoair[standalone,mcp](plus the providers your DAGs use, or pointAUTOAIR_CATALOG_FILEat a catalog built withautoair catalog buildin the Airflow image) and runautoair mcp-serve --http --host 0.0.0.0 --port 8766withAUTOAIR_AIRFLOW_URLset to the Airflow API server. Clients authenticate with their Airflow token. See MCP. - Through the AI service. Run
autoair ai-servein its own environment withautoair[standalone,ai,mcp]and setAUTOAIR_AI__SERVICE__PROXY_MCP=trueon the plugin:/autoair/mcp/is then proxied to the service, the plugin needs no FastMCP, and clients keep the plugin URL.
Either way the MCP tools validate and generate code for the Airflow installed in the MCP server's own environment (the newest version AutoAir knows when none is installed), not for the 3.1 API server. A DAG that uses a feature newer than 3.1 is therefore not flagged by MCP validation; the plugin's validation flags it when the DAG is validated or deployed there, and Airflow 3.1 reports an import error for generated code that uses a symbol it lacks.
PostgreSQL on Airflow 3.0
SQLAlchemy 1.4 has no psycopg 3 dialect, so on Airflow 3.0 AutoAir drives PostgreSQL through psycopg2. A postgresql://, postgres:// or postgresql+psycopg:// URL in database.url, kb.pgvector.url or a kb.pgvector.conn_id connection is switched to postgresql+psycopg2:// automatically. psycopg2 comes with apache-airflow-providers-postgres, which an Airflow running on a PostgreSQL metadata database already has; otherwise install psycopg2-binary. Without a driver the error reads cannot load the postgresql driver (...): SQLAlchemy 1.4 (Airflow 3.0) drives PostgreSQL through psycopg2: pip install psycopg2-binary (or apache-airflow-providers-postgres).
On SQLAlchemy 2 (Airflow 3.1 and newer, and standalone installs) PostgreSQL uses psycopg 3 as before.
Airflow constraints files
Airflow's constraints files pin every package to the versions an Airflow release was tested with. They are meant for installing Airflow and do not leave room for AutoAir: the 3.0 to 3.2 files pin packages below AutoAir's core requirements (for example idna below what httpx2 needs), the 3.0 and 3.1 files pin OpenTelemetry 1.27 below the otel extra, the 3.2 file pins pydantic-ai-slim 1.x while ai needs 2.43 or newer, and the 3.3 file pins an openai SDK older than ai-openai needs. Install Airflow with its constraints file if you use one, then install AutoAir in a second pip install without --constraint, keeping apache-airflow==<version> on that command line so pip does not change Airflow.