u

The 13th keyword. The human-AI boundary in the grammar.

u f marks a function whose body is generated by an LLM, type-checked by the compiler, and cached forever. Add u to delegate. Remove it to take over. One letter.

What it looks like

U
/// Rank products by relevance to the query.
/// Prefer exact title matches. Boost recent listings.
u f search(query: S, catalog: [Product]) -> [Product]

/// Detect fraudulent transactions from user history.
/// False positive rate must stay under 1%.
u f fraud_check(txn: Transaction, history: [Transaction]) -> RiskScore

// No u — human owns this. The wiring is yours.
f main()
	serve(8080, {
		"GET /search": (req) => Response.json(
			search(req.query["q"], load_catalog())
		)
	})

The humans wrote types, signatures, wiring, and intent (the comments). The AI wrote every function body. The compiler checked every one against the modifier system. The project reads like a table of contents.

How it works

1. The LLM gets context, not a blank page. When u2c --ai compiles a u f function, the LLM receives:

The function signature — params, types, modifiers, return type, error types
The UDoc comments — prescriptive intent the types can't express
The call graph — which functions this one calls and what they promise
The call sites — how callers actually use this function
Callee summaries — what the functions it calls do (from their UDoc)

2. The compiler verifies the result. The generated body is type-checked, linter-checked, and modifier-checked like any human-written code. -M means the AI can't mutate inputs. -E means no side effects. ! ErrorType means it must handle that error. The modifiers ARE the spec.

3. The result is cached. The generated body is saved in a .gen.u file next to the source. Subsequent builds use the cache — zero token cost. u2c --regen regenerates only when a signature, dependency, or call site changes.

The toggle

U
// Step 1: AI manages everything
u f checkout(cart: Cart, user: User) -> Receipt ! PaymentFailed

// Step 2: AI decomposes into sub-functions
// (generated in .gen.u)
u f validate_cart(cart: Cart) -> ValidatedCart ! EmptyCart
u f charge_payment(cart: ValidatedCart, user: User) -> Charge ! PaymentFailed
u f issue_receipt(charge: Charge, user: User) -> Receipt

// Step 3: Human takes over payment — just remove u
f charge_payment(cart: ValidatedCart, user: User) -> Charge ! PaymentFailed
	gateway = Stripe.connect(Config.stripe_key)
	r => gateway.charge(cart.total, user.payment_method)

// AI still manages the others

Add u — the AI takes over. The existing body is replaced by AI-generated code on next --regen.

Remove u — the .gen.u content inlines into the source. Frozen. You own it. The AI never touches it again.

The boundary is per-function, not all-or-nothing. You can claim any subtree.

When an LLM writes U code

Every function is u f by default. This is honest: the AI wrote it, another AI can rewrite it, a human can take over. The u modifier IS the provenance. No metadata files. No "generated by AI" comments. The syntax says it.

Agent generates
u f validate_email(email: S) -> L
u f hash_password(plain: S) -> S
u f create_user(name: S, email: S, password: S) -> User ! ValidationError
u f send_welcome(user: User) -> none +E
u f signup(req: Request) -> Response ! ValidationError

Over time, humans claim the functions they care about by removing u. What's left is the code nobody needs to own by hand — and the AI keeps it maintained.

Two directions of programming

Bottom-up: humans write frameworks, libraries, stable infrastructure — regular f, battle-tested, production-hardened. This is the foundation.

Top-down: a customer call happens. An agent hears the intent. It writes u f functions that use the bottom-up framework. The compiler checks them against the typed dependency graph — not by searching files, but by walking edges it already knows.

The stable code is human-owned. The evolving business logic is AI-managed. The typed boundary between them is the u modifier.

Why modifiers matter more than prompts

Every AI coding tool today relies on natural-language prompts to guide generation. In U, the modifier system provides a formal specification for free:

ModifierWhat it tells the AI
-M (default)You can't mutate the inputs
-E (default)No side effects — no I/O, no logging, no network
-D (default)Must be deterministic — same inputs, same output
+RThis is heap-allocated — manage the reference
+VMust be vectorizable — no branches, no exceptions
! ErrorTypeMust handle this specific error
+NMay return none — handle the null case

