authoring-go-sdk-tasks

작성자: astronomer

Writes Airflow task logic in Go using the Airflow Go SDK. Use when the user wants to implement Airflow tasks in Go, asks about `BundleProvider`/`RegisterDags`,…

npx skills add https://github.com/astronomer/agents --skill authoring-go-sdk-tasks

Authoring Go SDK Tasks

The Airflow Go SDK implements the language-SDK model for Go: your DAG stays in Python, and each task is a compiled Go function registered inside a bundle (a single native executable). This skill covers the Go-specific native API. The shared model (the Python @task.stub pattern, ID matching, the XCom-as-JSON contract) lives in authoring-language-sdk-tasks; read that first if you are new to language SDKs.

Experimental. The Go SDK is under active development and not production-ready. Module path github.com/apache/airflow/go-sdk (Go 1.24+). APIs may change.

Related skills: authoring-language-sdk-tasks (shared Python stub + concepts), deploying-go-sdk-bundles (build, pack, and ship the bundle), configuring-airflow-language-sdks (route the queue to the Go coordinator).


Recap: the Python side

A Go task is paired with a Python stub that carries no logic; it declares the task, its queue, and the dependency graph. IDs must match the Go registration exactly, and queue= routes the task to the Go runtime. Full rules are in authoring-language-sdk-tasks; the minimal shape:

from airflow.sdk import dag, task


@task.stub(queue="golang")
def extract(): ...


@task.stub(queue="golang")
def transform(): ...


@dag()
def simple_dag():
    extract() >> transform()


simple_dag()

The queue value ("golang" here) is an arbitrary label that must match the queue routed to the Go coordinator (queue_to_coordinator). See configuring-airflow-language-sdks.


The bundle entry point

A bundle implements bundlev1.BundleProvider: report its version and register your DAGs and tasks. main is one line; bundlev1server.Serve wires the bundle to the Airflow runtime for you.

package main

import (
	"log"

	v1 "github.com/apache/airflow/go-sdk/bundle/bundlev1"
	"github.com/apache/airflow/go-sdk/bundle/bundlev1/bundlev1server"
)

type myBundle struct{}

var _ v1.BundleProvider = (*myBundle)(nil)

func (m *myBundle) GetBundleVersion() v1.BundleInfo {
	return v1.BundleInfo{Name: bundleName, Version: &bundleVersion}
}

func (m *myBundle) RegisterDags(dagbag v1.Registry) error {
	simpleDag := dagbag.AddDag("simple_dag")      // dag_id must match the Python @dag name
	simpleDag.AddTask(extract)                    // task_id is the function name; must match the stub
	simpleDag.AddTaskWithName("transform", transform) // or set the task_id explicitly
	return nil
}

func main() {
	if err := bundlev1server.Serve(&myBundle{}); err != nil {
		log.Fatal(err)
	}
}

AddTask(fn) derives the task_id from the Go function's name; use AddTaskWithName("<task_id>", fn) when that name can't match the Python stub (an unexported, renamed, or reused function). RegisterDags is the single source of truth for task identity: the bundle's manifest (used by the packer and by the coordinator) is generated by running it, never hand-written.


Task functions: dependency injection by parameter type

A task is an ordinary Go function. The runtime inspects its signature and injects arguments by type; declare only what you need.

Parameter typeInjected value
context.ContextTask context for cancellation. Always available.
sdk.TIRunContextRicher context (embeds context.Context) exposing TaskInstance() and DagRun(). See Runtime context.
*slog.LoggerLogger wired to the Airflow task log.
sdk.ClientFull Airflow model access: Variables, Connections, XComs.
sdk.VariableClient / sdk.ConnectionClient / sdk.XComClientA narrower slice of sdk.Client. Prefer the narrowest you need; it documents intent and is trivial to fake in tests.

The optional return signature is (result, error): a non-nil result is pushed as the task's return_value XCom; a non-nil error fails the task (which triggers the stub's retry policy). Returning only error, or nothing, is also valid.

