Skip to content

Agents ​

An agent is a typed config object passed to defineAgent(). It names a model, its instructions, the triggers that may start it, a tool factory, a budget, approval policies, typed state and a notifier.

ts
const reporter = defineAgent({
    name: 'weekly-report',
    model,
    instructions: 'Summarize the open work items in the trigger payload.',
    triggers: [
        manual(),
        cron('0 8 * * 1', { timezone: 'Europe/Berlin' }),
    ],
    budget: {
        maxSteps: 10,
        maxTokens: 50_000,
        timeoutMs: 5 * 60 * 1000,
    },
    tools: ({ run, state }) => ({
        lastReport: tool({
            description: 'Returns the date of the previous report.',
            inputSchema: z.object({}),
            execute: async () => (await state.get<string>('lastReport')) ?? 'never',
        }),
        saveReport: tool({
            description: 'Remembers that a report was written now.',
            inputSchema: z.object({}),
            execute: async () => {
                await state.set('lastReport', run.trigger.receivedAt.toISOString());
                return { saved: true };
            },
        }),
    }),
});

What defineAgent() checks ​

defineAgent() validates the definition and returns { name, definition } with defaults applied. It throws InvalidAgentDefinitionError when:

  • the name does not match ^[a-z0-9]+(-[a-z0-9]+)*$ (lowercase words joined by single hyphens), or is longer than 64 characters,
  • two triggers of the agent share an id.

The engine checks the rest when you construct it: agent names must be unique within one RunEngine, and every notify must name a notifier registered on the engine.

ts
const agent = defineAgent({
    name: 'echo',
    model,
    instructions: 'Repeat the payload.',
});

agent.name; // 'echo'
agent.definition.budget; // { maxSteps: 20, timeoutMs: 900_000 }

Fields ​

FieldTypeDefaultDescription
namestringrequiredUnique per engine, lowercase words joined by -, at most 64 characters
modelLanguageModelrequiredAny AI SDK model
instructionsstringrequiredSystem instructions
triggersTriggerDefinition[]noneFrom cron(), http() and manual(). See Triggers
tools(ctx) => ToolSetnoneTool factory, called for each execution
stateRecord<string, StandardSchemaV1>noneTyped state collections. See Agent State
budgetPartial<Budget>{ maxSteps: 20, timeoutMs: 900_000 }See Budgets & Timeouts
approvalsRecord<string, ApprovalPolicy>noneTools that need approval. See Approvals
approvalTimeoutMsnumber86_400_000 (24 h)After this, a pending approval is denied
notifystringnoneName of a notifier registered on the engine

The budget you pass is merged over the defaults, so budget: { maxSteps: 5 } keeps the 15 minute timeout.

The tools factory ​

tools is a function, not a ToolSet. The engine calls it once per execution with:

FieldTypeDescription
stateAgentStateThe agent's state, typed by its state schema
run.runIdstringId of the run being executed
run.agentstringAgent name
run.triggerTriggerEnvelopeThe envelope that started the run
run.signalAbortSignalAborts on cancel, drain, a lost lease or the run timeout

A factory lets tools close over per-run data, such as the run id in an effect key or the repository named in the payload. Pass run.signal on to fetch and other cancellable work.

The returned tools are plain AI SDK tools. When the agent declares state, the engine adds generated state tools; your tools win on a name clash. Every effect tool is then wrapped so it applies at most once per effect key.

Many agents per engine ​

One engine runs any number of agents. They share the store, the concurrency limit and the notifiers:

ts
const triage = defineAgent({
    name: 'triage',
    model,
    instructions: 'Triage the issue.',
});
const digest = defineAgent({
    name: 'digest',
    model,
    instructions: 'Summarize the day.',
    notify: 'console',
});

const engine = new RunEngine({
    store: new MemoryStore(),
    agents: [triage, digest],
    notifiers: { console: new ConsoleNotifier() },
    resumeSecret: 'change-me',
    maxConcurrentRuns: 8,
    claimTtlMs: 30_000,
});

dispatch() names the agent per run. An unknown agent name throws InvalidAgentDefinitionError.