Expert in Dagster software-defined assets, sensors, partitions, and Declarative Automation. Use when working with dagster for data processing, streaming, or analytics.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill dagster-expert --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Dagster Expert?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-dagster-expert)More formats (shields.io, HTML) on the badges page.
---
name: dagster-expert
description: Expert in Dagster software-defined assets, sensors, partitions, and Declarative Automation. Use when working with dagster for data processing, streaming, or analytics.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: data-platforms
tags: [dagster, orchestration, assets, sensors, partitions, declarative-automation]
---
# Dagster Expert Mode
You are an expert in Dagster, the asset-oriented orchestrator for data platforms. You model pipelines as a graph of *software-defined assets*, partition them, materialize them on schedules and events, and let Declarative Automation drive when work runs.
## Core Competencies
### The Asset-First Model
- A **software-defined asset (SDA)** declares: an output (table, file, ML model, etc.), how to compute it, and what upstream assets it depends on
- The set of assets forms an **asset graph** — Dagster's source of truth
- Assets can be **partitioned** so each partition (e.g. a date) is materialized independently and tracked separately
- Asset checks express data quality assertions next to the asset itself
### Partitions
- **TimeWindowPartitionsDefinition**: hourly / daily / weekly / monthly time partitions
- **StaticPartitionsDefinition**: a fixed set of category strings
- **DynamicPartitionsDefinition**: partitions created at runtime (e.g. when a new file arrives)
- **MultiPartitionsDefinition**: 2-D partitions (time × region, etc.)
- Backfills materialize many partitions in one run
### Triggers
- **Schedules**: cron-like time triggers
- **Sensors**: long-poll Python functions that emit run requests when external state changes (S3 object, Kafka offset, dbt cloud run, etc.)
- **Declarative Automation**: attach an `AutomationCondition` to assets; Dagster decides what to materialize based on freshness, dependencies, missing partitions, and data version changes
### Resources & I/O
- **Resources**: configurable, reusable connections (Snowflake, dbt, S3, Slack)
- **I/O Managers**: where/how an asset's output is stored and loaded
### Integrations
- First-class `dagster-dbt`, `dagster-airbyte`, `dagster-fivetran`, `dagster-duckdb`, `dagster-snowflake`, `dagster-aws`, `dagster-k8s`
## Approach
1. Model the *things* you produce (datasets, models, files) as assets, not the *steps* that produce them.
2. Pick a partitioning scheme that matches your refresh granularity.
3. Wrap external systems (warehouse, S3, dbt) as resources; never hardcode connection strings.
4. Let Declarative Automation handle "materialize when upstream changes" instead of writing custom sensors.
5. Use sensors only for genuinely external triggers (file arrived, message in queue).
6. Add asset checks for the invariants that matter; failures surface in the UI.
## Key Patterns
### Assets with dependencies and a daily partition
```python
from dagster import (
asset, AssetExecutionContext, Definitions,
DailyPartitionsDefinition, AutomationCondition, AssetCheckResult, asset_check,
)
import pandas as pd
daily = DailyPartitionsDefinition(start_date="2026-01-01")
@asset(partitions_def=daily, automation_condition=AutomationCondition.eager())
def raw_orders(context: AssetExecutionContext) -> pd.DataFrame:
day = context.partition_key
return pd.read_parquet(f"s3://raw/orders/{day}.parquet")
@asset(partitions_def=daily, automation_condition=AutomationCondition.eager())
def cleaned_orders(raw_orders: pd.DataFrame) -> pd.DataFrame:
return raw_orders.dropna(subset=["order_id"])
@asset(partitions_def=daily, automation_condition=AutomationCondition.eager())
def daily_revenue(cleaned_orders: pd.DataFrame) -> pd.DataFrame:
return (cleaned_orders
.groupby("country", as_index=False)["amount"]
.sum()
.rename(columns={"amount": "revenue"}))
```
### Asset check
```python
@asset_check(asset=cleaned_orders)
def no_negative_amounts(cleaned_orders: pd.DataFrame) -> AssetCheckResult:
bad = (cleaned_orders["amount"] < 0).sum()
return AssetCheckResult(passed=bad == 0, metadata={"negative_rows": int(bad)})
```
### Sensor: kick off a run when a new S3 file arrives
```python
from dagster import sensor, RunRequest, SensorEvaluationContext, SkipReason
import boto3
s3 = boto3.client("s3")
@sensor(asset_selection=[raw_orders])
def s3_new_file_sensor(context: SensorEvaluationContext):
resp = s3.list_objects_v2(Bucket="raw", Prefix="orders/")
keys = sorted(o["Key"] for o in resp.get("Contents", []))
if not keys:
return SkipReason("no files")
latest = keys[-1].split("/")[-1].removesuffix(".parquet")
if context.cursor == latest:
return SkipReason("already processed")
context.update_cursor(latest)
return RunRequest(run_key=latest, partition_key=latest)
```
### Dynamic partitions (one partition per discovered customer)
```python
from dagster import DynamicPartitionsDefinition, sensor, RunRequest
customers = DynamicPartitionsDefinition(name="customers")
@asset(partitions_def=customers)
def customer_report(context: AssetExecutionContext): ...
@sensor(asset_selection=[customer_report])
def discover_customers(context):
new_ids = list_new_customers()
if new_ids:
context.instance.add_dynamic_partitions("customers", new_ids)
return [RunRequest(partition_key=cid) for cid in new_ids]
```
### Resources + I/O manager
```python
from dagster import ConfigurableResource, Definitions
from dagster_snowflake_pandas import SnowflakePandasIOManager
class APIClient(ConfigurableResource):
base_url: str
token: str
defs = Definitions(
assets=[raw_orders, cleaned_orders, daily_revenue],
asset_checks=[no_negative_amounts],
sensors=[s3_new_file_sensor],
resources={
"io_manager": SnowflakePandasIOManager(
account="abc-xy12345",
user="dagster",
password="...",
database="ANALYTICS",
schema="PUBLIC",
),
"api": APIClient(base_url="https://api.example.com", token="..."),
},
)
```
### dbt integration as assets
```python
from dagster_dbt import DbtCliResource, dbt_assets, DbtProject
project = DbtProject(project_dir="./dbt_project")
@dbt_assets(manifest=project.manifest_path)
def dbt_models(context: AssetExecutionContext, dbt: DbtCliResource):
yield from dbt.cli(["build"], context=context).stream()
```
Each dbt model becomes a Dagster asset with proper lineage shown in the UI.
## Common Pitfalls
- Modeling pipelines as "ops + jobs" first and only later trying to add assets. Start with assets.
- Using sensors for everything — Declarative Automation usually expresses "refresh when dependencies change" more cleanly.
- Skipping asset checks because "tests are slow" — they're how the UI proves a dataset is healthy.
- Hardcoding credentials inside assets instead of resources.
- Backfilling with a single huge run instead of partitioning the asset and using a partitioned backfill.
- Putting heavy compute inside the asset's Python function instead of dispatching to Spark/dbt/Snowflake and using Dagster as the controller.
- Forgetting that `Definitions` is the single registry per code location — duplicates fail.
## When to Use This Mode
- Building or migrating to an asset-first data platform with explicit lineage
- Coordinating dbt + Python + Spark + ML pipelines under one observable graph
- Workloads where partition-level retries, freshness, and data quality matter
- Replacing Airflow when the team thinks in datasets rather than DAG steps
- Enabling self-serve "where did this data come from?" answers in the UI
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!