func extract(ctx sdk.TIRunContext, client sdk.Client, log *slog.Logger) (any, error) {
	conn, err := client.GetConnection(ctx, "test_http")
	if err != nil {
		return nil, err
	}
	log.Info("connected", "host", conn.Host)
	return map[string]any{"go_version": runtime.Version()}, nil
}

func transform(ctx sdk.TIRunContext, client sdk.VariableClient) error {
	val, err := client.GetVariable(ctx, "my_variable")
	if err != nil {
		return err // VariableNotFound (a sentinel error) if absent
	}
	_ = val
	return nil
}

The sdk.Client surface

CallReturnsNotes
GetVariable(ctx, key)(string, error)VariableNotFound if absent.
UnmarshalJSONVariable(ctx, key, &ptr)errorDecode a JSON variable into a struct/pointer.
GetConnection(ctx, connID)(Connection, error)ConnectionNotFound if absent.
GetXCom(ctx, dagID, runID, taskID, mapIndex, key, value)(any, error)XComNotFound only if the key is absent; a stored null returns (nil, nil).
PushXCom(ctx, ti, key, value)errorRarely needed; a returned value is pushed for you.

Connection exposes ID, Type, Host, Port (int), Login *string, Password *string (nil when unset, distinct from empty), Path (schema), Extra map[string]any, plus GetURI(). Not-found cases return the sentinels sdk.VariableNotFound, sdk.ConnectionNotFound, sdk.XComNotFound.

To read an upstream task's result, call GetXCom explicitly, taking the dag_id/run_id/task_id you need from the runtime context (below).


Runtime context

Declare an sdk.TIRunContext parameter to read metadata about the task instance and its DAG run. It is an interface that embeds context.Context, so it is usable anywhere a context.Context is expected.

func extract(ctx sdk.TIRunContext, log *slog.Logger) error {
	ti, dagRun := ctx.TaskInstance(), ctx.DagRun()
	log.Info("running",
		"task_id", ti.TaskID,
		"run_id", dagRun.RunID,
		"logical_date", dagRun.LogicalDate)
	return nil
}
  • TaskInstance(): DagID, RunID, TaskID, MapIndex *int (nil when unmapped), TryNumber.
  • DagRun(): DagID, RunID, and the *time.Time timestamps LogicalDate, DataIntervalStart, DataIntervalEnd (nil when not sent).

The accessors are populated from the task's startup details before the body runs. Because TIRunContext embeds context.Context, pass it straight to client calls and cancellation checks (ctx.Done()); declare it as your context parameter by default. In tests, build the argument with sdk.NewTIRunContext(ctx, ti, dagRun) (it panics on a nil ctx).


Go-specific pitfalls

  • IDs must match the Python stub (dag_id from AddDag, task_id from the registered function name), and the stub's queue= must route to the Go coordinator, or the task is never delivered.
  • RegisterDags is authoritative. Do not hand-write the manifest; the packer generates it by running RegisterDags.
  • Ask for the narrowest client interface you need (sdk.VariableClient over sdk.Client) for clearer intent and easier fakes.
  • A non-nil error return fails the task and applies the stub's retries; a recovered panic is also a failure.
  • See authoring-language-sdk-tasks for the language-agnostic pitfalls (one process per task instance, set queue and retries on the stub).

Related Skills

  • authoring-language-sdk-tasks: Shared Python-stub pattern and concepts (read first).
  • deploying-go-sdk-bundles: Build and pack the bundle with go tool airflow-go-pack, then deploy it for the coordinator.
  • configuring-airflow-language-sdks: Route the queue to the Go coordinator (ExecutableCoordinator).
  • authoring-dags: General Airflow DAG authoring.

astronomer의 다른 스킬

