> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Running an Agent

> Run an agent to completion or stream its events, and shape each call with per-request input

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:

```typescript theme={null}
const chat = container.get(SupportChat);

const answer = await chat.run<string>({ prompt: "Summarize this thread." });
```

Without an [output schema](/ai/agents/structured-output), `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](https://tanstack.com/ai) event stream — text deltas, tool calls, and lifecycle events — so you can render output as it is produced:

```typescript theme={null}
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.

| Field               | Type                      | Description                                                                   |
| ------------------- | ------------------------- | ----------------------------------------------------------------------------- |
| `prompt`            | `string`                  | The user message, appended as the trailing turn.                              |
| `messages`          | `MessageType[]`           | Prior conversation turns prepended before `prompt`.                           |
| `systemPrompts`     | `string[]`                | Extra system prompts, appended after the agent's base prompts.                |
| `tools`             | `AiToolClassType[]`       | Extra [tools](/ai/agents/tools) for this call only, added to the agent's own. |
| `middlewares`       | `AiMiddlewareClassType[]` | Extra [middleware](/ai/agents/middleware) for this call only.                 |
| `temperature`       | `number`                  | Output randomness, range `[0.0, 2.0]`.                                        |
| `topP`              | `number`                  | Nucleus sampling threshold.                                                   |
| `maxTokens`         | `number`                  | Maximum tokens to generate.                                                   |
| `outputSchema`      | `AssertType`              | A schema for [structured output](/ai/agents/structured-output).               |
| `metadata`          | `Record<string, unknown>` | Request-scoped data carried through middleware — never sent to the model.     |
| `context`           | `unknown`                 | Runtime dependencies for tools and middleware — never sent to the model.      |
| `conversationId`    | `string`                  | Identifier for tracking a conversation.                                       |
| `abortController`   | `AbortController`         | Cancels the in-flight request.                                                |
| `agentLoopStrategy` | `AgentLoopStrategy`       | Controls how the agent loop iterates (TanStack AI).                           |

### Conversation history

Pass prior turns in `messages`; `prompt` is always appended last:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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`.

```typescript theme={null}
await chat.run<string>({
  prompt: "List my notes.",
  metadata: { userId: "user_123", sessionId: "sess_456" },
  context: { db, currentUser },
});
```

See [Middleware](/ai/agents/middleware) for how hooks read both.
