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.
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.
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.
// 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.