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_thresholdis 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.1.0 — alpha. The core primitives (@node, Program, edge(), wrappers, manifest, lint) are working. The training pipeline for producing .snail weights is not yet included — that ships in v0.2.0.
Release files for snail-dsl 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| snail_dsl-0.1.0.tar.gz | 23.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| snail_dsl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.0 kB
Release files / snail_dsl-0.1.0.tar.gz
| Download URL | snail_dsl-0.1.0.tar.gz |
|---|---|
| Size | 23.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ca33533c3f7b31da2e3a053bf25578fd4ca2cdb800238be20730d47dd107fb08
|
|
BLAKE2b-256 checksum How to use checksums |
d008c950e7813e8fb0d178cf81e9b7119a83f9031f58db33ae0d9218e50f4e27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.1
|
Release files / snail_dsl-0.1.0-py3-none-any.whl
| Download URL | snail_dsl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
33cc43136cb383c5fff482ec3342ac753b45a817d4c15e1954bcec58e15a3378
|
|
BLAKE2b-256 checksum How to use checksums |
5c6a2f81bb54d2c28b10df6b77282d2fd06b0e5ef764e81a2e9ba579c79ed4ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.1
|