Preview a run
What an agent would send a model, shown without calling one. And every event of a run, as it happens.
pnpm add @niscorp/cortex @niscorp/signal zod openaiThe model
createSignal makes the client that calls the model. Cortex is handed this client, here for Groq, and Signal reads the key from GROQ_API_KEY.
import { z } from 'zod';
import { createSignal } from '@niscorp/signal';
import { defineAgent, defineTool } from '@niscorp/cortex';
const llm = createSignal('groq');An agent
An agent with one tool, and an answer that has a shape.
const seatsLeft = defineTool({
id: 'seatsLeft',
name: 'seatsLeft',
description: 'How many seats are left on a night',
input: z.object({ night: z.string().describe('The night, as YYYY-MM-DD') }),
execute: ({ night }) => ({ night, left: night === '2026-10-24' ? 113 : 120 }),
});
const boxOffice = defineAgent({
id: 'box-office',
instructions: 'Look the night up with the seatsLeft tool, then give the answer.',
tools: [seatsLeft],
output: { schema: z.object({ left: z.number() }) },
});Preview
preview puts together exactly what a run would send: the messages, the tools, and how the answer will travel back. No model is called.
If something in the preview does not make sense to you, it will not make sense to the model either.
const question = 'How many seats are left on 2026-10-24?';
const preview = await boxOffice.preview(question, { llm });
console.log('answer travels by:', preview.strategy);
console.log('messages:', preview.messages.length, '· tools:', preview.tools.length);
console.log('about', preview.estimatedTokens, 'tokens');Every event
A run is a stream of events. for await reads them in order: the run starting, each step, each tool call before and after it runs, the answer as it is written, and the end.
const run = boxOffice.run(question, { llm });
for await (const event of run.events) {
if (event.type === 'tool-start') console.log('tool-start', event.call.toolId);
else if (event.type === 'tool-end') console.log('tool-end', event.observation.kind);
else if (!['model-delta', 'output-delta', 'output-partial'].includes(event.type)) console.log(event.type);
}Run it.
This file asks a model, so it is not run on this site. The preview needs no model: it prints how the answer will travel, the number of messages and tools, and a token estimate. Then, when the model calls the tool once and answers, the run’s events in order: run-start, step-start, tool-start seatsLeft, tool-end result, step-start, run-end. An answer that is sent back adds a retry.
GROQ_API_KEY=your-key npx tsx look.mts