Skip to main content
An agent exposes two ways to execute: run returns a single result once the agent loop finishes, and stream yields events as they arrive. Both take the same per-request input.

One-shot with run

run drives the agent loop to completion — calling the model, executing any tools it requests, and feeding the results back — then returns the final result:
const chat = container.get(SupportChat);

const answer = await chat.run<string>({ prompt: "Summarize this thread." });
Without an output schema, run resolves to the assistant’s collected text as a string. With one, it resolves to a validated, typed object — so type the call with the matching T.

Streaming

stream yields the raw run as an AG-UI event stream — text deltas, tool calls, and lifecycle events — so you can render output as it is produced:
for await (const event of chat.stream({ prompt: "Explain quantum computing." })) {
  if (event.type === "TEXT_MESSAGE_CONTENT") {
    process.stdout.write(event.delta);
  }
}
Narrow on event.type to handle only the chunks you care about.

Request input

Both methods accept a ChatInputType. Every field is optional, so chat.run() with no argument is valid.
FieldTypeDescription
promptstringThe user message, appended as the trailing turn.
messagesMessageType[]Prior conversation turns prepended before prompt.
systemPromptsstring[]Extra system prompts, appended after the agent’s base prompts.
toolsAiToolClassType[]Extra tools for this call only, added to the agent’s own.
middlewaresAiMiddlewareClassType[]Extra middleware for this call only.
temperaturenumberOutput randomness, range [0.0, 2.0].
topPnumberNucleus sampling threshold.
maxTokensnumberMaximum tokens to generate.
outputSchemaAssertTypeA schema for structured output.
metadataRecord<string, unknown>Request-scoped data carried through middleware — never sent to the model.
contextunknownRuntime dependencies for tools and middleware — never sent to the model.
conversationIdstringIdentifier for tracking a conversation.
abortControllerAbortControllerCancels the in-flight request.
agentLoopStrategyAgentLoopStrategyControls how the agent loop iterates (TanStack AI).

Conversation history

Pass prior turns in messages; prompt is always appended last:
const reply = await chat.run<string>({
  messages: [
    { role: "user", content: "My name is Alice." },
    { role: "assistant", content: "Hello Alice!" },
  ],
  prompt: "What is my name?",
});
// "Your name is Alice."

Sampling options

temperature, topP, and maxTokens map straight onto the model call:
await chat.run<string>({
  prompt: "Write a tagline.",
  temperature: 0.9,
  maxTokens: 60,
});

Cancellation

Pass an AbortController and abort it to cancel an in-flight run:
const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);

await chat.run<string>({ prompt: "Long task…", abortController: controller });

Metadata vs. context

Both metadata and context ride along with a request and neither is ever sent to the model — but they serve different roles:
  • metadata is part of the request config. It is shallow-merged across the run and can be read or transformed by middleware (e.g. tracing tags, feature flags, a session id).
  • context carries live dependencies — the authenticated user, a database client, an audit logger — that tools and middleware read via ctx.context.
await chat.run<string>({
  prompt: "List my notes.",
  metadata: { userId: "user_123", sessionId: "sess_456" },
  context: { db, currentUser },
});
See Middleware for how hooks read both.