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

# Agents

> Core agent concepts, AgentConfig, run/stream methods, and RunOutput in Agentium.

# Agents

## In plain terms

An **agent** is a single AI worker. You give it a job description ("you're a support assistant"), hand it a few tools ("here's how to look up an order"), and it figures out how to use them to answer each request.

It's the basic building block of everything in Agentium. One agent handles one role — like one employee. Need a whole department? You connect several agents into a [Team](/teams/overview).

> **The analogy:** if the AI model is a smart brain, an *agent* is that brain plus a job title, a set of tools, and a memory. The brain alone can only talk; the agent can actually get things done.

## What is an Agent? (technical)

An **Agent** in Agentium is a conversational AI unit that processes user input, optionally calls tools, and produces text or structured output. Agents are model-agnostic—you plug in any supported LLM provider (OpenAI, Anthropic, Google Gemini, Ollama)—and can be extended with tools, memory, sessions, and guardrails.

<CardGroup cols={2}>
  <Card title="Synchronous" icon="play">
    Use `run(input, opts?)` for a single request-response cycle.
  </Card>

  <Card title="Streaming" icon="stream">
    Use `stream(input, opts?)` for token-by-token or chunk-by-chunk output.
  </Card>
</CardGroup>

***

## AgentConfig

Configure an agent by passing an `AgentConfig` object to the `Agent` constructor. All properties except `name` and `model` are optional.

<ParamField path="name" type="string" required>
  Display name for the agent. Used in logs, events, and registry/route lookup.

  Names are **labels, not unique keys** (v2.3.2+): creating multiple agents with the same name never throws — the registry keeps the most recently constructed instance (last-write-wins). This makes ephemeral agents safe to create in loops, factories, or per-request handlers. Pass `register: false` to skip the registry entirely for throwaway agents.
</ParamField>

<ParamField path="model" type="ModelProvider" required>
  The LLM provider instance. Use factory functions like `openai("gpt-4o")`, `anthropic("claude-sonnet-4-20250514")`, or `google("gemini-2.0-flash")`.
</ParamField>

<ParamField path="instructions" type="string | (ctx) => string" required={false}>
  System instructions for the agent. Can be a static string or a function that receives `RunContext` and returns a string (useful for dynamic prompts).
</ParamField>

<ParamField path="tools" type="ToolDef[]" required={false}>
  Array of tool definitions created with `defineTool()`. Enables function calling.
</ParamField>

<ParamField path="memory" type="Memory" required={false}>
  Memory instance for short-term and optional long-term conversation context. See <a href="/agents/memory">Memory</a>.
</ParamField>

<ParamField path="storage" type="StorageDriver" required={false}>
  Storage driver for sessions. Defaults to `InMemoryStorage` if not provided.
</ParamField>

<ParamField path="sessionId" type="string" required={false}>
  Default session ID for this agent. Can be overridden per-run via `RunOpts`.
</ParamField>

<ParamField path="userId" type="string" required={false}>
  Default user ID for this agent. Can be overridden per-run via `RunOpts`.
</ParamField>

<ParamField path="addHistoryToMessages" type="boolean" required={false} default="true">
  Whether to include session history in the messages sent to the LLM. Set to `false` to disable.
</ParamField>

<ParamField path="numHistoryRuns" type="number" required={false}>
  Limits how many prior turns to include. Each turn = 2 messages (user + assistant). If unset, defaults to 20 messages.
</ParamField>

<ParamField path="maxToolRoundtrips" type="number" required={false} default="10">
  Maximum number of tool-call rounds before stopping. Prevents infinite loops.
</ParamField>

<ParamField path="temperature" type="number" required={false}>
  Sampling temperature passed to the model (0–2 typically). Lower = more deterministic.
</ParamField>

<ParamField path="structuredOutput" type="ZodSchema" required={false}>
  Zod schema to enforce structured JSON output. See <a href="/agents/structured-output">Structured Output</a>.
</ParamField>

<ParamField path="hooks" type="AgentHooks" required={false}>
  Lifecycle hooks: `beforeRun`, `afterRun`, `onToolCall`, `onError`. See <a href="/agents/hooks-and-guardrails">Hooks & Guardrails</a>.
</ParamField>

<ParamField path="guardrails" type="{ input, output }" required={false}>
  Input and output guardrails. Each is an array of validators. See <a href="/agents/hooks-and-guardrails">Hooks & Guardrails</a>.
</ParamField>

<ParamField path="eventBus" type="EventBus" required={false}>
  Custom event bus for emitting agent events. Defaults to a new `EventBus` if not provided.
</ParamField>

<ParamField path="reasoning" type="ReasoningConfig" required={false}>
  Enable extended thinking / chain-of-thought reasoning. See <a href="/agents/reasoning">Reasoning</a>.
</ParamField>

<ParamField path="userMemory" type="UserMemory" required={false}>
  User memory instance for cross-session personalization. See <a href="/agents/user-memory">User Memory</a>.
