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.