extract-person
This example extracts a Person from a message, then passes the result to a TypeScript helper that trims the name and employer. Nola derives the JSON Schema from the Person interface at compile time and validates the model’s response at runtime.
The helper lives in src/format.ts. The .tsi file imports it using the NodeNext ./format.js specifier, just as another TypeScript module would.
The line in backticks above the ask is a context statement: text every ask below it sees. The .message parameter is data the model reads; the statement is your words.
import { normalizePerson } from "./format.js";
export interface Person { name: string; age: number; employer: string; job: string;}
export infer function extractPerson(.message: string) { // A bare template literal on its own line is a context statement: text every // ask below it sees. `.message` is data; the statement is your words. `Answer from the text alone; never invent facts.` const person = ask `the person described in the text`: Person; return normalizePerson(person);}// Plain TypeScript, imported from person.tsi with the standard NodeNext// `./format.js` specifier — mixing existing TS code into a nola module// needs no special setup.import type { Person } from "./person.tsi";
export function normalizePerson(person: Person): Person { return { ...person, name: person.name.trim(), employer: person.employer.trim() };}Run it
Section titled “Run it”npx nola-lang run src/main.ts # mock provider (deterministic)# real model: edit nola.config.ts to openai({ model: "gpt-5-mini" }) (needs OPENAI_API_KEY)Prints {"name":"Alice Smith","age":32,"employer":"Acme Corp","job":"staff engineer"}.
Scaffold: npm create nola my-app -- --template typescript-interop. This template omits the format.ts helper and runs on a committed replay ledger (nola.replay.jsonl). The default feature-extraction template demonstrates extraction in a single .tsi script.
Source: examples/extract-person on GitHub.
Next: extract-resume