Skip to content
Contributions/AI & data engineering

Open-source proof of concept · By César Zea

DAG-
Healer.

An API changes.
The pipeline recovers.

I built DAG-Healer to explore how AI can help investigate and resolve failures in data pipelines: gather the evidence, propose a repair, and apply it when the required checks pass.

A working example with Apache Airflow, Claude Code and a source API that changes without warning.

PythonApache AirflowClaude CodeMIT
The repair workflowApache Airflow · click to enlarge ↗
The reliability DAG in Airflow: wait for an incident, drain the queue, check whether a repair was applied, then trigger the import again.
The reliability DAG in Airflow: wait for an incident, drain the queue, check whether a repair was applied, then trigger the import again.
/ 01 — The engineering problem

Start with
the evidence.

An external API changes. An import fails. Someone has to read the logs, compare payloads, work out what changed and decide whether a correction is safe. Repeating that investigation costs engineering time.

DAG-Healer prepares a diagnosis and a proposed fix from the evidence captured at failure. For the limited failures it can verify, it also applies the correction and recovers the pipeline. Everything else is handed to a person with the evidence and an explanation.

The purpose is to explore where this can reduce operational work, and what controls are needed around the model’s judgment.

  1. 01 / Capture

    Keep the evidence.

    Broken contract rules, source fields, sample records and the last good run.

  2. 02 / Diagnose

    Propose a correction.

    Claude Code assesses the failure and whether the replacement field means the same thing.

  3. 03 / Verify

    Check before changing.

    Code enforces the policy, permitted actions and data checks against a trial import.

  4. 04 / Recover or escalate

    Leave a record.

    Apply a verified mapping and rerun, or refuse the change and explain why.

/ 02 — Inside Airflow

Fix the cause.
Then try again.

A retry usually repeats the same failure when the source schema has changed. In this Airflow capture, the mapping was repaired between attempts: try 1 failed, and try 2 succeeded after the mapping had been repaired.

The import and the repair are separate DAGs. The incident queue is their interface; the import does not call or trigger the repair workflow.

The import

orders_ingest

Fetches, maps, validates and loads. A contract failure stops the batch before loading and saves a structured incident.

The reliability layer

reliability_layer

Waits using a deferred sensor, releasing the worker while idle. It drains incidents, diagnoses and checks each proposal, then triggers the import again after a repair.

A successful second attemptApache Airflow · click to enlarge ↗
The import task in Airflow: try 1 failed; try 2 succeeded with mapping version 2 and returned 120 rows.
The import task in Airflow: try 1 failed; try 2 succeeded with mapping version 2 and returned 120 rows.
/ 03 — A recorded live run · 22 September 2026

A recorded demo.
Step by step.

The step-by-step walkthrough below shows the complete console output from running the demo script, scripts/demo.sh, with this command:

TerminalFrom the repository root
 ./scripts/demo.sh --no-pause

Open each phase to follow the script’s explanations and execution traces, or switch to Raw to read its original console output.

A simulated shop API replaces total_price with order_total. The amounts are unchanged. The reporting field, total_amount, must keep its original meaning.

This walkthrough calls the same Python functions used by the DAGs, without an Airflow scheduler. Phase 4 uses a live Claude Code call: Opus 5.5, maximum reasoning effort.

Read the complete execution trace
Orders recovered
120
Total before & after
27,895.24
Live model calls
1
Verification gates
5

Loading the complete original transcript…

Open original .txt ↗
/ 04 — How a proposal becomes a change

Five gates.
One permitted edit.

The repair may repoint the source of an existing reporting field. It cannot rewrite application code, add reporting fields or relax the data contract.