</ParamField>

<ParamField path="logLevel" type="string" required={false} default="silent">
  Logging level: `"debug"` | `"info"` | `"warn"` | `"error"` | `"silent"`. Default is `"silent"`.
</ParamField>

<ParamField path="retry" type="Partial<RetryConfig>" required={false}>
  Retry configuration for transient LLM API failures (429, 5xx, network errors). Default: 3 retries with exponential backoff.
</ParamField>

<ParamField path="maxTokens" type="number" required={false}>
  Maximum output tokens per LLM call. Note: when `reasoning` is enabled, the Anthropic provider may override this to ensure enough room for both thinking and response tokens.
</ParamField>

<ParamField path="maxContextTokens" type="number" required={false}>
  Maximum context window tokens. When set, conversation history is automatically trimmed (oldest messages first) to fit within this limit.
</ParamField>

<ParamField path="toolResultLimit" type="ToolResultLimitConfig" required={false}>
  Limit large tool results before they're sent back to the LLM. Prevents prompt token explosion when tools return massive payloads (e.g. MCP servers returning 200KB of data). See <a href="/agents/tools#tool-result-limits">Tool Result Limits</a>.
</ParamField>

***

## Methods

### run(input, opts?) → RunOutput

Processes user input and returns the full response.

<CodeGroup>
  ```typescript Agent.run() theme={null}
  const result = await agent.run("What is the capital of France?");
  console.log(result.text);
  console.log(result.usage.totalTokens);
  ```

  ```typescript With RunOpts theme={null}
  const result = await agent.run("Continue our discussion.", {
    sessionId: "user-123-session",
    userId: "user-123",
    metadata: { source: "web" },
    apiKey: "sk-...", // Per-request API key override
  });
  ```
</CodeGroup>

### stream(input, opts?) → AsyncGenerator\<StreamChunk>

Streams the response as chunks. Use for real-time UIs or SSE.

```typescript theme={null}
for await (const chunk of agent.stream("Tell me a short story.")) {
  if (chunk.type === "text") process.stdout.write(chunk.text);
  if (chunk.type === "finish") console.log("\nDone.", chunk.usage);
}
```

***

## RunOpts

Options passed to `run()` or `stream()`:

| Property    | Type                      | Description                                                         |
| ----------- | ------------------------- | ------------------------------------------------------------------- |
| `sessionId` | `string`                  | Session ID for multi-turn conversations. Auto-generated if omitted. |
| `userId`    | `string`                  | User identifier.                                                    |
| `metadata`  | `Record<string, unknown>` | Arbitrary metadata available in `RunContext`.                       |
| `apiKey`    | `string`                  | Per-request API key override for the model provider.                |

***

## RunOutput

The object returned by `run()`:

