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

# Agent

> Base class for creating Agent implementations with state, RPC, scheduling, and email support

## Overview

The `Agent` class is the core building block for creating stateful agents on Cloudflare Workers. It extends PartyServer to provide WebSocket connections, state management, RPC methods, SQL storage, scheduling, email routing, MCP client support, and workflow integration.

```typescript theme={null}
import { Agent } from "agents";

class MyAgent extends Agent<Env, State> {
  initialState = { count: 0 };

  @callable()
  async increment() {
    this.setState({ count: this.state.count + 1 });
    return this.state.count;
  }
}
```

## Type Parameters

<ParamField path="Env" type="Cloudflare.Env" default="Cloudflare.Env">
  Environment type containing bindings (KV, D1, R2, etc.)
</ParamField>

<ParamField path="State" type="unknown" default="unknown">
  State type to store within the Agent
</ParamField>

<ParamField path="Props" type="Record<string, unknown>" default="Record<string, unknown>">
  Props type passed to the Agent on creation
</ParamField>

## Properties

### state

<ResponseField name="state" type="State" required>
  Current state of the Agent. Read-only. Use `setState()` to update.

  ```typescript theme={null}
  const count = this.state.count;
  ```
</ResponseField>

### initialState

<ResponseField name="initialState" type="State">
  Initial state for the Agent. Override to provide default state values.

  ```typescript theme={null}
  class MyAgent extends Agent<Env, { count: number }> {
    initialState = { count: 0 };
  }
  ```
</ResponseField>

### name

<ResponseField name="name" type="string" required>
  The unique name/ID of this Agent instance (inherited from PartyServer).
</ResponseField>

### env

<ResponseField name="env" type="Env" required>
  The environment bindings for this Agent (KV, D1, R2, etc.).
</ResponseField>

### ctx

<ResponseField name="ctx" type="AgentContext" required>
  The Durable Object context (storage, waitUntil, etc.).
</ResponseField>

### mcp

<ResponseField name="mcp" type="MCPClientManager" required>
  MCP client manager for connecting to external MCP servers.

  ```typescript theme={null}
  await this.mcp.registerServer(id, {
    url: "https://mcp-server.example.com",
    name: "My MCP Server"
  });
  ```
</ResponseField>

### observability

<ResponseField name="observability" type="Observability">
  Observability implementation for emitting events. Defaults to `genericObservability`.
</ResponseField>

## Static Options

### options

<ResponseField name="options" type="AgentStaticOptions">
  Static configuration options for the Agent class. Override in subclasses.

  ```typescript theme={null}
  class SecureAgent extends Agent {
    static options = {
      hibernate: true,
      sendIdentityOnConnect: false,
      hungScheduleTimeoutSeconds: 60,
      retry: {
        maxAttempts: 5,
        baseDelayMs: 200,
        maxDelayMs: 5000
      }
    };
  }
  ```
</ResponseField>

<Expandable title="AgentStaticOptions fields">
  <ParamField path="hibernate" type="boolean" default="true">
    Whether the Agent should hibernate when inactive
  </ParamField>

  <ParamField path="sendIdentityOnConnect" type="boolean" default="true">
    Whether to send identity (name, agent) to clients on connect
  </ParamField>

  <ParamField path="hungScheduleTimeoutSeconds" type="number" default="30">
    Timeout in seconds before a running interval schedule is considered "hung" and force-reset
  </ParamField>

  <ParamField path="retry" type="RetryOptions">
    Default retry options for schedule(), queue(), and this.retry()

    <Expandable title="RetryOptions fields">
      <ParamField path="maxAttempts" type="number" default="3">
        Maximum number of retry attempts
      </ParamField>

      <ParamField path="baseDelayMs" type="number" default="100">
        Base delay in milliseconds for exponential backoff
      </ParamField>

      <ParamField path="maxDelayMs" type="number" default="3000">
        Maximum delay cap in milliseconds
      </ParamField>
    </Expandable>
  </ParamField>
</Expandable>

## Methods

### setState()

<ParamField path="state" type="State" required>
  New state to set
</ParamField>

Update the Agent's state. Persists to storage and broadcasts to all connected clients.

```typescript theme={null}
this.setState({ count: this.state.count + 1 });
```

<Warning>
  Throws an error if called from a readonly connection context.
</Warning>

### sql()

<ParamField path="query" type="TemplateStringsArray" required>
  SQL query template strings
</ParamField>

<ParamField path="values" type="(string | number | boolean | null)[]">
  Values to be inserted into the query