These checks run in ordinary Python. Any failed required check stops the repair and produces a record for a person to inspect.

  1. 01

    Policy

    Is this failure class eligible for automatic repair? Is the declared confidence above the configured minimum? In this run, a rename can be repaired and reviewed afterwards; a semantic change must be escalated.

  2. 02

    Allowed actions

    The proposal must use an explicit permitted action: remap_field, retry or escalate. Model confidence cannot authorize another operation.

  3. 03

    Structure

    The reporting field must already exist. The proposed source must occur in the API payload and must not already feed another reporting field.

  4. 04

    Content assessment

    A complete assessment must identify the proposed fields, include old and new examples, and judge their contents equivalent. This checks the assessment’s completeness; it does not independently prove the model’s judgment.

  5. 05

    Data evidence

    A trial import must satisfy the contract and the baseline comparison. Here, the replacement remains numeric, its mean must be within 25% of the reference, and its missing-value rate within 5 percentage points.

The checks, in the task logApache Airflow · click to enlarge ↗
Airflow records the call to Claude Code, the accepted mapping, its pending-review state and the results of the policy, action, structure, content and data checks.
Airflow records the call to Claude Code, the accepted mapping, its pending-review state and the results of the policy, action, structure, content and data checks.

This Airflow capture is a separate execution from the console walkthrough above. It shows the mapping change and every recorded check in the task log.

/ 05 — The last two demo phases

Test the refusal,
as well as the repair.

The demo deliberately supplies incorrect diagnoses in phases 7 and 8. These are controlled tests of the verification, not mistakes observed in the live model call.

They show why passing a data contract, or looking statistically similar, cannot establish that two fields mean the same thing.

Phase 07 / Wrong delivery-charge mapping

A plausible type.
An implausible amount.

The supplied proposal maps the order total to shipping_price, including a deliberately false equivalence claim. The values satisfy the contract, but the baseline catches the difference.

Healthy mean232.46Delivery charge6.94

Refused. The 97% difference exceeds the 25% tolerance. Mapping and loaded data remain unchanged; an escalation report explains the refusal.

Phase 08 / Subtotal on an isolated copy

A smaller difference.
A meaningful limit.

The fixture substitutes a subtotal worth 90% of the true amount. With a semantic_change diagnosis, policy refuses it. With a false rename classification and false equivalence claim, every implemented check passes.

Healthy mean232.46Subtotal209.21

Accepted by these checks. The 10% difference fits inside the tolerance. Incorrect amounts are loaded into the isolated copy, leaving the recovered pipeline untouched.

Two separate recorded live model checks of the subtotal case classified it as a semantic change and requested escalation. That is an encouraging observation, not an accuracy guarantee. Read the original responses ↗

/ 06 — Open source · MIT

Run it.
Inspect the evidence.

The repository includes the two DAGs, the fake shop API, policy and contract files, the guided demo, tests and design notes. You can inspect every applied or refused correction.

This is a local proof of concept covering a narrow set of cases. It has not been designed or validated for production pipelines; use the supplied demo data.

Run the guided demo

Python 3.13, Docker, and Claude Code 2.1.280 or later with access to Opus 5.5.

git clone https://github.com/cesarzea/dag-healer.git
cd dag-healer
make install
./scripts/demo.sh

The demo asks before starting the fake API in Docker and pauses between phases. Add --no-pause to run continuously. Without Docker, start the API with make api in another terminal.

Installation & commands on GitHub ↗

Inspect it in Airflow

To see the scheduler, task dependencies, incident sensor and logs in the UI:

docker compose up
# Open http://127.0.0.1:8080

The DAGs support Airflow 3.3.2 and 2.11. The automated tests cover the repair controls, refused actions and demo boundaries; passing them does not establish correctness for arbitrary pipelines.

View the test workflow ↗

What taking this further would involve

More failure classes with appropriate checks, durable incident delivery, coordination between workers, rolling baselines and a review step before repaired data reaches reporting. The practical questions are how much investigation time this saves, how much review it needs, and how often it accepts or refuses the wrong repair.

Read the design rationale ↗
From an experiment to your engineering context

Where could this help
your data team?

I use working examples like this to discuss where AI can reduce operational effort, what evidence would justify automation, and where human judgment should remain.

By César Pedro Zea Gómez · Based on the README and live demo recorded on 22 September 2026. The screenshots show separate Airflow executions.