Writing prompts in natural language is great—until they become messy with multiple steps, output format descriptions, and too many lines of text...
With prai, prompts become code—structured, maintainable, and debuggable—leading to high-quality, reliable outputs.
npm install prai
import { History, Model, openai, step } from 'prai'
import { z } from 'zod'
// 1. Inputs for our theme generation process
const brandName = `pmndrs`
const brandDescription = `Open source developer collective`
// 2. Zod schema for a color in hsl - will be given to the LLM as the expected output format
const colorScheme = z
.object({
hue: z.number().describe('in degree (0-360)'),
saturation: z.number().describe('in percent (0-100)'),
lightness: z.number().describe('in percent (0-100)'),
})
.describe('hsl color')
// 3. Create a model based on an AI provider (openai, groq, more support comming soon)
const model = new Model({ name: 'gpt-4.1-mini', apiKey: 'insert key here', provider: openai({ apiKey: "" }) })
// 4. create a chat history
const history = new History()
// 5. First step
const adjectives = await step(
//6. Enforce a strict schema on the output (a list of strings) - LLM will be forced to comply
`list some adjectives fitting the design of the ${brandName} brand which is a ${brandDescription}`,
z.array(z.string()),
{ model, history }
)
// 7. Second step—generate a basic theme
const coreTheme = await step(
// 9. We can reference results from history using history.reference
`Based on the ${history.reference(adjectives)}, derive fitting color theme`,
z.object({
background: colorScheme,
foreground: colorScheme,
primary: colorScheme,
secondary: colorScheme,
accent: colorScheme,
border: colorScheme,
radius: z.number().describe('radius in rem'),
}),
{ model, history }
)
// 10. Final step—expand into a full shadcn theme
const result = await step(
`Expand the ${history.reference(coreTheme)} to a full shadcn theme`,
z.object({
background: colorScheme,
//Full scheme in /examples/theme
}),
{ model, history }
)
console.log(result.value)
Explore the complete prai documentation to learn everything from basic concepts to advanced patterns:
- Introduction - Overview of prai concepts and core philosophy
- Your First Workflow - Step-by-step tutorial building a complete brand theme generator
- Special Step Types - Specialized functions for data processing (
mapStep
,filterStep
,combineStep
, etc.) - Advanced Usage - Streaming responses, conditional workflows, model fallbacks, and testing strategies
- Best Practices - Production guidelines and optimization tips