Skip to content

Design Patterns ​

Intend is flexible. You can write your entire app in "fuzzy" AI steps, or you can write 99% of it in strict TypeScript and just use Intend for the tricky bits.

Here are common patterns for building robust apps.

1. The "Guardrail" Pattern ​

Use invariant to force the AI to implement safety checks before doing work.

typescript
export intent DeleteAccount(userId: string) -> void {
    // This isn't just a comment. 
    // The compiler enforces that logic exists to satisfy this!
    invariant "User must not be an Admin"
    
    step "Delete the user from DB"
}

Why: If the AI tries to generate a simple "DELETE FROM users" query, the invariant will force it to wrap that in an if (!isAdmin) check.

2. The "Orchestrator" Pattern ​

Use Intend as a high-level script that glues together your existing strict Typescript functions.

typescript
import { StripeCharge, DbSave, EmailSend } from "./lib";

export intent ProcessOrder(order: Order) -> void {
    // Intend handles the flow...
    step "Validate order stock" 
    
    // ...but calls strict code for the heavy lifting
    StripeCharge(order.total) => const chargeId
    
    DbSave(order, chargeId)
    
    EmailSend(order.email, "Confirmed!")
}

Why: This makes your business logic "readable as English" top-to-bottom, while keeping the "how" (Stripe API calls, SQL queries) hidden in strict, reliable TypeScript files.

3. The "Parser" Pattern ​

LLMs are world-class parsers. Use them to normalize messy inputs into strict types.

typescript
// Incoming: "  John Doe - 555.0199 "
export intent NormalizeContact(raw: string) -> Contact {
    step "Extract name and phone number from raw string" => const temp
    
    step "Format phone number to E.164 standard (+1...)" => const phone
    
    return { name: temp.name, phone: phone }
}

Why: Writing Regex for every possible phone number format is a nightmare. AI solves this trivially.

Released under the MIT License.