Skip to content

Workflow

Step 1 — Check contract syntax

akad check --contract contracts/sales.yaml
# OK  daily_sales v1.0.0 — contract is valid

Step 2 — Start the registry

docker compose up -d
  • Registry API: http://localhost:8000
  • Dashboard: http://localhost:8501

Step 3 — Publish the contract

akad publish --contract contracts/sales.yaml --registry-url http://localhost:8000
# Published daily_sales v1.0.0

Step 4 — Validate in your pipeline

From a local file (dev / CI):

from akad import DataContractValidator, DataContractBreachError

result = DataContractValidator(
    contract_path="contracts/sales.yaml",
    registry_url="http://localhost:8000",
).validate()

print(result.overall_status)    # COMPLIANT or BREACH
print(result.row_count)         # 48203

From the registry by name (Airflow workers — no local file needed):

result = DataContractValidator(
    contract_name="daily_sales",
    registry_url="http://akad-registry:8000",
).validate()

Step 5 — Use in Airflow

from airflow.sdk import dag, task
from akad import DataContractValidator
import os

REGISTRY_URL = os.environ.get("AKAD_REGISTRY_URL", "http://akad-registry:8000")

@dag(schedule="@daily", ...)
def sales_pipeline():

    @task
    def extract_and_load() -> int:
        # write dataset to /data/sales/daily.parquet
        ...

    @task
    def validate(row_count: int) -> str:
        result = DataContractValidator(
            contract_name="daily_sales",   # fetched from registry — no local file
            registry_url=REGISTRY_URL,
            notifiers=[],
        ).validate()

        if result.is_breach:
            raise ValueError(f"Contract breach — pipeline halted")

        return result.overall_status.value

    @task
    def transform(status: str) -> None:
        ...  # only runs when validation passes

    rows = extract_and_load()
    status = validate(rows)
    transform(status)

On breach: validate raises → Airflow marks it FAILED → transform is skipped — bad data never reaches downstream consumers.