Skip to content
Back to skills

268 Prototype 8a3b2a13

ASecurity

You are helping a developer prototype a new Dagster implementation following best practices. The implementation requirements and working directory have been provided: $ARGUMENTS

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 31, 2026
businesspythongobashsqlnodetestinggitapidatabasedocumentation

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 268-prototype_8a3b2a13 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 268 Prototype 8a3b2a13?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 268 Prototype 8a3b2a13
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-268-prototype-8a3b2a13/badge)](https://www.skillsdirectory.com/skills/tools-only-268-prototype-8a3b2a13)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Prototype Dagster Implementation

You are helping a developer prototype a new Dagster implementation following best practices. The
implementation requirements and working directory have been provided: $ARGUMENTS

## Overview

This command guides you through building production-ready Dagster code with:

- Best practices from `dagster-conventions` skill
- Appropriate integrations from `dagster-integrations` skill
- Validation and testing at every step
- Components and Pythonic assets as appropriate

## Workflow

### Step 1: Understand Requirements & Plan

1. **Analyze the requirements** to determine:
   - What assets need to be created
   - What integrations are needed
   - Whether to use Components or Pythonic assets (or both)
   - Testing strategy

2. **Reference available integrations**:

   ```bash
   uv run dg docs integrations --json
   ```

   Also consult the `dagster-integrations` skill for finding appropriate integrations for the use
   case.

3. **Review current project structure**:
   ```bash
   uv run dg list defs
   uv run dg list components
   ```

### Step 2: Choose Implementation Approach

**Use Components when**:

- Implementing common patterns (dbt, Fivetran, Airbyte, dlt, Sling)
- Need declarative YAML configuration
- Want reusability across projects
- Building standardized data pipelines
- **For dbt**: Use remote Git repository configuration to avoid cloning projects locally

**Use Pythonic Assets when**:

- Custom business logic required
- Complex transformations
- One-off implementations
- Need fine-grained control

**Use Both**:

- Mix Components for standard patterns (e.g., dbt transformations)
- Use Pythonic assets for custom logic
- Merge definitions as shown in `dagster-conventions`

### Step 3: Implement with Best Practices

#### For Component-Based Implementation

1. **Scaffold the component** (if creating custom):

   ```bash
   uv run dg scaffold component ComponentName
   ```

2. **Create component definitions**:

   ```bash
   uv run dg scaffold defs my_module.components.ComponentName my_component
   ```

3. **Configure in YAML** (`defs/<component_name>.yaml`):
   - Set all required parameters
   - Reference environment variables appropriately
   - Configure component-specific settings
   - **For dbt components**: Prefer `repo_url` + `repo_relative_path` over `project_dir`

4. **Validate the component loads**:

   ```bash
   uv run dg check defs
   uv run dg list defs
   ```

5. **Modern Component Pattern with Dataclass** (for custom components):

When creating custom components, use the `@dataclass` decorator with `Resolvable` for automatic YAML
schema generation:

```python
from dataclasses import dataclass, field
import dagster as dg
from dagster.components import Component, ComponentLoadContext, Resolvable

@dataclass
class CustomETLComponent(Component, Resolvable):
    """Custom ETL component with auto-generated YAML schema.

    All dataclass fields automatically become YAML-configurable via Resolvable.
    """

    # Required fields (no defaults)
    source_table: str
    destination_table: str
    transformation_sql: str

    # Optional fields with defaults
    enable_logging: bool = True
    batch_size: int = 1000

    # Collections use field(default_factory=...)
    custom_tags: list[str] = field(default_factory=list)

    def build_defs(self, context: ComponentLoadContext) -> dg.Definitions:
        """Build asset definitions for this component."""

        @dg.asset(
            key=dg.AssetKey([self.destination_table]),
            kinds={"postgres", "python"},  # ALWAYS include kinds
            tags={tag: "true" for tag in self.custom_tags},
        )
        def etl_asset(context: dg.AssetExecutionContext):
            if self.enable_logging:
                context.log.info(f"Processing {self.source_table} → {self.destination_table}")

            # ETL implementation
            # 1. Query source table
            # 2. Apply transformation_sql
            # 3. Load to destination table
            pass

        return dg.Definitions(assets=[etl_asset])
```

**Corresponding YAML configuration:**

```yaml
# defs/my_etl/defs.yaml
type: my_project.components.CustomETLComponent

attributes:
  source_table: "raw_orders"
  destination_table: "processed_orders"
  transformation_sql: "SELECT * FROM raw_orders WHERE status = 'complete'"
  enable_logging: true
  batch_size: 5000
  custom_tags: ["finance", "daily"]
```

**Key benefits of the dataclass pattern:**

- Fields automatically generate YAML schema via `Resolvable`
- Type hints provide validation
- Default values make fields optional
- Use `field(default_factory=list)` for mutable defaults (lists, dicts)
- Most Dagster integration components use this pattern

#### For Pythonic Asset Implementation

1. **Scaffold asset file**:

   ```bash
   uv run dg scaffold defs dagster.asset assets/<domain_name>.py
   ```

2. **Implement assets following conventions**:
   - Use `@dg.asset` decorator with metadata (group_name, owners, tags, kinds)
   - Define clear dependencies via function parameters
   - Use `ConfigurableResource` for external services
   - Add type hints and docstrings
   - Keep assets focused and composable

3. **Example multi-asset chain** (realistic 3-5 asset pipeline):

   ```python
   import dagster as dg
   from my_project.resources import DatabaseResource, S3Resource
   import pandas as pd

   # Asset 1: Raw data ingestion
   @dg.asset(
       group_name="sales_analytics",
       owners=["team:data-engineering"],
       tags={"priority": "high", "domain": "sales", "schedule": "daily"},
       kinds={"s3", "python"},  # ALWAYS include kinds
       description="Raw customer orders extracted from operational database",
   )
   def raw_customer_orders(database: DatabaseResource) -> pd.DataFrame:
       """Extract raw customer orders from operational DB."""
       query = "SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '1 day'"
       return database.query(query)

   # Asset 2: Data cleaning/transformation
   @dg.asset(
       group_name="sales_analytics",
       owners=["team:data-engineering"],
       tags={"priority": "high", "domain": "sales", "schedule": "daily"},
       kinds={"python"},
       description="Cleaned orders with validation and deduplication",
   )
   def cleaned_orders(raw_customer_orders: pd.DataFrame) -> pd.DataFrame:
       """Clean and deduplicate order data."""
       # Remove duplicates
       df = raw_customer_orders.drop_duplicates(subset=["order_id"])

       # Validate required fields
       df = df.dropna(subset=["order_id", "customer_id", "amount"])

       # Standardize formats
       df["amount"] = df["amount"].astype(float)
       df["created_at"] = pd.to_datetime(df["created_at"])

       return df

   # Asset 3: Business logic/aggregation
   @dg.asset(
       group_name="sales_analytics",
       owners=["team:data-engineering"],
       tags={"priority": "high", "domain": "sales", "schedule": "daily"},
       kinds={"python"},
       description="Customer lifetime value aggregated by customer",
   )
   def customer_lifetime_value(cleaned_orders: pd.DataFrame) -> pd.DataFrame:
       """Calculate customer lifetime value metrics."""
       clv = cleaned_orders.groupby("customer_id").agg({
           "amount": "sum",
           "order_id": "count",
           "created_at": ["min", "max"]
       }).reset_index()

       clv.columns = ["customer_id", "total_revenue", "order_count", "first_order", "last_order"]
       clv["avg_order_value"] = clv["total_revenue"] / clv["order_count"]

       return clv

   # Asset 4: Enrichment with external data
   @dg.asset(
       group_name="sales_analytics",
       owners=["team:data-engineering"],
       tags={"priority": "high", "domain": "sales", "schedule": "daily"},
       kinds={"python", "snowflake"},
       description="CLV enriched with customer demographic data",
   )
   def enriched_customer_metrics(
       customer_lifetime_value: pd.DataFrame,
       database: DatabaseResource
   ) -> pd.DataFrame:
       """Enrich CLV metrics with customer demographic data."""
       # Join with customer demographics
       customers = database.query("SELECT customer_id, segment, region FROM customers")
       enriched = customer_lifetime_value.merge(customers, on="customer_id", how="left")

       return enriched

   # Asset 5: Output/export for downstream consumption
   @dg.asset(
       group_name="sales_analytics",
       owners=["team:data-engineering"],
       tags={"priority": "high", "domain": "sales", "schedule": "daily"},
       kinds={"s3", "python"},
       description="Customer metrics exported to S3 for BI tools",
   )
   def customer_metrics_export(
       enriched_customer_metrics: pd.DataFrame,
       s3: S3Resource
   ) -> None:
       """Export enriched metrics to S3 for Tableau/Looker consumption."""
       # Write to S3 as parquet
       s3.write_parquet(
           enriched_customer_metrics,
           bucket="analytics-exports",
           key="customer_metrics/latest.parquet"
       )
   ```

   **Key patterns demonstrated:**
   - **Clear asset chain**: raw → cleaned → aggregated → enriched → exported
   - **Always include `kinds`**: Helps with filtering and organization in Dagster UI
   - **Dependencies via parameters**: Each asset lists its dependencies as function parameters
   - **Descriptive names**: Nouns that describe the data output, not the action
   - **Consistent metadata**: Same group, owners, tags across related assets
   - **Type hints**: Specify return types for better IDE support and validation

4. **Create resources** (`resources.py`):

   ```python
   from dagster import ConfigurableResource, EnvVar

   class MyDatabaseResource(ConfigurableResource):
       connection_string: str = EnvVar("DATABASE_URL")

       def query(self, sql: str) -> list:
           # Implementation
           pass
   ```

5. **Register in definitions** (`definitions.py`):

   ```python
   from dagster import Definitions
   from dagster_dg import load_defs
   from my_project.defs.assets import customers, customer_metrics
   from my_project.defs.resources import MyDatabaseResource

   # Load component definitions
   component_defs = load_defs()

   # Define pythonic assets
   pythonic_defs = Definitions(
       assets=[customers, customer_metrics],
       resources={"database": MyDatabaseResource()},
   )

   # Merge together
   defs = Definitions.merge(component_defs, pythonic_defs)
   ```

## Critical: Design Asset Keys for Multi-Component Pipelines

When building multi-component pipelines (e.g., Fivetran → dbt → Hightouch), **asset keys must be
designed so downstream components can reference them naturally**. This eliminates the need for
per-asset configuration and makes your pipeline maintainable.

### Key Principle: Upstream Defines, Downstream Consumes

The upstream component should generate asset keys that downstream components naturally expect. This
"configure once, apply to all" approach prevents configuration burden downstream.

### Common Downstream Integration Patterns

#### If dbt will consume your assets:

Use **flat, 2-level keys** like `["source_name", "table"]`:

```python
# GOOD: Flat 2-level keys
["fivetran_raw", "customers"]  # dbt: source('fivetran_raw', 'customers')
["api_data", "orders"]          # dbt: source('api_data', 'orders')

# AVOID: Deeply nested keys
["fivetran", "raw", "production", "customers"]  # Requires extra dbt config
```

**Why flat keys?** dbt sources expect 2-level structure:

```yaml
# sources.yml - works naturally with flat keys
sources:
  - name: fivetran_raw
    tables:
      - name: customers # Matches ["fivetran_raw", "customers"]
      - name: orders # Matches ["fivetran_raw", "orders"]
```

#### If custom Dagster assets will consume:

Match the key structure those assets expect in their `deps`:

```python
# Upstream component creates:
["raw", "customers"]

# Downstream asset references naturally:
@dg.asset(deps=[dg.AssetKey(["raw", "customers"])])
def processed_customers(): ...
```

#### If reverse ETL tools (Census, Hightouch) will consume:

Use simple model names from dbt (typically single-level keys):

```python
# dbt creates from model file names:
["customer_lifetime_value"]
["monthly_revenue_by_region"]

# Reverse ETL tools reference by model name directly
```

### Asset Key Anti-Patterns

❌ **Too deeply nested:**

```python
["company", "team", "project", "environment", "schema", "table"]
# Hard for downstream to reference, requires complex mapping
```

❌ **Inconsistent structure:**

```python
["raw", "customers"]           # 2 levels
["processed", "finance", "revenue"]  # 3 levels
# Confusing for consumers, unpredictable references
```

❌ **Generic names:**

```python
["data", "table1"]
["output", "result"]
# Not clear what system they're from, conflicts likely
```

✅ **Good patterns:**

```python
["source_system", "entity"]    # ["fivetran_raw", "customers"]
["integration", "object"]      # ["salesforce", "accounts"]
["stage", "table"]             # ["staging", "orders"]
```

### Verifying Asset Key Alignment

After implementing your components, verify dependencies are correct:

```bash
# Check that asset keys and dependencies align
uv run dg list defs --json | uv run python -c "
import sys, json
data = json.load(sys.stdin)
assets = data.get('assets', [])
print('Asset Dependencies:\n')
for asset in assets:
    key = asset.get('key', 'unknown')
    deps = asset.get('deps', [])
    if deps:
        print(f'{key}')
        for dep in deps:
            print(f'  ← {dep}')
    else:
        print(f'{key} (no dependencies)')
    print()
"
```

**What to verify:**

- ✅ Downstream assets list upstream assets in their `deps` array
- ✅ No missing dependencies (especially dbt models depending on sources)
- ✅ Keys are simple and descriptive (typically 2 levels)
- ✅ No duplicate keys with different structures

**Common issues:**

- **dbt models not depending on sources**: SQL must use `{{ source('source_name', 'table') }}`
- **Nested keys don't match dbt expectations**: Consider flattening (see advanced pattern below)
- **Reverse ETL can't find models**: Use simple model names that match dbt output

### Advanced: Override get_asset_spec() for Key Transformation

When subclassing existing integration components (like Fivetran, Sling), you can override
`get_asset_spec()` to transform asset keys for better downstream compatibility.

**When to use this pattern:**

- Subclassing integration components that generate nested keys
- Need to flatten keys for dbt compatibility
- Want to apply consistent key structure across all assets from a component
- "Configure once, apply to all" - one override affects all generated assets

**Example: Flatten Fivetran keys for dbt**

Problem: Fivetran creates `["fivetran", "connector_id", "schema", "table"]` but dbt expects
`["fivetran_raw", "table"]`.

Solution:

```python
from dagster_fivetran import FivetranAccountComponent
from dagster_fivetran.translator import FivetranConnectorTableProps
import dagster as dg

class CustomFivetranComponent(FivetranAccountComponent):
    """Fivetran component with flattened asset keys for dbt compatibility."""

    def get_asset_spec(self, props: FivetranConnectorTableProps) -> dg.AssetSpec:
        """Override to flatten asset keys for easier dbt integration."""
        base_spec = super().get_asset_spec(props)
        original_key = base_spec.key.path

        # Flatten nested key: ["fivetran", "connector", "schema", "table"]
        # becomes: ["fivetran_raw", "table"]
        table_name = original_key[-1]  # Get the last element (table name)
        flattened_key = dg.AssetKey(["fivetran_raw", table_name])

        return base_spec.replace_attributes(key=flattened_key)
```

**Result:** dbt sources work naturally without extra configuration:

```yaml
# sources.yml - no meta.dagster needed!
sources:
  - name: fivetran_raw
    tables:
      - name: customers # Matches ["fivetran_raw", "customers"]
      - name: orders # Matches ["fivetran_raw", "orders"]
```

**When NOT to override:**

- Using component directly (not subclassing) → Can't override
- Default keys already work for your pipeline → Keep it simple
- Only one or two assets need different keys → Configure individually instead

**Other use cases:**

- **Sling**: Flatten `["sling", "replication_name", "stream"]` → `["raw", "stream"]`
- **Custom components**: Apply consistent prefixing or namespacing
- **Multi-environment**: Add environment suffix like `_staging` or `_prod`

### Step 4: Add Automation

Choose the appropriate automation pattern based on requirements:

#### Declarative Automation (Recommended)

```python
from dagster import AutomationCondition

@dg.asset(
    automation_condition=AutomationCondition.on_missing()
    | AutomationCondition.on_cron("0 9 * * *")
)
def automated_asset() -> None:
    pass
```

#### Traditional Schedules

```bash
uv run dg scaffold defs dagster.schedule schedules.py
```

```python
import dagster as dg

my_schedule = dg.ScheduleDefinition(
    job=my_job,
    cron_schedule="0 0 * * *",  # Daily at midnight
)
```

#### Asset Selection-Based Scheduling (Recommended for Scale)

For larger projects, use **asset selection syntax** instead of hardcoded asset keys. This makes
schedules maintainable as your project grows:

```python
from dataclasses import dataclass
import dagster as dg
from dagster.components import Component, ComponentLoadContext, Resolvable

@dataclass
class ScheduledJobComponent(Component, Resolvable):
    """Component for scheduling assets using flexible selection syntax."""

    job_name: str
    cron_schedule: str
    asset_selection: str  # Selection string using tags, groups, kinds, etc.

    def build_defs(self, context: ComponentLoadContext) -> dg.Definitions:
        """Build a scheduled job with flexible asset selection."""

        job = dg.define_asset_job(
            name=self.job_name,
            selection=self.asset_selection,
        )

        schedule = dg.ScheduleDefinition(
            job=job,
            cron_schedule=self.cron_schedule,
        )

        return dg.Definitions(schedules=[schedule], jobs=[job])
```

**YAML configuration examples:**

```yaml
# Daily finance job - selects by tags
type: my_project.components.ScheduledJobComponent
attributes:
  job_name: "daily_finance_job"
  cron_schedule: "0 6 * * *" # 6 AM UTC daily
  asset_selection: "tag:schedule=daily tag:domain=finance"

---
# Hourly critical operations - selects by priority
type: my_project.components.ScheduledJobComponent
attributes:
  job_name: "hourly_ops_job"
  cron_schedule: "0 * * * *" # Every hour
  asset_selection: "tag:priority=critical"

---
# Weekly analytics - selects by group
type: my_project.components.ScheduledJobComponent
attributes:
  job_name: "weekly_analytics_job"
  cron_schedule: "0 8 * * 1" # Monday 8 AM UTC
  asset_selection: "group:sales_analytics"

---
# All dbt models - selects by kind
type: my_project.components.ScheduledJobComponent
attributes:
  job_name: "dbt_refresh_job"
  cron_schedule: "0 4 * * *" # 4 AM UTC daily
  asset_selection: "kind:dbt"
```

**Asset selection patterns:**

- `tag:key=value` - Assets with specific tag
- `group:name` - Assets in a group
- `kind:type` - Assets of a kind (dbt, python, fivetran, etc.)
- `owner:email` - Assets owned by a team
- `*pattern*` - Key pattern matching
- Multiple conditions with spaces (AND) or `|` (OR)

**Benefits:**

- No hardcoded asset keys → easier maintenance
- Automatically includes new assets matching criteria
- Self-documenting: selection string shows what's scheduled
- Scales to hundreds of assets without config bloat

#### Sensors (Event-Driven)

```bash
uv run dg scaffold defs dagster.sensor sensors.py
```

### Step 5: Implement Testing

**Always include tests** following `dagster-conventions` testing patterns:

1. **Create test file** (`tests/test_<asset_name>.py`):

   ```python
   import dagster as dg
   from my_project.defs.assets import customers, customer_metrics
   from unittest.mock import Mock

   def test_customers_asset():
       """Test customers asset logic directly."""
       # Mock dependencies
       mock_database = Mock()
       mock_database.query.return_value = [{"id": 1, "name": "Test"}]

       # Test with dg.materialize
       result = dg.materialize(
           assets=[customers],
           resources={"database": mock_database},
       )

       assert result.success

   def test_customer_metrics_dependency():
       """Test customer_metrics depends on customers."""
       result = dg.materialize(
           assets=[customers, customer_metrics],
           resources={"database": Mock()},
       )

       assert result.success
       assert result.output_for_node("customer_metrics") is not None
   ```

2. **Add asset checks** for data quality:

   ```python
   @dg.asset_check(asset=customers)
   def customers_not_empty(customers):
       """Validate that customers table has data."""
       return dg.AssetCheckResult(
           passed=len(customers) > 0,
           metadata={"row_count": len(customers)},
       )
   ```

3. **Run tests**:
   ```bash
   pytest tests/
   ```

### Step 6: Validate Complete Implementation

Run comprehensive validation checks:

1. **Validate definitions load**:

   ```bash
   uv run dg check defs
   ```

2. **List all definitions** to verify assets are registered:

   ```bash
   uv run dg list defs
   ```

3. **Check components** (if using Components):

   ```bash
   uv run dg list components
   ```

4. **Test asset materialization** in dev mode:

   ```bash
   uv run dg launch --assets <asset_name>
   ```

5. **Run the test suite**:

   ```bash
   pytest tests/ -v
   ```

6. **Verify asset key alignment and dependencies**:

This is CRITICAL for multi-component pipelines. Verify that downstream assets properly depend on
upstream assets:

```bash
# Visualize asset dependencies
uv run dg list defs --json | uv run python -c "
import sys, json
data = json.load(sys.stdin)
assets = data.get('assets', [])
print('Asset Dependencies:\n')
for asset in assets:
    key = asset.get('key', 'unknown')
    deps = asset.get('deps', [])
    if deps:
        print(f'{key}')
        for dep in deps:
            print(f'  ← {dep}')
    else:
        print(f'{key} (no dependencies)')
    print()
"
```

**What to verify:**

- ✅ Downstream assets list upstream assets in their `deps` array
- ✅ No missing dependencies (especially dbt models depending on sources)
- ✅ Asset keys are simple and descriptive (typically 2 levels: `["category", "name"]`)
- ✅ No duplicate asset keys with different structures

**Common issues and fixes:**

| Issue                                   | Problem                                                                                     | Cause                                               | Fix                                                                   |
| --------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------------------------- |
| **dbt models missing dependencies**     | Staging models show no upstream deps                                                        | SQL doesn't use `{{ source('...') }}`               | Add source references in SQL                                          |
| **Asset keys don't match expectations** | Fivetran creates `["fivetran", "raw", "table"]` but dbt expects `["fivetran_raw", "table"]` | Default component keys too nested                   | Override `get_asset_spec()` to flatten (see Asset Key Design section) |
| **Reverse ETL missing deps**            | Hightouch/Census can't find dbt models                                                      | Use simple model names or configure deps explicitly |
| **Duplicate keys**                      | Multiple components creating same key                                                       | Check key generation logic, ensure unique prefixes  |

**If dependencies are missing**, refer back to the "Critical: Design Asset Keys for Multi-Component
Pipelines" section above for guidance on fixing key alignment.

### Step 7: Documentation & Next Steps

1. **Document the implementation**:
   - Add clear docstrings to all assets
   - Document any custom components
   - Note any environment variables required
   - Explain the data flow

2. **Recommend next steps**:
   - Deploy to staging environment
   - Set up monitoring and alerting
   - Configure production resources
   - Enable automation conditions or schedules

## Key Principles

Throughout implementation, follow these principles from `dagster-conventions`:

- **Think in Assets**: Focus on _what_ to produce, not _how_ to execute
- **Environment Separation**: Use `ConfigurableResource` and `EnvVar` for configuration
- **Testing First**: Write tests alongside assets
- **Clear Naming**: Use nouns for assets (`customers`, not `load_customers`)
- **Proper Dependencies**: Use function parameters for asset dependencies
- **Metadata Rich**: Add owners, tags, groups, kinds to assets
- **Avoid Over-Engineering**: Keep it simple, don't add unnecessary abstractions

## Reference Documentation

Always cross-reference these resources:

- **Dagster API Reference**: https://docs.dagster.io/llms.txt for titles and descriptions
- **Full API Details**: https://docs.dagster.io/llms-full.txt for complete API information
- **Component Creation**:
  https://docs.dagster.io/guides/build/components/creating-new-components/creating-and-registering-a-component
- **Component Customization**:
  https://docs.dagster.io/guides/build/components/creating-new-components/component-customization

## Example Complete Implementation

For reference, here's a complete example structure showing all patterns:

```
my_project/
├── src/
│   └── my_project/
│       ├── definitions.py                    # Merge components + pythonic definitions
│       ├── defs/
│       │   ├── assets/
│       │   │   ├── __init__.py
│       │   │   └── sales_analytics.py        # Pythonic multi-asset chain (Phase 5)
│       │   ├── resources.py                  # Custom ConfigurableResource classes
│       │   ├── my_etl/                       # Custom component instance
│       │   │   └── defs.yaml                 # YAML config with dataclass fields
│       │   ├── daily_finance_job/            # Scheduled job with asset selection
│       │   │   └── defs.yaml
│       │   └── weekly_analytics_job/
│       │       └── defs.yaml
│       └── components/
│           ├── __init__.py
│           ├── custom_etl_component.py       # @dataclass + Resolvable pattern (Phase 1)
│           └── scheduled_job_component.py    # Asset selection-based scheduling (Phase 6)
└── tests/
    ├── test_sales_analytics.py               # Test multi-asset chains
    ├── test_custom_etl.py                    # Test custom components
    └── test_resources.py                     # Test resource configurations
```

**Key patterns integrated:**

- **Dataclass components** with auto-generated YAML schema
- **Multi-asset chains** (raw → cleaned → aggregated → enriched)
- **Asset key design** for dbt/downstream integration
- **Scheduled jobs** using asset selection syntax
- **Merged definitions** combining components and pythonic assets

## Validation Checklist

Before considering the prototype complete, ensure:

**Core Functionality:**

- [ ] All definitions load successfully (`dg check defs`)
- [ ] Assets appear in `dg list defs` output
- [ ] Tests pass (`pytest tests/`)
- [ ] At least one asset can be materialized (`dg launch --assets <name>`)

**Asset Quality:**

- [ ] All assets include `kinds` parameter (e.g., `kinds={"python", "snowflake"}`)
- [ ] Assets have proper metadata (owners, tags, groups)
- [ ] Asset names are descriptive nouns (data outputs, not actions)
- [ ] Resources use environment variables appropriately (`EnvVar`)

**Multi-Component Integration** (if using multiple components):

- [ ] Asset keys designed for downstream integration (see "Asset Key Design" section)
- [ ] Dependencies verified with JSON command (Step 6, item 6)
- [ ] Downstream assets list upstream assets in their `deps` array
- [ ] Asset keys are flat 2-level structure when consumed by dbt
- [ ] No missing dependencies between components

**Components** (if using custom components):

- [ ] Dataclass pattern with `@dataclass` + `Resolvable` for YAML schema generation
- [ ] All asset examples include `kinds` parameter

**Automation** (if using):

- [ ] Schedules/jobs use asset selection syntax (not hardcoded keys) for scalability
- [ ] Selection patterns tested with `dg list assets --job <job_name>`

**Documentation:**

- [ ] Documentation is clear and complete
- [ ] Appropriate integrations from `dagster-integrations` are used
- [ ] Best practices from `dagster-conventions` are followed

## Related Skills and Resources

For more specialized patterns and workflows, consider these complementary resources:

**Reusable Skills:**

- **dagster-conventions** - Comprehensive Dagster development conventions and best practices
- **dagster-integrations** - Index of 82+ Dagster integrations across cloud platforms, data
  warehouses, ETL tools, AI/ML, and more

**Composition Patterns:** These skills can be combined with `/dg:prototype` for complete workflows:

- Initialize projects with proper structure
- Leverage existing integration components
- Create custom components with advanced patterns
- Implement flexible scheduling strategies

**Cross-References in This Guide:**

- For **asset key design**, see: "Critical: Design Asset Keys for Multi-Component Pipelines" section
- For **dependency verification**, see: Step 6, item 6 with JSON validation command
- For **dataclass components**, see: Step 3, item 5 "Modern Component Pattern with Dataclass"
- For **multi-asset chains**, see: Step 3, item 3 "Example multi-asset chain"
- For **scalable scheduling**, see: Step 4, "Asset Selection-Based Scheduling"

Files in this skill

  • README.md912 B
  • skill.md29.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.