</ParamField>

Execute SQL queries against the Agent's database.

```typescript theme={null}
const users = this.sql<{ id: number; name: string }>`
  SELECT * FROM users WHERE id = ${userId}
`;
```

**Returns:** `T[]` - Array of query results

**Throws:** `SqlError` - If the query fails

### schedule()

Schedule a callback to run at a future time or on a recurring interval.

<ParamField path="callback" type="keyof this" required>
  Name of the method to call
</ParamField>

<ParamField path="options" type="ScheduleOptions" required>
  Scheduling options

  <Expandable title="ScheduleOptions variants">
    **At a specific time:**

    <ParamField path="time" type="Date" required>
      Date/time to execute
    </ParamField>

    <ParamField path="payload" type="T">
      Data to pass to the callback
    </ParamField>

    <ParamField path="retry" type="RetryOptions">
      Retry options for this specific schedule
    </ParamField>

    **After a delay:**

    <ParamField path="delayInSeconds" type="number" required>
      Number of seconds to delay
    </ParamField>

    **Cron schedule:**

    <ParamField path="cron" type="string" required>
      Cron expression (e.g., "0 0 \* \* \*")
    </ParamField>

    **Interval:**

    <ParamField path="intervalSeconds" type="number" required>
      Number of seconds between executions
    </ParamField>
  </Expandable>
</ParamField>

```typescript theme={null}
// One-time scheduled task
await this.schedule("sendReminder", {
  time: new Date(Date.now() + 3600000),
  payload: { userId: "123" }
});

// Recurring cron task
await this.schedule("dailyBackup", {
  cron: "0 0 * * *",
  payload: { type: "full" }
});

// Interval task
await this.schedule("healthCheck", {
  intervalSeconds: 300
});
```

**Returns:** `Promise<string>` - Schedule ID

### queue()

Queue a callback for asynchronous execution.

<ParamField path="callback" type="keyof this" required>
  Name of the method to call
</ParamField>

<ParamField path="payload" type="T">
  Data to pass to the callback
</ParamField>

<ParamField path="retry" type="RetryOptions">
  Retry options for this specific queue item
</ParamField>

```typescript theme={null}
await this.queue("processUpload", {
  fileId: "abc123",
  userId: "user-456"
});
```

**Returns:** `Promise<void>`

### retry()

Retry an async operation with exponential backoff and jitter.

<ParamField path="fn" type="(attempt: number) => Promise<T>" required>
  The async function to retry. Receives the current attempt number (1-indexed).
</ParamField>

<ParamField path="options" type="RetryOptions">
  Retry configuration (falls back to static options)

  <ParamField path="shouldRetry" type="(err: unknown, nextAttempt: number) => boolean">
    Predicate to determine if an error should be retried. Return false to stop immediately.
  </ParamField>
</ParamField>

```typescript theme={null}
const result = await this.retry(
  async (attempt) => {
    return await fetchExternalAPI();
  },
  {
    maxAttempts: 5,
    shouldRetry: (err) => err instanceof NetworkError
  }
);
```

**Returns:** `Promise<T>` - The result of fn on success

**Throws:** The last error if all attempts fail or shouldRetry returns false

### replyToEmail()

Reply to an email received via routeAgentEmail().

<ParamField path="email" type="AgentEmail" required>
  The email to reply to
</ParamField>

<ParamField path="options" type="ReplyOptions" required>
  <ParamField path="fromName" type="string" required>
    Sender name
  </ParamField>

  <ParamField path="subject" type="string">
    Email subject (defaults to "Re: original subject")
  </ParamField>

  <ParamField path="body" type="string" required>
    Email body
  </ParamField>

  <ParamField path="contentType" type="string" default="text/plain">
    MIME content type
  </ParamField>

  <ParamField path="headers" type="Record<string, string>">
    Additional headers
  </ParamField>

  <ParamField path="secret" type="string | null">
    Secret for signing agent headers (enables secure reply routing). Required if the email was routed via createSecureReplyEmailResolver.
  </ParamField>
</ParamField>

```typescript theme={null}
await this.replyToEmail(email, {
  fromName: "Support Team",
  body: "Thank you for your message!",
  secret: this.env.EMAIL_SECRET
});
```

### runWorkflow()

Run a Workflow and track its execution.

<ParamField path="workflowName" type="string" required>
  Name of the Workflow binding in env
</ParamField>

<ParamField path="params" type="Params" required>
  Parameters to pass to the workflow
</ParamField>

