<nil>NILScript

Get Started

Quickstart

Install the standard, explore the verb catalog from the CLI, and run your first PROPOSE → COMMIT loop — no account, key, or waitlist required.

Install

The core package is data only — JSON schemas and docs with zero runtime dependencies. Optional extras add the typed Python SDK.

shell
pip install nilscript            # the standard: schemas, docs, and CLI — zero runtime deps
pip install "nilscript[sdk]"     # adds the typed Python client (httpx + pydantic)
npm install nilscript            # the spec + JSON Schemas for the JS/TS ecosystem
Requirements
Python ≥ 3.12 for the tooling. The standard itself is language-agnostic — conform a backend by implementing six HTTP endpoints in any language. There is no [cli] extra; the CLI ships in the base package.

Explore the standard

Use the CLI to list verbs, inspect a verb’s full contract, and export an OpenAPI surface for codegen.

shell
nilscript verbs                  # list every standard verb
nilscript profile commerce.create_product   # inspect one verb's profile
nilscript export-openapi -o openapi.yaml     # OpenAPI 3.1 for the six endpoints

Your first plan

An agent never writes directly. It proposes; the server returns a preview or a refusal; on approval the server commits idempotently. The single-action loop is PROPOSE PROPOSALCOMMIT.

The agent only ever proposes
The server renders the preview from facts it resolves, never from values the agent supplied. That is what makes a hallucinated amount or customer id harmless.

Multi-step automation

When one action is not enough, the agent compiles intent into a DSL program (a JSON DAG). A validator checks it before any side effect; the runtime executes it node by node. The pattern is query → condition → action:

restock.nil.json
{
  "wosool": "0.1",
  "workspace": "ws_demo",
  "locale": "en-SA",
  "entry": "check_stock",
  "pipeline": [
    { "id": "check_stock", "type": "query",
      "verb": "commerce.get_product", "args": { "id": "prod_5512" } },
    { "id": "needs_restock", "type": "condition",
      "when": "$.check_stock.output.stock < 5",
      "then": "reorder", "else": null },
    { "id": "reorder", "type": "action",
      "verb": "commerce.create_restock_task",
      "args": { "product": "prod_5512", "quantity": 50 } }
  ],
  "on_error": "halt"
}

Ask, don’t guess

When the agent requests “refund Mohammed’s last order” and three customers named Mohammed exist, the server returns an AMBIGUOUS refusal (200 OK) with up to eight candidates for a human to choose — not a guessed error.

Build an agent

Have your agent emit NIL messages or DSL programs and never execute directly. The loop is generation → validation → regeneration:

  1. The agent generates a NIL message or DSL program.
  2. The validator checks schema, references, safety, and the verb whitelist — before any side effect.
  3. If invalid, structured diagnostics come back; the agent reads them and self-heals.
  4. Refusals (AMBIGUOUS, UNRESOLVED, INVALID_ARGS, POLICY_DENIED) are normal 200 OK answers, not errors.

Conform a backend

Implement six stateless HTTP endpoints that translate agent intent into your existing API:

  • PROPOSE — returns a preview, writes nothing.
  • COMMIT — writes once, emits an EVENT with result.entity.
  • QUERY — returns fresh business truth, never cached.
  • STATUS — poll a running or parked action.
  • EVENT — push a signed result after execution.
  • ROLLBACK — request a governed reversal, answered by a PROPOSAL then COMMIT.
Idempotency is non-negotiable
A retried COMMIT with the same key replays the original outcome — it never double-writes. An unmarked verb defaults to IRREVERSIBLE and refuses ROLLBACK honestly.

What to read next

NILScript is an open standard, stewarded by the Wosool project. The spec is extracted from running code.

Draft standard v0.3.0 · 0.x stage · NIL wire 0.1 · DSL 0.1