Skip to main content

selfheal-sdk

AI self-healing decorator for any Python data pipeline.

When your pipeline raises an exception, @healed classifies the failure, applies a fix automatically, and escalates to humans only when genuinely needed.

Built by Sahil Deol


Install

pip install selfheal-sdk

With AI backends (recommended):

pip install selfheal-sdk[typesafe]   # TypeSafe JEV — best classification
pip install selfheal-sdk[anthropic]  # Claude Haiku fallback
pip install selfheal-sdk[ollama]     # Ollama local LLM fallback (needs openai pkg for compat API)
pip install selfheal-sdk[all]        # everything

No extras? Zero-dep keyword fallback always works out of the box.


Quickstart

from selfheal import healed

@healed(pipeline="daily_sales_etl")
def run():
    records = extract()
    validate(records)        # raises? selfheal catches and heals it
    cleaned = transform(records)
    load(cleaned)

if __name__ == "__main__":
    run()

That's the only change needed.


How it works

When run() raises, @healed does this:

  1. Classify — sends the error + traceback to TypeSafe JEV (or fallback LLM). Returns failure_type, action, confidence, severity.
  2. Threshold check — auto-heals only when confidence ≥ 0.65 AND severity ≤ 3.
  3. Act:
Failure type Action Auto? Hook needed
BAD_DATA QUARANTINE ✅ run_quarantine()
TRANSIENT RETRY ✅ none
SCHEMA_DRIFT (new col) ADD_COLUMN ✅ add_columns_to_dest()
PERMISSION / CODE_DEFECT ESCALATE ❌ human approval
High severity (≥4) ESCALATE ❌ human approval
  1. Report — best-effort POST to your dashboard if configured. Never blocks the pipeline.

API keys

The healer tries backends in order: TypeSafe JEV → Anthropic → Ollama (local) → keyword fallback.

export TYPESAFE_API_KEY=ts-...       # TypeSafe JEV (recommended)
export ANTHROPIC_API_KEY=sk-ant-...  # Claude Haiku fallback
# Ollama runs locally — no API key needed. Start with: ollama serve

Keyword fallback requires no API key and always works.


Decorator options

@healed(
    pipeline="my_etl",                    # name in logs
    server_url="http://localhost:8000",   # optional dashboard URL
    on_escalate=None,                     # sync callback(result) on ESCALATE
    max_retries=1,                        # retry attempts before giving up
    silent=False,                         # suppress INFO logs
    retry_safe=False,                     # set True if pipeline is idempotent
    retry_backoff_base=1.0,               # backoff base seconds (exponential)
    retry_jitter=0.25,                    # random jitter added to each backoff
    send_source_code=True,                # set False if code contains secrets
    source_redactor=None,                 # optional fn(src) → redacted_src
)
def run():
    ...

Recovery hooks

Define these in the same module as your decorated function. selfheal calls them automatically.

BAD_DATA → run_quarantine()

@healed(pipeline="daily_sales_etl")
def run():
    records = extract()
    validate(records)
    load(transform(records))

def run_quarantine():
    records = extract()
    clean = [r for r in records if r.get("customer_id") and r.get("amount", 0) > 0]
    bad   = [r for r in records if r not in clean]
    log_bad_rows(bad)
    load(transform(clean))

SCHEMA_DRIFT → add_columns_to_dest(cols, schema)

def add_columns_to_dest(extra_cols: list[str], actual_schema: dict) -> None:
    with connect() as conn:
        for col in extra_cols:
            conn.execute(f"ALTER TABLE dest ADD COLUMN IF NOT EXISTS {col} TEXT")
        conn.commit()

selfheal calls this before retrying, so the retry succeeds with the new column in place.

ESCALATE → on_escalate callback

def notify_slack(result: dict):
    print(f"[ALERT] {result['root_cause']}")

@healed(pipeline="orders_etl", on_escalate=notify_slack, max_retries=3)
def run():
    ...

Environment variables

Variable Default Description
TYPESAFE_API_KEY — TypeSafe JEV API key
ANTHROPIC_API_KEY — Anthropic Claude Haiku fallback
SH_OLLAMA_BASE_URL http://localhost:11434/v1 Ollama API base URL
SH_HEALER_OLLAMA_MODEL qwen3-coder:30b Ollama model for classification fallback
SH_MIN_CONFIDENCE 0.65 Minimum confidence to auto-heal
SH_MAX_SEVERITY 3 Max severity (1–5) to auto-heal

Version history

Version Changes
0.3.4 Replaced NVIDIA NIM with local Ollama (qwen3-coder:30b) as the third fallback backend — no external API key required; configure via SH_OLLAMA_BASE_URL and SH_HEALER_OLLAMA_MODEL
0.3.3 Major hardening: PATCH_AND_RETRY permanently removed; normalize_decision() strict fail-closed gate (unknown types → UNKNOWN/ESCALATE, out-of-range confidence fails closed, "false" string → False); ALLOWED_FAILURE_TYPES frozenset; IDENTIFIER_RE SQL injection guard on ADD_COLUMN columns; keyword fallback reordered (PERMISSION/RESOURCE checked before TRANSIENT); BAD_DATA + SCHEMA_DRIFT from keyword fallback always advisory (safe=False); retry_safe=False idempotency guard; exponential backoff on all retries including first; latest exception propagated through retry loop; QUARANTINE/ADD_COLUMN escalate with diagnosis context (no module hooks); send_source_code / source_redactor source privacy controls; bool rejected for max_retries; async on_escalate rejected for sync functions at decoration time; backoff params validated at decoration time; max_retries=0 handled without UnboundLocalError; suppress_escalated_exception param; server_url=None default
0.3.2 PyPI release
0.3.1 README updated for PyPI
0.3.0 TypeSafe JEV primary backend; ADD_COLUMN auto-heal; max_retries; runbook ingestion; confidence + severity thresholds
0.2.0 Anthropic + NVIDIA LLM backends
0.1.0 Initial release — keyword fallback only

selfheal-sdk — by Sahil Deol

Release files for selfheal-sdk 0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for selfheal-sdk 0.3.5
File Size Uploaded
selfheal_sdk-0.3.5.tar.gz 16.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for selfheal-sdk 0.3.5
File Interpreter ABI Platform
selfheal_sdk-0.3.5-py3-none-any.whl Python 3 none any Details

Total release size: 31.9 kB

Release files / selfheal_sdk-0.3.5.tar.gz

Download URL selfheal_sdk-0.3.5.tar.gz
Size 16.8 kB
Tags Source
SHA-256 checksum
How to use checksums
3966723de174ce384abcea164430ef0bdf716a652783a9425fa19ced399808f4
BLAKE2b-256 checksum
How to use checksums
33506f754d38a946426fbadd98743e1c2833f8f463c48dab9a9c987b2b17fd02
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.8

Release files / selfheal_sdk-0.3.5-py3-none-any.whl

Download URL selfheal_sdk-0.3.5-py3-none-any.whl
Size 15.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f9b66b1645f32d17e5a967456c93cbffaaa7efdc1e4db5c737b2e3e2f5598b0f
BLAKE2b-256 checksum
How to use checksums
c03c4faf2b38bf24c78b2089f15c22db9c8de69786d06f283fdc8ff722e7cea6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.8

Release history Release notifications | RSS feed

This release

0.3.5 This release

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page