Describe what you want. Your agent writes the spec and the code. NTNT verifies both match.
IDD is a methodology built into NTNT where requirements become executable specifications. When you prompt an agent to build a feature, the agent writes both the .intent file and the implementation. NTNT continuously verifies that the code matches the intent — giving the agent a closed feedback loop and giving you a readable spec of exactly what was built.
You write code, then write tests to verify it. Tests drift from requirements. Requirements live in Jira tickets nobody reads. There’s no single source of truth connecting what was asked for to what was built.
Traditional testing is backward — you write code, then write tests to verify it. Tests drift from requirements. Requirements live in Jira tickets nobody reads. There’s no single source of truth connecting “what was asked for” to “what was built.”
Requirements ARE the tests. Your agent writes them in .intent files using the Intent Assertion Language (IAL), annotates the code with @implements, and runs ntnt intent check to verify everything matches. One source of truth. No drift. You review the intent file — not the test suite.
When you describe a feature in a prompt, the agent generates both the intent file and the implementation in one pass. It runs ntnt intent check, sees what failed, and iterates — all without human intervention. You get a readable intent file to review instead of opaque test code.
You describe what you want. The agent generates the intent spec and the implementation. NTNT verifies they match.
From your prompt, the agent creates a .intent file with features, scenarios, and a glossary — natural language phrases that map to executable checks. You review the spec before implementation begins.
# server.intent ## Glossary | Term | Means | |---------------------------|--------------------------| | a user visits {path} | GET {path} | | the home page | / | | the page loads | status 200 | | they see "{text}" | body contains "{text}" | --- Feature: Home Page id: feature.home Scenario: Shows welcome message When a user visits the home page → the page loads → they see "Welcome" Scenario: Shows navigation When a user visits the home page → they see "About" → they see "Contact"
GET /, “the page loads” resolves to status 200. Defined once, reused across every feature.The agent writes the code and links it to the intent with @implements annotations. NTNT knows which code is responsible for which requirements.
// @implements: feature.home fn home(req) { return html("<h1>Welcome</h1><nav><a href='/about'>About</a> <a href='/contact'>Contact</a></nav>") } get("/", home) listen(8080)
@implements: feature.home annotation links this function to the intent. When the agent runs ntnt intent check, it sees exactly which scenarios passed and which failed — then iterates until everything is green.The agent runs ntnt intent check and gets a definitive pass/fail. Every scenario maps back to a requirement. The agent iterates on failures automatically — you see the final result.
$ ntnt intent check server.tnt ✓ Feature: Home Page ✓ Shows welcome message ✓ the page loads → status 200 ✓ they see "Welcome" → body contains "Welcome" ✓ Shows navigation ✓ they see "About" → body contains "About" ✓ they see "Contact" → body contains "Contact" 1/1 features passing · 4/4 assertions
IDD covers unit functions, cross-cutting constraints, and runtime contracts. One methodology, the whole codebase.
# utils.intent ## Glossary | Term | Means | |---------------------|--------------------------------------------------| | slugifying {text} | call: to_slug({text}), source: utils.tnt | --- Feature: URL Slugs id: feature.slugs Scenario: Basic conversion When slugifying "Hello World" → result is "hello-world" → is lowercase → does not contain " " Scenario: Deterministic When slugifying "Hello World" → is deterministic
# security.intent Constraint: Security Headers description: "All responses include security headers" applies_to: [feature.home, feature.api] → header "X-Frame-Options" exists → header "X-Content-Type-Options" equals "nosniff"
fn divide(a: Int, b: Int) -> Float requires b != 0, "divisor must not be zero" ensures result * b == a, "division must be reversible" { return a / b } // requires fails → 400 Bad Request (in HTTP routes) // ensures fails → 500 Internal Server Error (in HTTP routes)
The call: and source: keywords let you test individual functions without spinning up a server. is deterministic is a built-in property check — NTNT calls the function multiple times and verifies consistent output.
Constraints apply across multiple features. Define security requirements once, and every annotated feature is checked against them. Cross-cutting concerns belong in one place.
Contracts are runtime-checked preconditions and postconditions. They document the API contract AND enforce it. In HTTP routes, violations automatically return proper error responses.
These assertions work without a Glossary — they’re built into the IDD runtime and available in any intent file.
status 200 — exact status codestatus 2xx — status classbody contains "text"body matches /pattern/body is emptyresponse is valid JSONresponse time < 100msheader X existsheader X equals Ycontent-type is jsoncode passes lintno syntax errorsresult is Xis lowercaseis non-emptystarts with "prefix"ends with "suffix"is deterministicis idempotentntnt intent check server.tnt | Verify implementation matches intent — pass/fail for every scenario |
ntnt intent studio server.intent | Live visual feedback as you code (opens :3001) |
ntnt intent coverage server.tnt | See which features are covered and which aren’t |
ntnt intent init server.intent | Generate code scaffolding from an intent file |
Install NTNT and describe your first feature. Your agent generates the intent spec, writes the implementation, and verifies it all matches — automatically.