Agent Native

migrating-airflow-2-to-3

This skill guides agents through migrating Apache Airflow 2.x DAG code to Airflow 3.x, handling breaking changes in imports, operators, context variables, and…

by AstronomerOfficial publisher

Identity proven by GitHub's verified organisation badge (astronomer)

Agents
Claude Code
License
Apache-2.0 (permissive)
Pin
486ee63pinned Oct 9, 2026
Context cost
about 2,100 tokenswhen the skill loads
GitHub stars
451on astronomer/agents
Scripts
None found

What it does

“Guide for migrating Apache Airflow 2.x projects to Airflow 3.x. Use when the user mentions Airflow 3 migration, upgrade, compatibility issues, breaking changes, or wants to modernize their Airflow codebase. If you detect Airflow 2.x code that needs migration, prompt the user and ask if they want you to help upgrade. Always load this skill as the first step for any migration-related request.”
The author's description, from SKILL.md

Generated summary from the skill's own text

This skill guides agents through migrating Apache Airflow 2.x DAG code to Airflow 3.x, handling breaking changes in imports, operators, context variables, and metadata database access. It provides Ruff rule recommendations for automated fixes, manual search patterns for remaining issues, and code examples for replacing direct database access with the Airflow Python client or REST API. The skill emphasizes testing the upgrade path through Airflow 2.11 before jumping to 3.x and includes configuration, scheduling, and callback behavior changes.

When to use it

  • User mentions Airflow 3 migration, upgrade, or compatibility issues
  • Detecting Airflow 2.x code that needs modernization to 3.x
  • Addressing breaking changes in DAG imports, operators, or context usage
  • Refactoring direct metadata database access patterns

When not to

  • Upgrading from Airflow 1.x or other data pipeline frameworks
  • Airflow 3.x to 4.x or future major version migrations
  • Deploying or testing already-migrated Airflow 3.x DAGs

Install

These commands install from the publisher's repository and need no account.

skills CLI

npx skills add astronomer/agents --skill migrating-airflow-2-to-3

Installs from the repository's default branch, which may have changed since the commit we checked.

GitHub CLI 2.90 or later

gh skill install astronomer/agents migrating-airflow-2-to-3@486ee63d01f8126c52fbc92c36cd36ec31708dcd

Installs the commit we checked (486ee63).

Copy by hand

Download the folder at 486ee63 and put it in .claude/skills/migrating-airflow-2-to-3 for Claude Code and in .agents/skills/migrating-airflow-2-to-3 for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.

Skill folder on GitHub at 486ee63

Claude Code plugin

/plugin install astronomer-data-agents@claude-plugins-official

The publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.

Claude Code plugin

/plugin install data@claude-plugins-official

The publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.

Claude Code plugin

/plugin install data-engineering@claude-plugins-official

The publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.

Copy for your agent

A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.

Prompt

Install the agent skill "migrating-airflow-2-to-3" by Astronomer.

Source, pinned to commit 486ee63d01f8126c52fbc92c36cd36ec31708dcd:
https://github.com/astronomer/agents/tree/486ee63d01f8126c52fbc92c36cd36ec31708dcd/skills/migrating-airflow-2-to-3

1. Download that folder at exactly this commit. Do not use the default branch.
2. Copy every file unchanged, keeping the folder structure, into .claude/skills/migrating-airflow-2-to-3/ for Claude Code and .agents/skills/migrating-airflow-2-to-3/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist.
3. Do not edit the files, and do not run any script in the folder unless I ask you to.
4. When you are done, list the files you copied and where you put them.

Listing and checks: https://www.agentnative.dev/skills/astronomer/migrating-airflow-2-to-3

SKILL.md at the pin

---
name: migrating-airflow-2-to-3
description: Guide for migrating Apache Airflow 2.x projects to Airflow 3.x. Use when the user mentions Airflow 3 migration, upgrade, compatibility issues, breaking changes, or wants to modernize their Airflow codebase. If you detect Airflow 2.x code that needs migration, prompt the user and ask if they want you to help upgrade. Always load this skill as the first step for any migration-related request.
hooks:
  PostToolUse:
    - matcher: "Edit"
      hooks:
        - type: command
          command: "echo 'Consider running: ruff check --preview --select AIR .'"
