Open standard · v0.3.0
Unexpressible,
not filtered.
NILScript is the governed action layer for AI agents. The agent proposes; only the kernel commits; the undeclared action cannot be named. The structural guarantee holds while NIL is the sole effect path.
- 01propose
- 02approve
- 03commit
- 04rollback
Quick start
Up and running in three commands.
The CLI is the toolkit for building and verifying adapters straight from the standard. No account, key, or waitlist — install, scaffold, and watch a real propose→commit loop run locally.
1 · Install
# 0.3.0 is on PyPI
pip install "nilscript[cli]" # the adapter toolkit
pip install "nilscript[demo]" # + the local reference demo2 · Explore & scaffold
nilscript verbs # the verb catalog from the standard
nilscript scaffold-shim --name my-nil-adapter # a bootable shim for any backend
nilscript demo # run the reference demo locallyThree files become yours. Everything else is generated and identical across adapters — you build the surface once, and any NIL-speaking agent works against it.
system.pythe one place I/O happens
translate.pyverb ⇄ native
compensation.pyreversibility
The argument, in four moves
Try to break it. Then see why the cost collapses.
A filter inspects an action the agent has already named, and sometimes lets it through. NILScript removes the agent’s ability to name it. Watch the stream: declared intents reach the set, the undeclared one dissolves at the boundary — then walk the four steps.
The write happens inside the loop
In the ReAct pattern the agent reasons and acts in one loop. A poisoned observation steers the next real write. A filter blocks most attacks, but it is a probability, and the risk compounds with every step.
A guardrail blocks most injections. Across a run of n steps the leak compounds. The whole loop is the perimeter.
Deciding is severed from doing
Under NIL the loop can only emit a proposal: intent with zero effect. The real write happens at commit, outside the loop, behind a gate. Poison the loop and you get a pending decision, never a write.
A poisoned proposal becomes a held card a human can reject. The backend stays byte-identical. The effect moved outside the loop.
It isn’t caught. It can’t be named.
A filter maps your intent to an action, including the forbidden one, then gambles on blocking it. NIL only binds intent to declared actions. The forbidden action has no arrow into the declared set. There is nothing to point at.
Same forbidden action, both sides. Left: an arrow exists and a dice-roll lets it through. Right: there is no arrow to draw. Run it and watch the tokens.
Filter
Blocks with probability p < 1. Over many tries it leaks.
NIL
The verb isn’t in Σ, so it refuses at propose. Zero effect.
Spam it. The filter eventually commits a real payment. NIL stays at zero, every time, because the action it names was never declared.
One boundary, not one per step
Filtering needs a check at every step, and each check leaks. The cost of the perimeter is O(n) and the residual risk never reaches zero. NIL replaces the whole chain with a single structural boundary: O(1), and zero by construction, independent of the model. Move the dials.
The perimeter collapses
Each guard checkpoint blocks most attacks and leaks a little. Add steps and the accumulated risk climbs. Switch to NIL and the chain collapses to one boundary.
Independent of the model
Unauthorized-write rate against run length. The filter follows 1 − (1 − ε)n and moves with the model through ε. NIL is the flat line at zero.
The filter line bends with ε and climbs with n. The NIL line does not move, because the unauthorized action has no representation to commit. That is the whole claim, in one picture.
Proof
Unexpressible, not filtered: 0.00% unauthorized writes across 2,108 evals.
NIL is the layer between the agent and the backend, so we don’t compete on a leaderboard: we instrument one. Across 2,108 real prompt-injection attacks (base setting, two models), raw agents were hijacked into a write on up to 1 in 22 cases. Routed through NIL, unauthorized writes admitted at the gate 0.00%: an undeclared action has an empty preimage, so it is unexpressible, not merely filtered. Every authorized call still passes through (no false refusals). The defense is model-independent by construction.
- 0.00%
- unauthorized writes admitted at the gate
- 2,108
- base-setting injection evals, 2 models
- 4.46%
- raw hijack rate, ungated
- 100%
- authorized calls passed through (no false refusal)
Where it sits
Not another tool in the stack — the layer underneath the write.
Guardrails inspect the conversation, frameworks orchestrate the agent, engines run the workflow — and all of them still hand a namable write to the backend. NILScript is the one layer where an unauthorized action has no representation to send. It doesn’t replace a category; it’s the governance layer they all leave undefined.
- LLM Guardrails
- Safety Models
- AI Gateways
- Policy Engines
- Workflow Engines
- BPM Platforms
- Agent Frameworks
- Enterprise Integration
- Knowledge Graphs
- Digital Twin
- Intent-Based Systems
- NILScript ↓