# Agent class

The `Agent` class is the foundation for creating AI agents in Mastra. It provides methods for generating responses, streaming interactions, and handling voice capabilities.

## Usage examples

### Basic string instructions

Passing instructions as a string or array of strings is the simplest way to set up an agent. This is useful for straightforward use cases where you need to provide a prompt without additional configuration.

```typescript
import { Agent } from '@mastra/core/agent'

// String instructions
export const agent = new Agent({
  id: 'test-agent',
  name: 'Test Agent',
  instructions: 'You are a helpful assistant that provides concise answers.',
  model: 'openai/gpt-5.5',
})

// System message object
export const agent2 = new Agent({
  id: 'test-agent-2',
  name: 'Test Agent 2',
  instructions: {
    role: 'system',
    content: 'You are an expert programmer',
  },
  model: 'openai/gpt-5.5',
})

// Array of system messages
export const agent3 = new Agent({
  id: 'test-agent-3',
  name: 'Test Agent 3',
  instructions: [
    { role: 'system', content: 'You are a helpful assistant' },
    { role: 'system', content: 'You have expertise in TypeScript' },
  ],
  model: 'openai/gpt-5.5',
})
```

### Provider-specific configurations

Each model provider also enables a few different options, including prompt caching and configuring reasoning. You can set `providerOptions` on the instruction level to set different caching strategy per system instruction/prompt.

```typescript
import { Agent } from '@mastra/core/agent'

export const agent = new Agent({
  id: 'core-message-agent',
  name: 'Core Message Agent',
  instructions: {
    role: 'system',
    content: 'You are a helpful assistant specialized in technical documentation.',
    providerOptions: {
      openai: {
        reasoningEffort: 'low',
      },
    },
  },
  model: 'openai/gpt-5.5',
})
```

### Mixed instruction formats

```typescript
import { Agent } from '@mastra/core/agent'

// This could be customizable based on the user
const preferredTone = {
  role: 'system',
  content: 'Always maintain a professional and empathetic tone.',
}

export const agent = new Agent({
  id: 'multi-message-agent',
  name: 'Multi Message Agent',
  instructions: [
    { role: 'system', content: 'You are a customer service representative.' },
    preferredTone,
    {
      role: 'system',
      content: 'Escalate complex issues to human agents when needed.',
      providerOptions: {
        anthropic: { cacheControl: { type: 'ephemeral' } },
      },
    },
  ],
  model: 'anthropic/claude-sonnet-4-6',
})
```

## Thread signals

Use Agent signals to send real-time input and context into a memory thread. Message APIs are for user-authored input. `sendSignal()` is the lower-level API for system-generated context.

When the target thread is running, `sendMessage()` delivers the message into the active agent loop. When the thread is idle, Mastra starts a stream with the message as the first input by default.

```typescript
const subscription = await agent.subscribeToThread({
  resourceId: 'user-123',
  threadId: 'thread-abc',
})

void (async () => {
  for await (const chunk of subscription.stream) {
    console.log(chunk)
  }
})()

agent.sendMessage('Use the latest customer note too.', {
  resourceId: 'user-123',
  threadId: 'thread-abc',
  ifIdle: {
    streamOptions: {
      maxSteps: 3,
    },
  },
})
```

Use `attributes` to identify different users in a shared thread. The attributes are rendered as XML so the model can distinguish who said what:

```typescript
agent.sendMessage(
  {
    contents: 'Can we simplify the API surface?',
    attributes: { name: 'Devin', from: 'slack' },
  },
  { resourceId: 'user-123', threadId: 'thread-abc' },
)
```

The model receives this as:

```xml
<user name="Devin" from="slack">Can we simplify the API surface?</user>
```

The UI sees the message contents and can also read `attributes` and `metadata` off the signal message for custom rendering (e.g. showing user names, avatars, or platform badges).

### `sendMessage(message, options)`

Sends a user message to an active run or memory thread. Use this when the active agent should receive the message immediately.

