An agent’s prompt
Cortex puts together what a model is told, once per run, from parts that each come from whoever knows them. This file builds an agent from those parts and prints what it would send. It calls no model.
pnpm add @niscorp/cortex @niscorp/signal zod openaiThe model
createSignal makes the client for a provider, here Groq. Nothing in this file calls it: a preview only asks the client what the provider can do, so it needs no key.
import { z } from 'zod';
import { createSignal } from '@niscorp/signal';
import { defineAgent, defineTool } from '@niscorp/cortex';
import type { Producer } from '@niscorp/cortex';
const llm = createSignal('groq');A tool with a guide
A tool’s description and input schema are sent with the tool. How to use it well goes in its guide, which Cortex puts in the prompt of every agent that has the tool, so an agent’s instructions never have to describe it.
const seatsLeft = defineTool({
id: 'seatsLeft',
name: 'seatsLeft',
description: 'How many seats are left on a night',
input: z.object({ night: z.string() }),
guide: 'Pass the night as YYYY-MM-DD. A night with no show answers left: 0.',
execute: ({ night }) => ({ night, left: night === '2026-10-24' ? 113 : 120 }),
});What the app knows
A producer is a function that returns what goes in the prompt. It is given the run’s deps, which are typed: here, the programme the app has read from its database.
It runs once, when a run starts. A string it returns becomes one system message, and an array of strings one message each.
type Deps = { programme: { night: string; title: string }[] };
const onStage: Producer<Deps> = ({ deps }) => deps.programme.map((show) => `${show.night}: ${show.title}`);The agent
instructions is the system prompt, and can be a function of deps too. context lists the agent’s producers: a string of its own, and the one above.
The schema is the contract for the answer, so there is no prose about the JSON to write. What a field must be goes in its .describe(), and Cortex sends the schema with it.
const Order = z.object({
night: z.string().describe('The night, as YYYY-MM-DD'),
seats: z.number().int().min(1).max(6),
});
const boxOffice = defineAgent<z.infer<typeof Order>, Deps>({
id: 'box-office',
instructions: 'Read the order out of the message. Check the night with the seatsLeft tool.',
context: ['Doors open thirty minutes before the show.', onStage],
tools: [seatsLeft],
output: { schema: Order },
});What the run adds
producers on a run come after the agent’s own. An app uses them for what every agent should know at that moment, such as who is asking, without changing any agent.
const programme = [
{ night: '2026-10-24', title: 'The Tempest' },
{ night: '2026-10-25', title: 'Twelfth Night' },
];
const preview = await boxOffice.preview('Two seats for Sunday, please.', {
llm,
deps: { programme },
producers: ['The member asking is Grace.'],
});Print it
preview returns the messages a run would start with, in the order Cortex puts them. Signal’s entry for Groq’s default model says it does not keep a tool’s arguments to their schema, so the answer is written as plain JSON (emit) and the schema goes in the prompt as OUTPUT SCHEMA.
The first four messages are the same on every run of this agent. They come first so that a provider’s prompt cache holds them.
console.log('answer travels by:', preview.strategy);
for (const message of preview.messages) {
const text = typeof message.content === 'string' ? message.content : JSON.stringify(message.content);
console.log(message.role.padEnd(7), text.split(/\s+/).slice(0, 6).join(' '));
}Run it.
It calls no model and needs no key. First the instructions, then the tool’s guide, the schema, and how to finish, which Cortex writes for the way the answer travels. Then the agent’s producers, the run’s, and the question as the user’s message.
npx tsx prompt.mtsanswer travels by: emit system Read the order out of the system TOOL GUIDES — how to use system OUTPUT SCHEMA — your output MUST system FINISH PROTOCOL: Use your tools as system Doors open thirty minutes before the system 2026-10-24: The Tempest system 2026-10-25: Twelfth Night system The member asking is Grace. user Two seats for Sunday, please.