| Property             | Type               | Description                                                         |
| -------------------- | ------------------ | ------------------------------------------------------------------- |
| `text`               | `string`           | The assistant's text response.                                      |
| `toolCalls`          | `ToolCallResult[]` | Results from any tool calls made during the run.                    |
| `usage`              | `TokenUsage`       | Token usage breakdown (see below).                                  |
| `structured`         | `unknown`          | Parsed structured output when `structuredOutput` schema is set.     |
| `thinking`           | `string`           | Model's internal reasoning content (when reasoning is enabled).     |
| `durationMs`         | `number`           | Wall-clock duration of the run in milliseconds.                     |
| `timeToFirstTokenMs` | `number`           | Time from request start to the first token received from the model. |
| `runId`              | `string`           | Unique identifier for this run (UUID).                              |
| `agentName`          | `string`           | Name of the agent that produced this output.                        |
| `sessionId`          | `string`           | Session ID used for this run.                                       |
| `userId`             | `string`           | User ID used for this run.                                          |
| `model`              | `string`           | Model identifier (e.g., `"gpt-4o"`, `"gemini-2.5-flash"`).          |
| `modelProvider`      | `string`           | Provider identifier (e.g., `"openai"`, `"vertex"`, `"anthropic"`).  |
| `status`             | `string`           | Run status: `"completed"` or `"error"`.                             |
| `createdAt`          | `number`           | Unix timestamp (ms) when the run started.                           |
| `responseId`         | `string`           | Provider-specific response ID (e.g., OpenAI's `chatcmpl-*`).        |
| `messages`           | `ChatMessage[]`    | Full message history sent to the model (system + history + user).   |
| `metrics`            | `RunMetrics`       | Aggregated metrics for the run (see below).                         |

### TokenUsage

```typescript theme={null}
interface TokenUsage {
  promptTokens: number;
  completionTokens: number;
  totalTokens: number;
  reasoningTokens?: number;
  cachedTokens?: number;
  audioInputTokens?: number;
  audioOutputTokens?: number;
  providerMetrics?: Record<string, unknown>;
}
```

The `providerMetrics` field contains the **raw, unmodified usage object** returned by the underlying provider API. This gives you full transparency into provider-specific metrics (e.g., `thoughtsTokenCount` from Gemini, `prompt_tokens_details` from OpenAI, `cache_read_input_tokens` from Anthropic).

### RunMetrics

```typescript theme={null}
interface RunMetrics {
  inputTokens: number;
  outputTokens: number;
  totalTokens: number;
  timeToFirstTokenMs?: number;
  durationMs?: number;
}
```

***

## Basic Example

<CodeGroup>
  ```typescript Minimal agent theme={null}
  import { Agent, openai } from "@agentium/core";

  const agent = new Agent({
    name: "Assistant",
    model: openai("gpt-4o"),
    instructions: "You are a helpful assistant. Be concise.",
  });

  const result = await agent.run("What is the capital of France?");
  console.log(result.text);
  ```

  ```typescript With tools and logging theme={null}
  import { Agent, openai, defineTool } from "@agentium/core";
  import { z } from "zod";

  const weatherTool = defineTool({
    name: "getWeather",
    description: "Get weather for a city",
    parameters: z.object({ city: z.string() }),
    execute: async ({ city }) => `${city}: 22°C, sunny`,
  });

  const agent = new Agent({
    name: "ToolBot",
    model: openai("gpt-4o"),
    tools: [weatherTool],
    instructions: "Use tools when needed.",
    logLevel: "info",
  });

  const result = await agent.run("What's the weather in Tokyo?");
  console.log(result.text);
  ```
</CodeGroup>

***

### Full-Featured Agent Example

A comprehensive example showing all major config options together:

```typescript theme={null}
import {
  Agent, anthropic, CostTracker, MongoDBStorage,
  defineTool, type ContentPart,
} from "@agentium/core";
import { z } from "zod";

const storage = new MongoDBStorage("mongodb://localhost:27017/myapp");
const costTracker = new CostTracker({
  budget: { maxCostPerSession: 2.0, onBudgetExceeded: "warn" },
});

const searchTool = defineTool({
  name: "searchDatabase",
  description: "Search the product database by query",
  parameters: z.object({
    query: z.string().describe("Search query"),
    limit: z.number().optional().describe("Max results (default 10)"),
  }),
  execute: async ({ query, limit }) => {
    const results = await db.search(query, limit ?? 10);
    return JSON.stringify(results);
  },
});

const agent = new Agent({
  name: "product-assistant",
  model: anthropic("claude-sonnet-4-6"),
  instructions: "You help customers find products. Be concise and helpful.",
  tools: [searchTool],

  // Memory: persistent sessions + summaries + user personalization
  memory: {
    storage,
    maxMessages: 20,
    summaries: true,
    userFacts: true,
    userProfile: true,
    model: anthropic("claude-haiku-4-5-20251001"),
  },

  // Tool routing: only send relevant tools to the model
  toolRouter: {
    model: anthropic("claude-haiku-4-5-20251001"),
    maxTools: 5,
  },

  // Tool result limits: summarize large API responses
  toolResultLimit: {
    maxChars: 20000,
    strategy: "summarize",
    model: anthropic("claude-haiku-4-5-20251001"),
  },

  // Extended thinking for complex queries
  reasoning: { enabled: true, budgetTokens: 2000 },

  // Cost tracking with session budget
  costTracker,

  // Lifecycle hooks
  hooks: {
    beforeRun: async (ctx) => {
      console.log(`[${ctx.runId}] Starting run for session ${ctx.sessionId}`);
    },
    afterRun: async (ctx, output) => {
      console.log(`[${ctx.runId}] Completed in ${output.durationMs}ms, ${output.usage.totalTokens} tokens`);
    },
    onError: async (ctx, error) => {
      console.error(`[${ctx.runId}] Error: ${error.message}`);
    },
  },

  logLevel: "info",
  maxToolRoundtrips: 3,
});

const result = await agent.run("Find me wireless headphones under $100", {
  sessionId: "session-abc",
  userId: "user-42",
});

console.log(result.text);
console.log(`Cost: $${costTracker.getSummary().totalCost.toFixed(4)}`);
```

***

### Dynamic Instructions

Instructions can be a function that receives `RunContext`, allowing you to customize the system prompt per request:

```typescript theme={null}
const agent = new Agent({
  name: "support-bot",
  model: openai("gpt-4o"),
  instructions: (ctx) => {
    const role = ctx.metadata?.role ?? "customer";
    const lang = ctx.metadata?.language ?? "English";
    return `You are a support agent. The user's role is "${role}".
Respond in ${lang}. Be concise and professional.
Session state: ${JSON.stringify(ctx.sessionState)}`;
  },
});

// The instructions function is called fresh on every run
const result = await agent.run("How do I reset my password?", {
  metadata: { role: "admin", language: "Spanish" },
});
```

This is useful for multi-tenant apps, internationalization, or injecting session-specific context into the prompt.