<ParamField path="options" type="RunWorkflowOptions">
  <ParamField path="id" type="string">
    Unique workflow instance ID (auto-generated if not provided)
  </ParamField>

  <ParamField path="metadata" type="Record<string, unknown>">
    Custom metadata to store with the workflow
  </ParamField>
</ParamField>

```typescript theme={null}
const instanceId = await this.runWorkflow("ProcessingWorkflow", {
  taskId: "task-123",
  data: "input data"
});
```

**Returns:** `Promise<string>` - Workflow instance ID

### getWorkflows()

Query tracked workflows.

<ParamField path="criteria" type="WorkflowQueryCriteria">
  <ParamField path="workflowName" type="string">
    Filter by workflow binding name
  </ParamField>

  <ParamField path="status" type="WorkflowStatus">
    Filter by status ("queued", "running", "complete", "errored", etc.)
  </ParamField>

  <ParamField path="limit" type="number" default="100">
    Maximum number of results
  </ParamField>

  <ParamField path="offset" type="number" default="0">
    Number of results to skip
  </ParamField>
</ParamField>

```typescript theme={null}
const page = await this.getWorkflows({
  status: "running",
  limit: 10
});
```

**Returns:** `Promise<WorkflowPage>`

### approveWorkflow()

Approve a workflow waiting for approval.

<ParamField path="workflowId" type="string" required>
  Workflow instance ID
</ParamField>

<ParamField path="metadata" type="T">
  Metadata to pass to the workflow
</ParamField>

```typescript theme={null}
await this.approveWorkflow(instanceId, { approvedBy: "admin" });
```

### rejectWorkflow()

Reject a workflow waiting for approval.

<ParamField path="workflowId" type="string" required>
  Workflow instance ID
</ParamField>

<ParamField path="reason" type="string">
  Reason for rejection
</ParamField>

```typescript theme={null}
await this.rejectWorkflow(instanceId, "Insufficient permissions");
```

## Lifecycle Hooks

### onConnect()

<ParamField path="connection" type="Connection" required>
  The new WebSocket connection
</ParamField>

<ParamField path="ctx" type="ConnectionContext" required>
  Connection context (includes the upgrade request)
</ParamField>

Called when a new WebSocket connection is established.

```typescript theme={null}
async onConnect(connection: Connection, ctx: ConnectionContext) {
  const userId = new URL(ctx.request.url).searchParams.get("user");
  connection.setState({ userId });
}
```

### onMessage()

<ParamField path="connection" type="Connection" required>
  The connection that sent the message
</ParamField>

<ParamField path="message" type="string | ArrayBuffer" required>
  The message data
</ParamField>

Called when a WebSocket message is received.

```typescript theme={null}
async onMessage(connection: Connection, message: string | ArrayBuffer) {
  if (typeof message === "string") {
    const data = JSON.parse(message);
    // Handle custom message
  }
}
```

### onClose()

<ParamField path="connection" type="Connection" required>
  The connection that closed
</ParamField>

<ParamField path="code" type="number" required>
  WebSocket close code
</ParamField>

<ParamField path="reason" type="string" required>
  Close reason
</ParamField>

<ParamField path="wasClean" type="boolean" required>
  Whether the close was clean
</ParamField>

Called when a WebSocket connection closes.

```typescript theme={null}
async onClose(connection: Connection, code: number, reason: string) {
  console.log(`Connection ${connection.id} closed: ${reason}`);
}
```

### onRequest()

<ParamField path="request" type="Request" required>
  The HTTP request
</ParamField>

Called when an HTTP request is received.

```typescript theme={null}
async onRequest(request: Request) {
  if (request.method === "POST") {
    const data = await request.json();
    return new Response(JSON.stringify({ status: "ok" }));
  }
  return new Response("Method not allowed", { status: 405 });
}
```

**Returns:** `Response | Promise<Response>`

### onStart()

<ParamField path="props" type="Props">
  Props passed to the Agent on creation
</ParamField>

Called when the Agent is created or wakes from hibernation.

```typescript theme={null}
async onStart(props?: Props) {
  // Initialize resources, restore state, etc.
}
```

### onEmail()

<ParamField path="email" type="AgentEmail" required>
  The incoming email message
</ParamField>

Called when an email is routed to this Agent via routeAgentEmail().

```typescript theme={null}
async onEmail(email: AgentEmail) {
  const subject = email.headers.get("subject");
  await this.replyToEmail(email, {
    fromName: "Bot",
    body: `Received: ${subject}`,
    secret: this.env.EMAIL_SECRET
  });
}
```

