astronomer/agents/migrating-ai-sdk-to-common-ai
Claude Code and agent skill by astronomer/agents
- community
Checking that the SKILL.md file is still in the repository.
Migrates Airflow projects from airflow-ai-sdk to apache-airflow-providers-common-ai 0.4.0+. Use when replacing airflow-ai-sdk with the official Airflow AI provider - migrating LLM decorators (@task.llm, @task.agent, @task.llm_branch, @task.embed), switching from model strings/objects to connection-based LLM configuration, updating imports from airflow_ai_sdk to the new provider, or upgrading an existing common-ai 0.1.x setup to 0.4.x (multimodal prompts, toolsets, embedding operators); also when common-ai provider, AIP-99, a pydanticai connection or migrating away from airflow-ai-sdk come up.
Install
npx vskill@latest install astronomer/agents/migrating-ai-sdk-to-common-aiSKILL.md
Migrate airflow-ai-sdk to apache-airflow-providers-common-ai
This skill migrates Airflow projects from airflow-ai-sdk to apache-airflow-providers-common-ai (target 0.4.0+), the official Airflow AI provider built on PydanticAI. It also covers upgrading projects already on common-ai 0.1.x, since several capabilities (multimodal prompts, toolsets, embedding operators, structured-output XCom behavior) changed between 0.1.0 and 0.4.0.
CRITICAL: The new provider requires Airflow 3.0+ and (for 0.4.0) pydantic-ai-slim >= 1.71.0. The API surface has changed: LLM configuration moves from code (model strings/objects) to Airflow connections (pydanticaitype). There is no@task.embedin the new provider; embeddings move to the LlamaIndex integration or a plain@task(see Step 3).
Before starting
Use the Grep tool with the pattern below to inventory everything that needs to migrate:
From the results, capture:
- All files importing
airflow-ai-sdk/airflow_ai_sdk - Which decorators are in use:
@task.llm,@task.agent,@task.llm_branch,@task.embed - The model configuration pattern (string names like
"gpt-5", orOpenAIModel(...)objects) - Any
airflow_ai_sdk.BaseModelsubclasses used asoutput_type
Use this inventory to drive the steps below.
Step 1: Update requirements.txt
Remove:
Add:
Use the latest available 0.x version unless the user has pinned a specific one. Available extras (0.4.0): [openai], [anthropic], [google], [bedrock], [llamaindex], [langchain], [mcp], plus file-format extras ([pdf], [docx], [parquet], [avro]) for DocumentLoaderOperator and [sql]/[common-sql] for the SQL operators. There are no [groq]/[mistral] extras; for those providers install the matching pydantic-ai-slim extra yourself.
Add [llamaindex] if the project migrates @task.embed to the LlamaIndexEmbeddingOperator (recommended, see Step 3). In that case sentence-transformers and torch can usually be removed, which shrinks the image considerably. Keep them only if the project stays on local sentence-transformers embeddings via plain @task.
Step 2: Create PydanticAI connection
The new provider uses an Airflow connection instead of model strings or objects in code.
Connection type: pydanticai Default connection ID: pydanticai_default
Via environment variable (.env)
Model format
The model field uses provider:model format:
| Provider | Example model value | |
|---|---|---|
| OpenAI | openai:gpt-5 | |
| Anthropic | anthropic:claude-sonnet-4-20250514 | |
google:gemini-2.5-pro | ||
| Groq | groq:llama-3.3-70b-versatile | |
| Mistral | mistral:mistral-large-latest | |
| Bedrock | bedrock:us.anthropic.claude-sonnet-4-20250514-v1:0 |
Custom endpoints (Ollama, vLLM, Snowflake Cortex, etc.)
Set host to the base URL:
Use the openai: prefix for any OpenAI-compatible API, regardless of the actual provider.
Connection ID convention
The env var name determines the connection ID:
AIRFLOW_CONN_PYDANTICAI_DEFAULTcreatespydanticai_defaultAIRFLOW_CONN_PYDANTICAI_CORTEXcreatespydanticai_cortex
Model resolution priority
model_idparameter on the decorator/operator (highest)modelin connection's extra JSON (fallback)
Other connection types (0.4.0)
Besides pydanticai, the provider registers vendor-specific connection types: pydanticai-azure (Azure OpenAI: host = endpoint, extra api_version), pydanticai-bedrock (AWS credentials/region in extra), and pydanticai-vertex (GCP project/location in extra). The LlamaIndex and LangChain hooks read API key/host/extra from whatever connection ID they are given, so a single pydanticai_default connection can serve LLM calls and embeddings: one API key entry for the whole project.
Step 3: Migrate decorators
@task.llm
Parameter mapping:
| airflow-ai-sdk | common-ai provider | Notes | |
|---|---|---|---|
model="gpt-5" | llm_conn_id="pydanticai_default" | Model specified in connection | |
model=OpenAIModel(...) | llm_conn_id="pydanticai_default" | Model + endpoint in connection | |
system_prompt="..." | system_prompt="..." | Unchanged | |
output_type=MyModel | output_type=MyModel | Unchanged | |
result_type=MyModel | output_type=MyModel | result_type was already deprecated | |
| (not available) | model_id="openai:gpt-5" | Override connection's model | |
| (not available) | require_approval=True | Built-in HITL review | |
| (not available) | agent_params={...} | Extra kwargs for pydantic-ai Agent | |
| (not available) | serialize_output=True | Force dict shape for BaseModel output |
Multimodal prompts (0.4.0+): the translation function may return a Sequence[UserContent] instead of a string, e.g. for vision:
This matches the old airflow-ai-sdk vision pattern, so vision code migrates unchanged. Note: common-ai 0.1.x only accepted strings — if a project disabled vision to migrate to 0.1.0, re-enable it when bumping to 0.4.0. Non-string prompts are incompatible with require_approval=True / enable_hitl_review=True (both render the prompt as text).
Structured output via XCom (0.4.0 behavior change): with output_type=<BaseModel subclass>, the model instance flows through XCom on Airflow cores whose task SDK has SUPPORTS_OPERATOR_DESERIALIZATION_WALKER (attribute access downstream); on older cores (including Astro Runtime 3.2 task SDK 1.2.x) the provider automatically dumps to a dict (subscript access). Check which shape arrives at runtime before choosing attribute vs dict access downstream, or set serialize_output=True to force the dict shape everywhere. The output_type class must be defined at module scope (nested classes cannot be deserialized from XCom).
@task.llm_branch
Only change: model= becomes llm_conn_id=.
@task.agent
This has the biggest API change. The Agent is no longer pre-built in user code.
Parameter mapping:
| airflow-ai-sdk | common-ai provider | Notes | |
|---|---|---|---|
agent=Agent(model, ...) | llm_conn_id="..." | Model from connection | |
Agent's system_prompt | system_prompt="..." | Now a decorator param | |
Agent's tools=[...] | toolsets=[FunctionToolset(tools=[...])] | Preferred: gets automatic tool-call logging | |
Agent's tools=[...] | agent_params={"tools": [...]} | Also works, but no tool-call logging | |
Agent's output_type | output_type=MyModel | Now a decorator param | |
| (not available) | durable=True | Step-level caching (needs [common.ai] durable_cache_path) | |
| (not available) | enable_hitl_review=True | Iterative human review loop (see below) |
Key insight: Everything that was configured on the Agent() constructor now goes into either a top-level decorator parameter or agent_params. The agent_params dict is passed directly to pydantic-ai's Agent constructor. Prefer toolsets over agent_params["tools"]: the operator wraps each toolset in a LoggingToolset, so every tool call appears in the task log with timing.
enable_hitl_review behavior: the task generates a first draft, then blocks until a human acts. The reviewer uses the HITL Review tab/extra link on the task instance (chat UI from the provider's auto-registered hitl_review plugin) to request changes (agent regenerates with the feedback in its message history) or approve. Constraints: requires a string prompt, incompatible with durable=True, and the final (possibly regenerated) output is what flows to XCom. Warn users that the Dag run waits indefinitely at this task unless hitl_timeout is set. For headless testing, the plugin exposes REST endpoints under /hitl-review: GET /sessions/find, POST /sessions/feedback, POST /sessions/approve, POST /sessions/reject (query params dag_id, task_id, run_id, map_index).
@task.embed (NO EQUIVALENT — three replacement options)
The new provider does NOT include an embed decorator. Pick the replacement based on what the project needs:
Option A (recommended): `LlamaIndexEmbeddingOperator` (0.4.0, [llamaindex] extra). Connection-based, one task embeds the whole document list, and with persist_dir the resulting vector index is persisted for retrieval (pairs with LlamaIndexRetrievalOperator):
The operator returns {"chunks": [{"text", "metadata", "vector"}], ...}. Put a stable key into each document's metadata — it round-trips through chunking, so vectors can be mapped back to source records.
Option B: `LlamaIndexHook` for raw vectors (no operator, no persisted index). Shortest path when vectors go straight to a database:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/migrating-ai-sdk-to-common-ai/SKILL.md
Popularity
- Repository stars
- 412
- Repository forks
- 56
- 7-day trend score
- 30
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/astronomer/agents/migrating-ai-sdk-to-common-ai)