The AI isn't generating freestyle code — it's filling a constrained slot. The compiler checks the result against the same rules that apply to human code.

Structured intent — /// @tag

The type system captures purity, mutability, and error types. But business intent, performance requirements, and security constraints need natural language. Structured tags bridge the gap:

U
/// @intent Rank by relevance. Prefer exact title matches.
/// @constraint False positive rate must stay under 1%.
/// @perf Must complete in under 100ms for catalogs up to 10K items.
/// @example search("red shoes", catalog) => [Product{title: "Red Shoes"}]
/// @security Never expose internal product IDs in results.
u f search(query: S, items: [Product]) -> [Product]
	...

The compiler parses these tags, includes them in the LLM prompt, and includes them in the contract fingerprint. If the intent changes — even without a signature change — the body is regenerated. The tags are:

@intent — what the function should accomplish
@constraint — invariants the generated body must maintain
@perf — performance requirements
@example — input/output examples (informal test cases)
@security — security-sensitive requirements
Plain /// without a tag becomes the description.

UDoc: the dual of code

For regular f, the compiler derives documentation mechanically from the AST — what the function reads, writes, guards on, throws. All deterministic, can never go out of sync. No LLM. No transformer. Try it in the playground — the UDoc tab shows derived facts in 20 languages, instantly, in the browser.

For u f, the comments are the INPUT to generation — they prescribe intent the types can't express. The compiler can diff the prescribed intent against the derived behavior: if the UDoc says "never exceed budget" but the generated code has a rounding edge case, the compiler flags it mechanically.

f → code is truth, UDoc is derived downward
u f → UDoc is truth, code is derived upward
Same facts. Opposite directions. Same format.

Pay once, cache forever

When a u f function is compiled with --ai, the LLM is invoked once. The generated body is saved as a .gen.u file — valid U source with a metadata header and footer:

search.gen.u
/// @generated abc123def456 model=claude-sonnet-4-6
f search(query: S, items: [Product]) -> [Product]
	exact = items.filter(item => item.title == query)
	partial = items.filter(item => item.title.contains(query))
	r => exact + partial

/// @meta tokens=342 confidence=0.8 at=2026-07-30
/// @footer 2

Subsequent builds use the cache — zero token cost. The compiler regenerates only when the contract fingerprint changes:

A signature changes (the contract changed)
A type it depends on changes (the data shape changed)
A new call site appears (someone uses it differently)
A callee's contract changes (downstream behavior changed)

This makes AI-assisted compilation practical for large codebases. The expensive step happens once per function per contract change, not once per build.

The graph verifies everything

The real value isn't generating code — LLMs can do that without a compiler. The value is verifying that generated code fits. When a u f body is generated, the compiler checks it against every edge in the typed dependency graph:

Does it satisfy the callers' expectations?
Does it respect the modifiers of the things it calls?
Does it handle the error types that callees declare?
Does it maintain the invariants that transitive callers depend on?

These checks are mechanical, exhaustive, and instant. The LLM pays the creative cost once. The graph pays the verification cost forever, at compiler speed.

Why agents fail — and why u doesn't

The HANDBOOK.md benchmark (July 2026) found that the best frontier agents pass only 36.2% of standing-instruction tasks. Agents let requests override policy, lose rule details over long horizons, and report compliance they didn't achieve.

u f functions can't have this problem. The constraints aren't in a 100-page handbook the agent might forget — they're in the function signature the compiler checks on every build. The policy IS the type system.

The bridge

A customer describes what they need. An agent writes u f functions expressing that intent — typed signatures, modifier constraints, plain-English UDoc. The compiler verifies the generated code fits the existing codebase via the dependency graph. The graph is not re-inferred — it IS the compilation.

U is designed for a world where the people describing what they want and the systems building it are close enough to meet. The u keyword is where they meet.

See it in action

Playground (UDoc tab) Safebots integration Tutorial