airflow
astronomer
Apache Airflow DAG, 실행, 작업 및 시스템 구성을 쿼리, 관리 및 문제 해결합니다. DAG 검사, 실행 관리, 작업 로깅, 구성 쿼리 및 직접 REST API 액세스에 걸쳐 30개 이상의 명령을 지원합니다. 지속적인 구성으로 여러 Airflow 인스턴스를 관리하고 로컬 및 Astro 배포를 자동으로 검색합니다. DAG 실행을 동기식(완료 대기) 또는 비동기식으로 트리거하고, 실패를 진단하고, 재시도를 위해 실행을 지우고, 재시도/맵 인덱스 필터링을 통해 작업 로그에 액세스합니다. 출력...
official
airflow-hitl
astronomer
인간 승인 게이트, 폼 입력, 그리고 지연 가능 연산자를 사용한 Airflow DAG 내 분기 처리. 네 가지 연산자 유형: 승인/거부 결정을 위한 ApprovalOperator, 폼을 통한 다중 옵션 선택을 위한 HITLOperator, 인간 주도 작업 라우팅을 위한 HITLBranchOperator, 폼 데이터 수집을 위한 HITLEntryOperator. 모든 연산자는 지연 가능하며, Airflow UI의 Required Actions 탭 또는 REST API를 통해 인간 응답을 기다리는 동안 작업자 슬롯을 해제합니다. 선택적 기능 지원 포함: 사용자 정의...
official
airflow-state-store
astronomer
Persists task and asset state across retries and DAG runs using Airflow 3.3's AIP-103 key/value stores (`task_state_store`, `asset_state_store`) and the…
official
analyzing-data
astronomer
데이터 웨어하우스에 질의하여 캐시된 패턴과 개념 매핑을 통해 비즈니스 질문에 답변합니다. 반복되는 질문 유형에 대한 패턴 조회 및 캐싱을 지원하며, 결과 기록을 통해 향후 질의를 개선합니다. 개념-테이블 매핑 캐시와 INFORMATION_SCHEMA 또는 코드베이스 grep을 통한 테이블 스키마 탐색을 포함합니다. 분석을 위해 Polars 또는 Pandas DataFrame을 반환하는 run_sql() 및 run_sql_pandas() 커널 함수를 제공합니다. 개념, 패턴 및 테이블 캐시를 관리하기 위한 CLI 명령어와 추가 기능을 포함합니다.
official
annotating-task-lineage
astronomer
Airflow 태스크에 인렛과 아웃렛을 사용하여 데이터 계보를 주석 처리합니다. 입력 및 출력을 데이터베이스, 데이터 웨어하우스, 클라우드 스토리지 전반에 걸쳐 정의하기 위해 OpenLineage Dataset 객체, Airflow Assets 및 Airflow Datasets를 지원합니다. 운영자에 내장된 OpenLineage 추출기가 없는 경우 대체 수단으로 사용되며, 사용자 정의 추출기와 OpenLineage 메서드가 우선 적용되는 4단계 우선순위 시스템을 따릅니다. Snowflake, BigQuery, S3 및 PostgreSQL에 대한 일관된 명명을 보장하는 데이터셋 명명 헬퍼를 포함합니다.
official
authoring-dags
astronomer
Apache Airflow DAG 생성을 위한 안내 워크플로우로, 검증 및 테스트 통합을 포함합니다. 구조화된 6단계 접근 방식: 환경 및 기존 패턴 발견, DAG 구조 계획, 모범 사례에 따른 구현, af CLI 명령어로 검증, 사용자 동의 하에 테스트, 수정 반복. 발견을 위한 CLI 명령어(af config connections, af config providers, af dags list)와 검증을 위한 명령어(af dags errors, af dags get, af dags explore)는 DAG에 대한 즉각적인 피드백을 제공합니다...
official
authoring-java-sdk-tasks
astronomer
Airflow 작업 로직을 Java, Kotlin 또는 Airflow Java SDK를 사용하는 모든 JVM 언어로 작성합니다. 사용자가 Java/JVM에서 Airflow 작업을 구현하려 하거나, 요청할 때 사용합니다…
official
authoring-language-sdk-tasks
astronomer
Airflow 언어 SDK를 위한 언어 중립적 기반 — DAG는 Python으로 유지하면서 비Python 언어로 작업 로직을 구현합니다. 사용자가...
official