Skip to content

pmndrs/prai

Repository files navigation

prai 🤖

JS Framework for building step-by-step LLM instructions
(programmable ai)


NPM NPM Twitter Discord

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

What does it look like?

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:

Getting Started

  • 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

Core Concepts

  • Steps - Fundamental building blocks of prai workflows with schema integration and examples
  • Models - AI provider abstraction supporting OpenAI, Groq, Gemini, and mock providers
  • History - Conversation tracking, reference system, subtasks, and multimodal support

About

JS Framework for building step-by-step LLM instructions

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

No packages published