**message** (`string | Array<TextPart | FilePart> | { contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): User-authored input. Bare strings and parts without attributes are sent to the model as normal user input. When \`attributes\` are present, Mastra renders the message as a \`\<user>\` XML element with the attributes included.

**options.runId** (`string`): Run ID to target directly. Use this when you already know the active run ID.

**options.resourceId** (`string`): Resource ID for the memory thread. Required with \`threadId\` for thread-targeted messages.

**options.threadId** (`string`): Thread ID to target. Required with \`resourceId\` for thread-targeted messages.

**options.ifActive.behavior** (`'deliver' | 'persist' | 'discard'`): Controls what happens when the target thread is active. Defaults to \`deliver\`.

**options.ifIdle.behavior** (`'wake' | 'persist' | 'discard'`): Controls what happens when the target thread is idle. Defaults to \`wake\`.

**options.ifIdle.streamOptions** (`AgentExecutionOptions`): Options for the stream that starts when \`ifIdle.behavior\` is \`wake\`. Mastra uses the top-level \`resourceId\` and \`threadId\` for memory context.

Returns `{ accepted: true, runId: string, signal: CreatedAgentSignal, persisted?: Promise<void> }`. `persisted` is only present for `persist` behavior and resolves when Mastra finishes writing the message to memory.

### `queueMessage(message, options)`

Queues a user message for the next turn on a thread. If the thread is active, Mastra waits for the active run to finish, then starts a new run with the queued message. If the thread is idle, Mastra starts a run immediately.

```typescript
agent.queueMessage('Also check whether the tests need updates.', {
  resourceId: 'user-123',
  threadId: 'thread-abc',
})
```

`queueMessage()` accepts the same `message` and `options` shape as `sendMessage()` and returns `{ accepted: true, runId: string, signal: CreatedAgentSignal, persisted?: Promise<void> }`.

### `sendSignal(signal, options)`

Sends a signal to an active run or memory thread.

**signal** (`{ type: 'user' | 'state' | 'reactive' | 'notification' | 'user-message' | 'system-reminder'; tagName?: string; contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): Signal context to send to the thread. \`type\` is the semantic signal category. \`tagName\` controls the XML tag the model sees. For example, \`{ type: 'notification', tagName: 'github-review' }\` renders as \`\<github-review>...\</github-review>\`. Legacy \`user-message\` and \`system-reminder\` payloads are still accepted and normalized. Unknown \`type\` values are rejected; use \`tagName\` for custom XML tags.

**options.runId** (`string`): Run ID to target directly. Use this when you already know the active run ID.

**options.resourceId** (`string`): Resource ID for the memory thread. Required with \`threadId\` for thread-targeted signals.

**options.threadId** (`string`): Thread ID to target. Required with \`resourceId\` for thread-targeted signals.

**options.ifActive.behavior** (`'deliver' | 'persist' | 'discard'`): Controls what happens when the target thread is active. Defaults to \`deliver\`.

**options.ifIdle.behavior** (`'wake' | 'persist' | 'discard'`): Controls what happens when the target thread is idle. Defaults to \`wake\`.

**options.ifIdle.streamOptions** (`AgentExecutionOptions`): Options for the stream that starts when \`ifIdle.behavior\` is \`wake\`. Mastra uses the top-level \`resourceId\` and \`threadId\` for memory context.

Returns `{ accepted: true, runId: string, signal: CreatedAgentSignal, persisted?: Promise<void> }`. `persisted` is only present for `persist` behavior and resolves when Mastra finishes writing the signal to memory.

### `sendNotificationSignal(notification, options)`

Creates or coalesces a notification inbox record, resolves the notification delivery policy, and sends a notification signal when the decision is immediate.

```typescript
const result = await agent.sendNotificationSignal(
  {
    source: 'github',
    kind: 'ci-status',
    priority: 'high',
    summary: 'CI failed on main: 3 tests failed.',
    dedupeKey: 'github:acme/app:main:ci',
  },
  {
    resourceId: 'user-123',
    threadId: 'thread-abc',
  },
)
```

**notification.source** (`string`): External system that produced the notification, such as \`github\`, \`slack\`, or \`email\`.

**notification.kind** (`string`): Notification kind within the source, such as \`ci-status\`, \`mention\`, or \`direct-message\`.

**notification.summary** (`string`): LLM-facing summary used as the notification signal contents.

**notification.priority** (`'low' | 'medium' | 'high' | 'urgent'`): Priority used by the notification delivery policy. Defaults to \`medium\`.

**notification.payload** (`unknown`): Structured payload stored on the inbox record for tools or application code.

**notification.dedupeKey** (`string`): Key used to coalesce duplicate pending notifications from the same source and thread.

**notification.coalesceKey** (`string`): Key used to combine related pending notifications from the same source and thread.

**notification.attributes** (`Record<string, JSONValue>`): Extra attributes copied onto the emitted notification signal.

**notification.metadata** (`Record<string, unknown>`): Application metadata stored on the inbox record.

**options.resourceId** (`string`): Resource ID for the notification inbox and target memory thread.

**options.threadId** (`string`): Thread ID for the notification inbox and target memory thread.

**options.ifIdle.streamOptions** (`AgentExecutionOptions`): Options for the stream that starts when an immediate notification wakes an idle thread.

Returns `{ accepted: true, record: NotificationRecord, decision: NotificationDeliveryDecision, runId?: string, signal?: CreatedAgentSignal, persisted?: Promise<void> }`. `record` is the stored inbox record. `decision` is the delivery-policy result. `signal` and `runId` are present when ingress emits a signal immediately, including the immediate summary emitted for active high-priority notifications. `persisted` is present when the emitted signal is persisted without waking an idle thread.

Default delivery is priority-aware. `urgent` notifications deliver immediately. `high` notifications deliver immediately when the thread is idle; when the thread is active, Mastra emits a summary immediately and keeps `deliverAt` for later full delivery when the thread is idle. `medium` notifications deliver immediately when idle and batch into summaries when active. `low` notifications batch into summaries in both active and idle threads; idle low-priority summaries reach subscribers without waking the model loop. For the full flow, visit [Signals](https://mastra.ai/docs/agents/signals).

### `subscribeToThread(options)`

Subscribes to raw stream chunks for a memory thread. Use this before calling `sendMessage()`, `queueMessage()`, or `sendSignal()` when you need to render stream output, observe signal echoes, or abort the active run.

**options.resourceId** (`string`): Resource ID for the memory thread.

**options.threadId** (`string`): Thread ID to subscribe to.

Returns an `AgentThreadSubscription` object with these members:

**stream** (`AsyncIterable<AgentChunkType>`): Raw agent stream chunks for the subscribed thread.

**activeRunId** (`() => string | null`): Returns the active run ID for the thread, or \`null\` when no run is active.

**abort** (`() => boolean`): Aborts the active run for the thread. Returns \`true\` when a run was aborted.

**unsubscribe** (`() => void`): Stops the subscription without aborting the active run.

## Constructor parameters

**id** (`string`): Unique identifier for the agent. Defaults to \`name\` if not provided.

**name** (`string`): Display name for the agent. Used as the identifier if \`id\` is not provided.

**description** (`string`): Optional description of the agent's purpose and capabilities.

**metadata** (`Record<string, unknown> | ({ requestContext: RequestContext }) => Record<string, unknown> | Promise<Record<string, unknown>>`): Optional metadata for classifying or filtering the agent in clients. Can be a static record or a function that resolves the metadata from the request context.

**instructions** (`SystemMessage | ({ requestContext: RequestContext }) => SystemMessage | Promise<SystemMessage>`): Instructions that guide the agent's behavior. Can be a string, array of strings, system message object, array of system messages, or a function that returns any of these types dynamically. SystemMessage types: string | string\[] | CoreSystemMessage | CoreSystemMessage\[] | SystemModelMessage | SystemModelMessage\[]

**model** (`MastraLanguageModel | ({ requestContext: RequestContext }) => MastraLanguageModel | Promise<MastraLanguageModel>`): The language model used by the agent. Can be provided statically or resolved at runtime.

**agents** (`Record<string, Agent> | ({ requestContext: RequestContext }) => Record<string, Agent> | Promise<Record<string, Agent>>`): Subagents that the agent can access. Can be provided statically or resolved dynamically.

**tools** (`ToolsInput | ({ requestContext: RequestContext }) => ToolsInput | Promise<ToolsInput>`): Tools that the agent can access. Can be provided statically or resolved dynamically.

**transform** (`ToolPayloadTransformPolicy`): Shared policy for transforming tool payloads before display streams or user-visible transcript messages receive them. Use per-tool \`transform\` on \`createTool()\` for tool-local rules.

**notifications** (`{ deliveryPolicy?: NotificationDeliveryPolicyConfig }`): Notification delivery configuration for \`sendNotificationSignal()\`. \`deliveryPolicy\` can define \`decide\`, \`sources\`, \`priorities\`, or \`default\` rules that return \`deliver\`, \`queue\`, \`defer\`, \`summarize\`, \`persist\`, or \`discard\` decisions.

**workflows** (`Record<string, Workflow> | ({ requestContext: RequestContext }) => Record<string, Workflow> | Promise<Record<string, Workflow>>`): Workflows that the agent can execute. Can be static or dynamically resolved.

**defaultOptions** (`AgentExecutionOptions | ({ requestContext: RequestContext }) => AgentExecutionOptions | Promise<AgentExecutionOptions>`): Default options used when calling \`stream()\` and \`generate()\`.

**defaultGenerateOptionsLegacy** (`AgentGenerateOptions | ({ requestContext: RequestContext }) => AgentGenerateOptions | Promise<AgentGenerateOptions>`): Default options used when calling \`generateLegacy()\`.

**defaultStreamOptionsLegacy** (`AgentStreamOptions | ({ requestContext: RequestContext }) => AgentStreamOptions | Promise<AgentStreamOptions>`): Default options used when calling \`streamLegacy()\`.

**mastra** (`Mastra`): Reference to the Mastra runtime instance (injected automatically).

**scorers** (`MastraScorers | ({ requestContext: RequestContext }) => MastraScorers | Promise<MastraScorers>`): Scoring configuration for runtime evaluation and telemetry. Can be static or dynamically provided.

**memory** (`MastraMemory | ({ requestContext: RequestContext }) => MastraMemory | Promise<MastraMemory>`): Memory module used for storing and retrieving stateful context.

**voice** (`CompositeVoice`): Voice settings for speech input and output.

**inputProcessors** (`(Processor | ProcessorWorkflow)[] | ({ requestContext: RequestContext }) => (Processor | ProcessorWorkflow)[] | Promise<(Processor | ProcessorWorkflow)[]>`): Input processors that can modify or validate messages before they are processed by the agent. Can be individual Processor objects or workflows created with \`createWorkflow()\` using ProcessorStepSchema.

**outputProcessors** (`(Processor | ProcessorWorkflow)[] | ({ requestContext: RequestContext }) => (Processor | ProcessorWorkflow)[] | Promise<(Processor | ProcessorWorkflow)[]>`): Output processors that can modify or validate messages from the agent before they are sent to the client. Can be individual Processor objects or workflows.

**maxProcessorRetries** (`number`): Maximum number of times a processor can request retrying the LLM step.

**requestContextSchema** (`StandardJSONSchemaV1`): Standard JSON Schema for validating request context values. When provided, the context is validated at the start of generate() or stream(), throwing a MastraError if validation fails.

**editor** (`false | { instructions?: boolean; tools?: boolean | { description?: boolean } }`): Controls which fields the editor can override for this code-defined agent. Omit to allow editing instructions and tools. See Editor overrides below.

## Editor overrides

When you register the [`MastraEditor`](https://mastra.ai/reference/editor/mastra-editor), the `editor` field controls which parts of a code-defined agent can be changed through the editor. Fields owned by code are read-only in Studio and are stripped from saved overrides.

**editor** (`false | { instructions?: boolean; tools?: boolean | { description?: boolean } }`): Omit to allow editing instructions and tools. Set to \`false\` to lock the agent. Set \`instructions: true\` to allow instruction edits. Set \`tools: true\` to allow tool membership and description edits, or \`tools: { description: true }\` to allow only description edits.

The agent's `id`, `name`, and `model` always come from code and can't be overridden through the editor. See the [Editor overview](https://mastra.ai/docs/editor/overview) for usage.

## Returns

**agent** (`Agent<TAgentId, TTools>`): A new Agent instance with the specified configuration.