---

# Airflow 2 to 3 Migration

This skill helps migrate **Airflow 2.x DAG code** to **Airflow 3.x**, focusing on code changes (imports, operators, hooks, context, API usage).

**Important**: Before migrating to Airflow 3, strongly recommend upgrading to Airflow 2.11 first, then to at least Airflow 3.0.11 (ideally directly to 3.1). Other upgrade paths would make rollbacks impossible. See: https://www.astronomer.io/docs/astro/airflow3/upgrade-af3#upgrade-your-airflow-2-deployment-to-airflow-3. Additionally, early 3.0 versions have many bugs - 3.1 provides a much better experience.

## Migration at a Glance

1. Run Ruff's Airflow migration rules to auto-fix detectable issues (AIR30/AIR301/AIR302/AIR31/AIR311/AIR312).
   - `ruff check --preview --select AIR --fix --unsafe-fixes .`
2. Scan for remaining issues using the manual search checklist in [reference/migration-checklist.md](reference/migration-checklist.md).
   - Focus on: direct metadata DB access, legacy imports, scheduling/context keys, XCom pickling, datasets-to-assets, REST API/auth, plugins, and file paths.
   - Hard behavior/config gotchas to explicitly review:
     - Cron scheduling semantics: consider `AIRFLOW__SCHEDULER__CREATE_CRON_DATA_INTERVAL=True` if you need Airflow 2-style cron data intervals.
     - `.airflowignore` syntax changed from regexp to glob; set `AIRFLOW__CORE__DAG_IGNORE_FILE_SYNTAX=regexp` if you must keep regexp behavior.
     - OAuth callback URLs add an `/auth/` prefix (e.g. `/auth/oauth-authorized/google`).
     - **Shared utility imports**: Bare imports like `import common` from `dags/common/` no longer work on Astro. Use fully qualified imports: `import dags.common`.
3. Plan changes per file and issue type:
   - Fix imports - update operators/hooks/providers - refactor metadata access to using the Airflow client instead of direct access - fix use of outdated context variables - fix scheduling logic.
4. Implement changes incrementally, re-running Ruff and code searches after each major change.
5. Explain changes to the user and caution them to test any updated logic such as refactored metadata, scheduling logic and use of the Airflow context.

---

## Architecture & Metadata DB Access

Airflow 3 changes how components talk to the metadata database:

- Workers no longer connect directly to the metadata DB.
- Task code runs via the **Task Execution API** exposed by the **API server**.
- The **DAG processor** runs as an independent process **separate from the scheduler**.
- The **Triggerer** uses the task execution mechanism via an **in-process API server**.

**Trigger implementation gotcha**: If a trigger calls hooks synchronously inside the asyncio event loop, it may fail or block. Prefer calling hooks via `sync_to_async(...)` (or otherwise ensure hook calls are async-safe).

**Key code impact**: Task code can still import ORM sessions/models, but **any attempt to use them to talk to the metadata DB will fail** with:

```text
RuntimeError: Direct database access via the ORM is not allowed in Airflow 3.x
```

### Patterns to search for

When scanning DAGs, custom operators, and `@task` functions, look for:

- Session helpers: `provide_session`, `create_session`, `@provide_session`
- Sessions from settings: `from airflow.settings import Session`
- Engine access: `from airflow.settings import engine`
- ORM usage with models: `session.query(DagModel)...`, `session.query(DagRun)...`

### Replacement: Airflow Python client

Preferred for rich metadata access patterns. Add to `requirements.txt`:

```text
apache-airflow-client==<your-airflow-runtime-version>
```

Example usage:

```python
import os
from airflow.sdk import BaseOperator
import airflow_client.client
from airflow_client.client.api.dag_api import DAGApi

_HOST = os.getenv("AIRFLOW__API__BASE_URL", "https://<your-org>.astronomer.run/<deployment>/")
_TOKEN = os.getenv("DEPLOYMENT_API_TOKEN")

class ListDagsOperator(BaseOperator):
    def execute(self, context):
        config = airflow_client.client.Configuration(host=_HOST, access_token=_TOKEN)
        with airflow_client.client.ApiClient(config) as api_client:
            dag_api = DAGApi(api_client)
            dags = dag_api.get_dags(limit=10)
            self.log.info("Found %d DAGs", len(dags.dags))
```

