Core Concepts
NIL — Wire Protocol
NIL (Network Intent Layer) is the lower layer: if the DSL is the program, NIL is the syscall interface. It defines an immutable envelope, a closed set of performatives, six HTTP endpoints, and refusals as first-class protocol outcomes.
The envelope
Every NIL message is immutable — eight fields, no more. additionalProperties: false rejects any unknown field at the door.
| Field | Meaning |
|---|---|
nil | Protocol version (currently “0.1”) |
id | Unique message id |
performative | One of the closed performative set |
grant | The scoped, budgeted authorization in use |
workspace | Tenant / isolation unit |
timestamp | RFC 3339 creation time |
trace | W3C Trace Context traceparent |
body | Performative-specific payload |
{
"nil": "0.1",
"id": "msg_01HZX9Q7C3",
"performative": "PROPOSE",
"grant": "grant_acme_agent",
"workspace": "ws_acme",
"timestamp": "2026-06-16T09:00:00Z",
"trace": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"body": {
"verb": "commerce.create_product",
"args": { "name": "Desert Honey 500g", "price": "85.00", "currency": "SAR" }
}
}Performatives — a closed set
NIL has a closed vocabulary: seven performatives on the speaker plane, plus DECIDE on the owner plane. The kernel is SEQRD-PC. Six map to HTTP endpoints; PROPOSAL is the synchronous response to PROPOSE and ROLLBACK.
| Performative | Side effects | Purpose |
|---|---|---|
PROPOSE | None (dry run) | “What would happen if I did this?” |
PROPOSAL | None | The answer: a preview or a refusal |
COMMIT | Yes | Execute a previewed proposal |
QUERY | None | Read state |
STATUS | None | Check a proposal or run |
EVENT | — | Signed, sequenced notification |
ROLLBACK | None | Request a governed reversal |
DECIDE | Authorizes | Owner plane: approve / reject / modify |
DECIDE remains the separate, credential-separated owner-plane performative. A profile cannot invent a new performative — the performatives are the grammar, the profiles are the vocabulary.PROPOSE → PROPOSAL
The two-phase core. PROPOSE has no side effects; the system answers with a PROPOSAL — either a preview or a refusal. The preview is rendered from system-resolved facts, never from the agent’s hint.
{
"nil": "0.1",
"performative": "PROPOSAL",
"body": {
"outcome": "preview",
"proposal_id": "prop_77c1",
"tier": "MEDIUM",
"preview": {
"ar": "إنشاء فاتورة لـ «شركة آكمي» بمبلغ 4,200.00 ر.س",
"en": "Create invoice for 'Acme Corporation' for SAR 4,200.00"
},
"resolved": {
"customer_id": "cust_3391",
"customer_name": "Acme Corporation",
"amount": "4200.00", "currency": "SAR"
},
"modifiable": ["discount_pct"],
"expires_at": "2026-06-16T09:15:01Z"
}
}COMMIT
COMMIT references an existing proposal_id and carries an idempotency key. A retried COMMIT with the same key is a no-op that replays the original outcome with replayed: true — no second invoice.
{
"performative": "COMMIT",
"body": {
"proposal_id": "prop_77c1",
"idempotency_key": "create_invoice@run_5530"
}
}QUERY & STATUS
QUERY is read-only — no side effects, no proposal, fresh business truth. STATUS checks the state of a proposal or a run, which matters for parked HIGH and CRITICAL proposals awaiting a decision.
EVENT
The system pushes signed, ordered notifications following Standard Webhooks conventions. Each carries a monotonic sequence number per workspace for dedup and an HMAC-SHA256 signature. A sequence gap means a missed event; a repeat means dedup.
ROLLBACK
The lifecycle-closing primitive. ROLLBACK requests a reversal of a prior committed action; it does not execute. Like PROPOSE it has no side effects — the system answers with a PROPOSAL (a compensation preview), which is then COMMITted like any other action. So “no silent write” holds for free. The system resolves the verb’s reversibility tier:
- REVERSIBLE — a clean inverse (
create_product↔delete_product). - COMPENSABLE — an offsetting forward action (
record_payment→process_refund). - IRREVERSIBLE — refused honestly with code
IRREVERSIBLE; the default for any unmarked verb.
Verbs and profiles
A verb is a domain action — commerce.create_product, services.create_invoice — that names intent, not implementation. Whether it becomes a SQL insert, a GraphQL mutation, or three SOAP calls is the system’s problem. A verb is standard only if it has a published profile, which fixes its arg schema, tier floor, modifiable facts, resolution rules, and localized preview templates.
commerce.create_product present the same preview to a human and accept the same args from an agent. That is what makes NIL a port, not just an API.Refusals are outcomes
The most important design decision in NIL: a refusal is a 200 OK PROPOSAL, not an HTTP error. The system decided not to proceed, and that decision is data the agent and human can reason about. An AMBIGUOUS refusal returns up to eight candidates rather than a guess:
{
"performative": "PROPOSAL",
"body": {
"outcome": "refusal",
"code": "AMBIGUOUS",
"message": "3 customers match 'Acme'. Choose one.",
"candidates": [
{ "id": "cust_3391", "label": "Acme Corporation", "hint": "Riyadh · 41 invoices" },
{ "id": "cust_7720", "label": "Acme Trading Est.", "hint": "Jeddah · 2 invoices" },
{ "id": "cust_9015", "label": "Acme Holdings", "hint": "Dammam · 0 invoices" }
]
}
}| Code | Meaning |
|---|---|
AMBIGUOUS | Hint matched >1; returns ≤8 candidates |
UNRESOLVED | Hint matched nothing |
INVALID_ARGS | Args failed the profile schema |
POLICY_DENIED | No grant authorizes the action |
BUDGET_EXHAUSTED | Grant budget spent (fail-closed) |
EXPIRED / SUSPENDED | Proposal/grant expired, or actor suspended |
IRREVERSIBLE | ROLLBACK targeted an effect with no reversal |
Standards alignment
NIL deliberately reuses existing standards instead of reinventing them:
| Standard | Used for |
|---|---|
| W3C Trace Context | The trace field |
| BCP 47 | Locale tags for previews |
| ISO 4217 | Currency codes |
| RFC 6750 | Bearer tokens |
| RFC 9457 | Problem Details (transport errors) |
| Standard Webhooks | Signed EVENT (HMAC-SHA256 + sequence) |