### onStateChanged()

<ParamField path="state" type="State | undefined" required>
  The new state
</ParamField>

<ParamField path="source" type="Connection | 'server'" required>
  Source of the state update
</ParamField>

Called after state has been persisted and broadcast. This is a notification hook—errors are routed to onError and do not affect persistence.

```typescript theme={null}
async onStateChanged(state: State, source: Connection | "server") {
  // Log state changes, trigger side effects, etc.
}
```

### validateStateChange()

<ParamField path="nextState" type="State" required>
  The proposed new state
</ParamField>

<ParamField path="source" type="Connection | 'server'" required>
  Source of the state update
</ParamField>

Called **before** state is persisted. Throw an error to reject the update. Must be synchronous.

```typescript theme={null}
validateStateChange(nextState: State, source: Connection | "server") {
  if (source !== "server" && nextState.adminOnly) {
    throw new Error("Only server can set adminOnly fields");
  }
}
```

### onWorkflowProgress()

<ParamField path="event" type="WorkflowProgressCallback" required>
  Progress event from the workflow
</ParamField>

Called when a tracked workflow reports progress.

```typescript theme={null}
async onWorkflowProgress(event: WorkflowProgressCallback) {
  console.log(`Workflow ${event.workflowId} progress:`, event.progress);
}
```

### onWorkflowComplete()

<ParamField path="event" type="WorkflowCompleteCallback" required>
  Completion event from the workflow
</ParamField>

Called when a tracked workflow completes.

```typescript theme={null}
async onWorkflowComplete(event: WorkflowCompleteCallback) {
  console.log(`Workflow ${event.workflowId} completed:`, event.result);
}
```

### onWorkflowError()

<ParamField path="event" type="WorkflowErrorCallback" required>
  Error event from the workflow
</ParamField>

Called when a tracked workflow errors.

```typescript theme={null}
async onWorkflowError(event: WorkflowErrorCallback) {
  console.error(`Workflow ${event.workflowId} failed:`, event.error);
}
```

### onError()

Called when an error occurs. Override to customize error handling.

```typescript theme={null}
async onError(error: unknown) {
  console.error("Agent error:", error);
  // Don't throw to suppress the error, or re-throw to propagate
  throw error;
}
```

## Connection Management

### getConnections()

Get all active WebSocket connections.

```typescript theme={null}
const connections = this.getConnections();
for (const conn of connections) {
  conn.send("broadcast message");
}
```

**Returns:** `Iterable<Connection>`

### broadcast()

<ParamField path="message" type="string | ArrayBuffer" required>
  Message to broadcast
</ParamField>

<ParamField path="exclude" type="string[]">
  Connection IDs to exclude
</ParamField>

Broadcast a message to all connected clients (optionally excluding some).

```typescript theme={null}
this.broadcast(JSON.stringify({ event: "update", data }), [sourceConnectionId]);
```

### setConnectionReadonly()

<ParamField path="connection" type="Connection" required>
  The connection to mark
</ParamField>

<ParamField path="readonly" type="boolean" default="true">
  Whether the connection should be readonly
</ParamField>

Mark a connection as readonly (cannot call setState).

```typescript theme={null}
this.setConnectionReadonly(connection, true);
```

### isConnectionReadonly()

<ParamField path="connection" type="Connection" required>
  The connection to check
</ParamField>

Check if a connection is marked as readonly.

```typescript theme={null}
if (this.isConnectionReadonly(connection)) {
  return new Response("Readonly connection", { status: 403 });
}
```

**Returns:** `boolean`

### shouldConnectionBeReadonly()

<ParamField path="connection" type="Connection" required>
  The connection being established
</ParamField>

<ParamField path="ctx" type="ConnectionContext" required>
  Connection context
</ParamField>

Override to determine if a connection should be readonly on connect.

```typescript theme={null}
shouldConnectionBeReadonly(connection: Connection, ctx: ConnectionContext) {
  const url = new URL(ctx.request.url);
  return url.searchParams.get("readonly") === "true";
}
```

**Returns:** `boolean`

## Related

* [Routing](/api/routing) - Route requests to Agents
* [State Management](/api/state) - Manage Agent state
* [RPC with @callable](/api/callable) - Define callable methods
* [Scheduling](/api/scheduling) - Schedule recurring tasks
* [Workflows](/api/workflows) - Integrate with Cloudflare Workflows
* [Email Routing](/api/email) - Handle incoming emails
