Skip to main content

SNAIL — Single Node Activated Inference Layer

A Python DSL for composing frozen, single-pass neural primitives into statically-typed dataflow programs.

If an MCP tool and a markdown skill had a baby, and you told the LLM it wasn't allowed to interpret the recipe — it was just one of many nodes in the recipe — you'd get SNAIL.

Why

Most AI models are trained to be comprehensive. SNAIL trains tiny, single-task nodes — activated exactly once, locked output, frozen forever — and composes them into deterministic graphs.

A SNAIL program is a recipe that's more resilient than a .md spec and more deterministic than an MCP tool call. Every step is a typed function call, not a prompt the LLM might re-interpret. Every run emits a manifest. Every node knows what it doesn't know (OOD is a first-class type).

Install

pip install snail-dsl

Quick start

from snail import node, Program, edge
from pydantic import BaseModel

# Declare the type contract for each node's output.
class InvoiceTotal(BaseModel):
    ok: dict | None = None       # { "total": float, "currency": str, "confidence": float }
    ood: dict | None = None      # { "reason": str, "confidence": float, "threshold": float }

@node(
    name="extract_invoice_total",
    input_schema=dict,            # replace with a real pydantic model
    output_schema=InvoiceTotal,
    distribution="synthetic_invoices_v2",
    frozen_weights="weights/extract_invoice_total_v3.snail",
    confidence_threshold=0.7,
)
def extract_invoice_total(ctx, weights, image):
    raw = weights.model.forward(image["tensor"])
    return InvoiceTotal(ok={
        "total": raw["total"],
        "currency": raw["currency"],
        "confidence": raw["confidence"],
    })

# Compose into a typed DAG.
invoice_pipeline = Program(
    name="invoice_pipeline_v1",
    nodes=[extract_invoice_total],
    edges=[],
)

result = invoice_pipeline.run({"image_path": "scan.png"})
print(result.manifest)

The decorator enforces:

  • Single forward pass per call — no retries, no second thoughts.
  • Weights loaded once, frozen for the lifetime of the program.
  • Output type-checked against output_schema; mismatches become OOD.
  • Confidence below confidence_threshold is silently flipped to OOD.
  • Output is locked (immutable) before being handed back to the caller.

The four primitives

Primitive What it does
@node Decorator that wraps a Python function as a frozen, single-pass, OOD-aware node.
Program Container that builds a typed DAG of nodes. Validates at construction time.
edge() Builder for typed field-to-field connections between nodes.
manifest Structured per-run log: which nodes fired, what they got, what they returned.

Architecture

  • Nodes are frozen, single forward pass, locked output.
  • Composition is a static DAG declared in Python.
  • Training is 100% synthetic, offline.
  • OOD is a first-class type (Ok / OOD discriminated union).
  • Every node ships with golden tests (pytest).
  • Every run emits a manifest.

Wrapping external models

External models (HuggingFace, hosted APIs, pure functions) become nodes through wrappers. They never get called directly.

from snail.wrappers import ExternalLocalNode, HostedNode, DeterministicNode

# Pin a local model to exact weights hash
classify_layout = ExternalLocalNode(
    name="classify_layout",
    input_schema=InvoiceImage,
    output_schema=LayoutClass,
    distribution="rvl_cdip_subset",
    call=lambda img: yolo_model.predict(img.path),
    weight_pin="yolov8n@sha256:abc123...",
)

# Wrap a hosted API
summarize = HostedNode(
    name="summarize",
    input_schema=InvoiceText,
    output_schema=InvoiceSummary,
    endpoint="anthropic://claude-sonnet-4-5",
    prompt_template="Summarize: {text}",
    api_key_env="ANTHROPIC_API_KEY",
)

# Or just a pure function
validate_email = DeterministicNode(
    name="validate_email",
    input_schema=EmailField,
    output_schema=EmailValidated,
    fn=lambda x: x if "@" in x.value else None,
    ood_on_none=True,
)

Testing

pip install -e ".[dev]"
pytest

Golden tests live in tests/golden/. The lint rule (catches direct import openai, import anthropic, etc. outside wrappers) is enforced via the snail.lint module.

License

Apache License 2.0. Copyright 2026 Tico Internet LLC.

Status

v0.2.0 — beta. Adds the training tooling (recipe YAML, train_recipe, freeze_weights, golden tests), real provider clients (anthropic, openai, ollama, stub), the snail CLI (run, inspect, render, train, verify), and a DAG renderer that emits SVG.

v0.2.0 quickstart

Train a recipe

# recipe_classify_intent.recipe.yaml
name: classify_intent
dataset: customer_intents_v3
frozen_output: weights/classify_intent.snail.json
nodes:
  - name: classify_intent
    input_schema: Message
    output_schema: Intent
    distribution: customer_intents_v3
    epochs: 5
    learning_rate: 0.001
    weight_pin: phi-4-mini-3.8b@sha256:placeholder
golden_cases:
  - input: {text: "I want a refund"}
    expected: {intent: refund, confidence_min: 0.7}
snail train recipe_classify_intent.recipe.yaml --output-dir ./weights

Render the DAG

snail render examples/customer_support_v3.py --out dist/customer_support_v3.svg

Use real providers

import os
os.environ["ANTHROPIC_API_KEY"] = "..."
from snail.wrappers import HostedNode

summarize = HostedNode(
    name="summarize",
    input_schema=In,
    output_schema=Out,
    distribution="english_v1",
    endpoint="anthropic://claude-sonnet-5",
    prompt_template="Summarize: {text}",
    api_key_env="ANTHROPIC_API_KEY",
    provider="anthropic",   # NEW in v0.2.0
)

Verify golden cases

snail verify examples/customer_support_v3.py --golden-dir ./goldens

Release files for snail-dsl 0.2.0

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

Source distribution (sdist)

Source distribution for snail-dsl 0.2.0
File Size Uploaded
snail_dsl-0.2.0.tar.gz 43.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for snail-dsl 0.2.0
File Interpreter ABI Platform
snail_dsl-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 83.9 kB

Release files / snail_dsl-0.2.0.tar.gz

Download URL snail_dsl-0.2.0.tar.gz
Size 43.5 kB
Tags Source
SHA-256 checksum
How to use checksums
ccde93cb87f6b18244b35926d43c3c30ef15d625ee53815c7634ccf7ad279548
BLAKE2b-256 checksum
How to use checksums
97aa21073d980b11b17f5c902ba58c53e07268a5a52f4b6ee947159e7493dfba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / snail_dsl-0.2.0-py3-none-any.whl

Download URL snail_dsl-0.2.0-py3-none-any.whl
Size 40.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
63058f6dd3800477ed0b0d4963d70b0db329c10e9d254e2c8569b44ce8c2f15c
BLAKE2b-256 checksum
How to use checksums
5fc143bc9abbf5a234e1f01a0943442f3b4c07a131faaa8b91a7f519fd025bd7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.0

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