authoring-language-sdk-tasks
This skill teaches how to implement Airflow task logic in non-Python languages (Java, Go, etc.) while keeping the DAG and scheduling in Python.
Identity proven by GitHub's verified organisation badge (astronomer)
- Agents
- Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
- License
- Apache-2.0 (permissive)
- Pin
- 486ee63pinned Oct 9, 2026
- Context cost
- about 1,700 tokenswhen the skill loads
- GitHub stars
- 451on astronomer/agents
- Scripts
- None found
What it does
“The language-neutral foundation for Airflow language SDKs — implement task logic in a non-Python language while the DAG stays in Python. Use when the user wants to run an Airflow task in another language (Java, Kotlin, Go, or other JVM/native languages), asks how the Python `@task.stub` pairs with native task code, how task/DAG IDs must match across the two sides, how data passes via XCom as JSON, or which language SDKs exist. This skill owns the shared Python-stub pattern and conceptual model; for a specific language's native API, build, and runtime, use that language's skill (e.g. authoring-java-sdk-tasks, authoring-go-sdk-tasks).”
Generated summary from the skill's own text
This skill teaches how to implement Airflow task logic in non-Python languages (Java, Go, etc.) while keeping the DAG and scheduling in Python. It covers the shared model where Python stubs declare tasks and route them to language-specific coordinators, native code implements the logic, and data passes between them as JSON via XCom. Language-specific details like native APIs and type mappings are handled by companion skills.
When to use it
- User wants to run Airflow task logic in Java, Kotlin, Go, or other non-Python languages
- User asks how Python stub tasks pair with native code implementations
- User needs to understand task ID matching or data passing between Python and native sides
- User is learning the shared XCom-as-JSON contract across language boundaries
When not to
- User needs language-specific native API details, build tooling, or runtime setup for a particular language
- User is configuring queue-to-coordinator routing or Airflow-side language SDK setup
- User is deploying or packaging language SDK artifacts
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add astronomer/agents --skill authoring-language-sdk-tasksInstalls 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 authoring-language-sdk-tasks@486ee63d01f8126c52fbc92c36cd36ec31708dcdInstalls the commit we checked (486ee63).
Copy by hand
Download the folder at 486ee63 and put it in .claude/skills/authoring-language-sdk-tasks for Claude Code and in .agents/skills/authoring-language-sdk-tasks for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.
Claude Code plugin
/plugin install astronomer-data-agents@claude-plugins-officialThe 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-officialThe 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-officialThe 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 "authoring-language-sdk-tasks" by Astronomer. Source, pinned to commit 486ee63d01f8126c52fbc92c36cd36ec31708dcd: https://github.com/astronomer/agents/tree/486ee63d01f8126c52fbc92c36cd36ec31708dcd/skills/authoring-language-sdk-tasks 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/authoring-language-sdk-tasks/ for Claude Code and .agents/skills/authoring-language-sdk-tasks/ 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/authoring-language-sdk-tasks
SKILL.md at the pin
---
name: authoring-language-sdk-tasks
description: The language-neutral foundation for Airflow language SDKs — implement task logic in a non-Python language while the DAG stays in Python. Use when the user wants to run an Airflow task in another language (Java, Kotlin, Go, or other JVM/native languages), asks how the Python `@task.stub` pairs with native task code, how task/DAG IDs must match across the two sides, how data passes via XCom as JSON, or which language SDKs exist. This skill owns the shared Python-stub pattern and conceptual model; for a specific language's native API, build, and runtime, use that language's skill (e.g. authoring-java-sdk-tasks, authoring-go-sdk-tasks).
---
# Authoring Language SDK Tasks (Shared Foundation)
Airflow language SDKs let you implement task logic in a language other than Python while the DAG and its scheduling stay in Python. This skill describes the parts that are identical across every language SDK. Each language has its own companion skill for the native API, build tooling, and runtime — see [Per-language skills](#per-language-skills).
> **Experimental.** The language SDKs are in preview. APIs and artifact coordinates may change.
---
## The model
A DAG is authored in Python as usual. Tasks that should run in another language are declared as **stubs** routed to a dedicated queue. At runtime, Airflow hands a stub task to a **coordinator** that launches a short-lived **native subprocess** for that one task instance, runs your compiled/native code, and shuts the subprocess down.
Consequences that hold for every language SDK:
- **One subprocess per task instance** — there is no shared in-process state between task instances. Pass data via XCom or an external store.
- **The DAG, schedule, retries, and queue routing live in Python.** The native side only implements task logic.
- **Data crossing the boundary is JSON.** See [The XCom-as-JSON contract](#the-xcom-as-json-contract).
---
## The two-sided model
Every task has two halves that must agree:
1. A **Python stub** in a normal DAG file — no logic; it declares the task, its queue, the dependency graph, and retry policy.
2. A **native implementation** (Java, Go, etc.) whose IDs match the Python side and where the work happens.
### Python side (scheduling)
The example below uses the Go SDK to be concrete, but the Python side is **identical for every language SDK**. The queue name (`"golang"` here) is an arbitrary label you choose — it just has to match a key in `queue_to_coordinator` (see **configuring-airflow-language-sdks**). Pick whatever name fits the SDK you're routing to.
```python
from datetime import timedelta
from airflow.sdk import dag, task
@dag
def sales_pipeline():
@task.stub(queue="golang") # queue selects the coordinator (see configuring-airflow-language-sdks)
def extract(): ...
@task.stub(queue="golang")
def transform(extracted): ... # arg only declares the dependency
@task.stub(queue="golang", retries=1, retry_delay=timedelta(seconds=5))
def load(transformed): ...
@task() # an ordinary Python task can sit downstream
def report(loaded):
print(f"done: {loaded}")
report(load(transform(extract())))
sales_pipeline()
```
Rules that apply regardless of language:
- The **stub function name is the task ID** and the `@dag` name (or `dag_id=`) is the DAG ID. The native side must use these exact IDs.
- An upstream argument on a stub (e.g. `transform(extracted)`) exists **only to declare the dependency** in Python. The value itself is fetched on the native side via XCom — passing it in Python does not hand it to the native code.
- **Queue, retries, and other task arguments are set on the stub**, not in the native code. A native task that fails is reported back to Airflow, which then applies the stub's retry policy.
- The `queue` value is what routes the task to a coordinator; the same string must appear in `queue_to_coordinator` (see **configuring-airflow-language-sdks**).
---
## The XCom-as-JSON contract
XCom values are stored as JSON in Airflow's metadata database, so the boundary between Python and any native language is JSON. The Python/JSON side is the same for every SDK:
| Python type | JSON |
|-------------|------|
| `int` | number (integer) |
| `float` | number (decimal) |
| `str` | string |
| `bool` | boolean |
| `None` | null |
| `list` | array |
| `dict` | object |
Each language SDK maps these JSON types onto its own native types (e.g. a JSON integer becomes a Java `Long`). The native-type mapping lives in that language's skill. The key portability rule: a value pushed by one task is read by another **as JSON**, so the consuming side must expect a type compatible with what was stored.
---
## What is language-specific (and lives elsewhere)
This skill deliberately stops at the shared concepts. The following differ per language and are documented in each language's companion skills:
- **Native task API** — how you declare tasks, read connections/variables/XComs, and push results (annotations, interfaces, function registration, etc.).
- **Native type mapping** — the native column of the JSON table above.
- **Build and packaging** — how the artifact is compiled and bundled.
- **Runtime prerequisite** — what must be present on the worker (a language runtime for some SDKs, e.g. a JRE for the Java SDK; none for the Go SDK's self-contained bundles).
The Airflow-side wiring (which coordinator runs which queue) is shared in structure but has per-coordinator options; it lives in **configuring-airflow-language-sdks**.
---
## Language-agnostic pitfalls
- **IDs must match exactly** across the Python stub function name and the native task ID, and across `@dag`/`dag_id` and the native DAG ID. Mismatches surface as "no DAGs" or missing-XCom errors.
- **Both sides need the upstream reference.** Python declares the dependency by passing the upstream call; the native code retrieves the value via XCom.
- **Set queue and retries on the stub**, never in the native code.
- **Stub bodies must be empty.** An AST check enforces it — only `pass`, `...`, or a docstring is allowed in the body; any real logic is rejected.
- **`retry_policy` is rejected on stubs** (`@task.stub` raises `ValueError`). Use `retries`/`retry_delay` instead — a retry-policy callable runs Python in-process and would never fire for a task executing in a native subprocess.
- Assets, deferral, and some other Airflow features have limited or no support in the language SDKs today.
---
## Per-language skills
- **authoring-java-sdk-tasks**: Java/Kotlin/JVM native API, type mapping, and logging.
- **authoring-go-sdk-tasks**: Go native API — task registration, dependency injection by parameter type, and client access.
- *(Future language SDKs each add their own `authoring-<lang>-sdk-tasks` skill that builds on this one.)*
## Related Skills
- **configuring-airflow-language-sdks**: Route a queue to a coordinator and set runtime options.
- **authoring-dags**: General Airflow DAG authoring (the Python side lives here too).
- **deploying-java-sdk-bundles**: Build and ship the Java artifact.
- **deploying-go-sdk-bundles**: Build, pack, and ship the Go bundle (per-language deploy skills follow the same shape).
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 486ee63Files
- SKILL.md7.3 KB · a1cad5d190e5
1 file, 7.3 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.
Skill folder on GitHub at 486ee63More 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 6 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 6 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 6 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 6 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 6 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 6 days ago
Related in Backend and APIs
authoring-java-sdk-tasks
This skill teaches how to write Airflow task logic in Java, Kotlin, or other JVM languages using the Airflow Java SDK.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago
authoring-go-sdk-tasks
Enables writing Airflow task logic in Go by implementing the Go SDK's native API.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2K tokens · pinned 6 days ago
temporal-developer
This skill guides developers building Temporal applications across Python, TypeScript, Go, Java, .NET, Ruby, and Rust.
by TemporalOfficial publisher
Claude Code, Codex, Cursor +3 · about 1.7K tokens · pinned 6 days ago
speech-engine
This skill integrates ElevenLabs Speech Engine to add real-time voice conversations to custom agent runtimes.
by ElevenLabsOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago
databricks-apps-python
Enables agents to build Python backends for Databricks Apps using FastAPI, Flask, Dash, Streamlit, Gradio, or Reflex.
by DatabricksOfficial publisher
Contains scripts
Claude Code, Codex, Cursor +3 · about 2.9K tokens · pinned 6 days ago
queues
Vercel Queues enables agents to publish JSON messages to durable topics using @vercel/queue (JavaScript) or vercel-queue (Python), with consumer functions…
by VercelOfficial publisher
Claude Code, Codex, Cursor +3 · about 1.6K tokens · pinned 6 days ago