nua.list()
list() processes an array of records in a single LLM request and returns one output per row.
Signature
Section titled “Signature”nua.list< S extends z.ZodTypeAny, TData extends Record<string, unknown>, PK extends keyof TData & string, Name extends string,>( prompt: string, options: ListOptions<S, TData, PK, Name>): Promise<CastResult<ListResultRow<S, PK, Name>[]>>Parameters
Section titled “Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Instructions applied to each row. Keep it constant across calls. |
options.input | TData[] | Yes | Array of objects to process. |
options.primaryKey | keyof TData | Yes | Name of a property that uniquely identifies each row. |
options.output.name | string | Yes | Property name for the generated value on each result row. |
options.output.schema | Zod schema | Yes | The shape of the value generated for each row. |
options.model | ModelInput | No | Overrides the client’s default model for this call. |
Result rows
Section titled “Result rows”Each result row has two properties: the primary key, echoed back by the model, and the output under output.name.
const result = await nua.list('Analyze the sentiment of each review', { input: [ { reviewId: 'r1', text: 'Great product! Exceeded expectations.' }, { reviewId: 'r2', text: 'Terrible service. Never buying again.' }, ], primaryKey: 'reviewId', output: { name: 'sentiment', schema: z.enum(['positive', 'neutral', 'negative']) },});
// result.data:// [// { reviewId: 'r1', sentiment: 'positive' },// { reviewId: 'r2', sentiment: 'negative' },// ]Rows are typed from the primary key and the output’s name. Here each row is { reviewId: string | number; sentiment: 'positive' | 'neutral' | 'negative' }, so row.sentiment is typed and row.sentment is a type error. Pass output.name as a string literal, as above, to get this type. A name in a variable typed as string gives rows whose every other property has the output’s type.
The primary key
Section titled “The primary key”The model may return rows in a different order than the input, so always match result rows to inputs by primary key, never by array index:
const byId = new Map(reviews.map((r) => [r.reviewId, r]));
for (const row of result.data) { const review = byId.get(row.reviewId); // ...}Each input object must be an object containing the primaryKey property and at least one other property. Choose a field that is unique within the array, such as id, email, or slug. Values may be strings or numbers.
Nuabase parses every returned row with your schema, but doesn’t require that every input row comes back. If a missing row would matter, compare the returned keys against your input.
Examples
Section titled “Examples”Lead enrichment
Section titled “Lead enrichment”const EnrichmentSchema = z.object({ companySize: z.enum(['solo', 'small', 'medium', 'enterprise']), priority: z.enum(['low', 'medium', 'high']), recommendedPlan: z.string(),});
const result = await nua.list('Analyze each lead and recommend a plan', { input: [ { id: 'lead-1', notes: 'CEO at Acme Corp, interested in enterprise plan' }, { id: 'lead-2', notes: 'Freelancer, looking for starter tier' }, { id: 'lead-3', notes: 'CTO at growing startup, evaluating options' }, ], primaryKey: 'id', output: { name: 'enrichment', schema: EnrichmentSchema },});
if (result.success) { for (const row of result.data) { console.log(`${row.id}: ${row.enrichment.priority} - ${row.enrichment.recommendedPlan}`); }}Content tagging
Section titled “Content tagging”const TagSchema = z.object({ tags: z.array(z.string()).max(5), difficulty: z.enum(['beginner', 'intermediate', 'advanced']),});
const result = await nua.list('Generate tags and a difficulty level for each article', { input: articles, // [{ slug, title, content }, ...] primaryKey: 'slug', output: { name: 'metadata', schema: TagSchema },});Routing support email
Section titled “Routing support email”const RouteSchema = z.object({ department: z.enum(['support', 'sales', 'billing', 'engineering']), urgency: z.enum(['low', 'normal', 'high', 'critical']),});
const result = await nua.list('Classify each email for routing', { input: emails, // [{ messageId, subject, body }, ...] primaryKey: 'messageId', output: { name: 'routing', schema: RouteSchema },});Large arrays
Section titled “Large arrays”All rows go into one request, so the input must fit the model’s context, and the output for every row must fit in one response. On API providers a response is capped at 4096 output tokens. For large datasets, split the array into chunks and call list() per chunk:
const chunkSize = 50;const rows = [];
for (let i = 0; i < leads.length; i += chunkSize) { const result = await nua.list(prompt, { input: leads.slice(i, i + chunkSize), primaryKey: 'id', output, }); if (!result.success) throw new Error(result.error); rows.push(...result.data);}Using the same prompt for every chunk lets the provider reuse its prompt cache. You can also run chunks in parallel with Promise.all; a local agent runs at most concurrency (default 2) processes at once and queues the rest.