### Replacement: Direct REST API calls

For simple cases, call the REST API directly using `requests`:

```python
from airflow.sdk import task
import os
import requests

_HOST = os.getenv("AIRFLOW__API__BASE_URL", "https://<your-org>.astronomer.run/<deployment>/")
_TOKEN = os.getenv("DEPLOYMENT_API_TOKEN")

@task
def list_dags_via_api() -> None:
    response = requests.get(
        f"{_HOST}/api/v2/dags",
        headers={"Accept": "application/json", "Authorization": f"Bearer {_TOKEN}"},
        params={"limit": 10}
    )
    response.raise_for_status()
    print(response.json())
```

---

## Ruff Airflow Migration Rules

Use Ruff's Airflow rules to detect and fix many breaking changes automatically.

- **AIR30 / AIR301 / AIR302**: Removed code and imports in Airflow 3 - **must be fixed**.
- **AIR31 / AIR311 / AIR312**: Deprecated code and imports - still work but will be removed in future versions; **should be fixed**.

Commands to run (via `uv`) against the project root:

```bash
# Auto-fix all detectable Airflow issues (safe + unsafe)
ruff check --preview --select AIR --fix --unsafe-fixes .

# Check remaining Airflow issues without fixing
ruff check --preview --select AIR .
```

---

## Reference Files

For detailed code examples and migration patterns, see:

- **[reference/config-changes.md](reference/config-changes.md)** - `airflow.cfg` section moves, renames, and removals
- **[reference/migration-patterns.md](reference/migration-patterns.md)** - Code examples for imports, scheduling, XCom, Assets, DAG bundles, runtime behavior changes
- **[reference/removed-methods.md](reference/removed-methods.md)** - Removed model methods with SDK/API migration paths
- **[reference/migration-checklist.md](reference/migration-checklist.md)** - Search patterns and fixes for issues Ruff doesn't catch

---

## Quick Reference Tables

### Key Import Changes

| Airflow 2.x | Airflow 3 |
|-------------|-----------|
| `airflow.operators.dummy_operator.DummyOperator` | `airflow.providers.standard.operators.empty.EmptyOperator` |
| `airflow.operators.bash.BashOperator` | `airflow.providers.standard.operators.bash.BashOperator` |
| `airflow.operators.python.PythonOperator` | `airflow.providers.standard.operators.python.PythonOperator` |
| `airflow.decorators.dag` | `airflow.sdk.dag` |
| `airflow.decorators.task` | `airflow.sdk.task` |
| `airflow.datasets.Dataset` | `airflow.sdk.Asset` |

### Context Key Changes

| Removed Key | Replacement |
|-------------|-------------|
| `execution_date` | `context["dag_run"].logical_date` |
| `tomorrow_ds` / `yesterday_ds` | Use `ds` with date math: `macros.ds_add(ds, 1)` / `macros.ds_add(ds, -1)` |
| `prev_ds` / `next_ds` | `prev_start_date_success` or timetable API |
| `triggering_dataset_events` | `triggering_asset_events` |
| `templates_dict` | `context["params"]` |

**Asset-triggered runs**: `logical_date` may be `None`; use `context["dag_run"].logical_date` defensively.

**Cannot trigger with future `logical_date`**: Use `logical_date=None` and rely on `run_id` instead.

Cron note: for scheduled runs using cron, `logical_date` semantics differ under `CronTriggerTimetable` (aligning `logical_date` with `run_after`). If you need Airflow 2-style cron data intervals, consider `AIRFLOW__SCHEDULER__CREATE_CRON_DATA_INTERVAL=True`.

### Default Behavior Changes

| Setting | Airflow 2 Default | Airflow 3 Default |
|---------|-------------------|-------------------|
| `schedule` | `timedelta(days=1)` | `None` |
| `catchup` | `True` | `False` |

### Callback Behavior Changes

- `on_success_callback` no longer runs on skip; use `on_skipped_callback` if needed.
- `@teardown` with `TriggerRule.ALWAYS` not allowed; teardowns now execute even if DAG run terminated early.

---

## Resources

- [Astronomer Airflow 3 Upgrade Guide](https://www.astronomer.io/docs/astro/airflow3/upgrade-af3)
- [Airflow 3 Release Notes](https://airflow.apache.org/docs/apache-airflow/stable/release_notes.html)
- [Ruff Airflow Rules](https://docs.astral.sh/ruff/rules/#airflow-air)

---

## Related Skills

- **testing-dags**: For testing DAGs after migration
- **debugging-dags**: For troubleshooting migration issues
- **deploying-airflow**: For deploying migrated DAGs to production

From astronomer/agents at 486ee63, shown as plain text under its license: Apache-2.0 (permissive). The license text is in LICENSE.

View SKILL.md on GitHub at 486ee63

Files

5 files, 38 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.

Skill folder on GitHub at 486ee63
All 33 skills from Astronomer

More from Astronomer

  • airflow

    This skill uses the `af` CLI to query, manage, and troubleshoot Apache Airflow instances.

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 3.6K tokens · pinned 7 days ago

  • airflow-adapter

    This skill provides an adapter layer that automatically detects whether an agent is connected to Airflow 2.x or 3.x and routes API calls to the correct…

    Claude Code · about 170 tokens · pinned 7 days ago

  • airflow-hitl

    Implements human-in-the-loop workflows in Airflow 3.1+ using deferrable operators that pause DAGs and collect human decisions via the UI or REST API.

    Claude Code, Codex, Cursor +4 · about 1.7K tokens · pinned 7 days ago

  • airflow-plugins

    Builds Airflow 3.1+ plugins that embed FastAPI apps, custom UI pages, React components, middleware, macros, and operator links directly into the Airflow UI…

    Claude Code, Codex, Cursor +4 · about 5.8K tokens · pinned 7 days ago

  • airflow-state-store

    Helps agents work with Airflow 3.3's task and asset state stores for persisting coordination state across task retries, implementing crash-safe external job…

    Claude Code, Codex, Cursor +4 · about 5.9K tokens · pinned 7 days ago

  • analyzing-data

    Queries a data warehouse using SQL to answer business questions about metrics, trends, and aggregations.

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 1.2K tokens · pinned 7 days ago

All Coding workflow skills
  • final-release-review

    Audits Python SDK release candidates or plans against the previous release, comparing diffs for regressions, API changes, and version compatibility.

    by OpenAIOfficial publisher

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 5.4K tokens · pinned 7 days ago

  • n8n-code-nodes-official

    This skill guides agents to use n8n Code nodes correctly as a last resort.

    by n8nOfficial publisher

    Claude Code, Codex, Cursor +4 · about 2.9K tokens · pinned 7 days ago

  • managing-python-dependencies

    This skill ensures the agent manages Python dependencies correctly by detecting the project's existing dependency manager and using the appropriate tool.

    by GoogleOfficial publisher

    Claude Code, Codex, Cursor +4 · about 740 tokens · pinned 7 days ago

  • run-experiment

    This skill sets up and executes Python-based experiments within a managed environment.

    by ImbueOfficial publisher

    Claude Code · about 910 tokens · pinned 7 days ago

  • practice-registry

    This skill checks Scala, Python, TypeScript, JavaScript, and Rust code against company-specific coding practices before generation, during editing, and before…

    by WriterOfficial publisher

    Claude Code, Codex, Cursor +4 · about 410 tokens · pinned 7 days ago

  • python-project

    Scaffolds production-grade Python projects with uv package management, pyproject.toml, src layout, Ruff linting, pytest testing, and optional CLI, API…

    by NebiusOfficial publisher

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 3.4K tokens · pinned 7 days ago

The skills listed here are third-party software, collected from public GitHub repositories as a catalog of recent skills and provided as is. Agent Native does not write or control them and is not responsible for any harm, loss or damage caused by installing or using them. Labels and checks describe what we saw at one commit and are not a guarantee. Read a skill's files before you run it. Terms of use