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.
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.
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
Env
Cloudflare.Env
default: "Cloudflare.Env"
Environment type containing bindings (KV, D1, R2, etc.)
State type to store within the Agent
Props
Record<string, unknown>
default: "Record<string, unknown>"
Props type passed to the Agent on creation
Properties
state
Current state of the Agent. Read-only. Use setState() to update. const count = this . state . count ;
initialState
Initial state for the Agent. Override to provide default state values. class MyAgent extends Agent < Env , { count : number }> {
initialState = { count: 0 };
}
name
The unique name/ID of this Agent instance (inherited from PartyServer).
env
The environment bindings for this Agent (KV, D1, R2, etc.).
ctx
The Durable Object context (storage, waitUntil, etc.).
mcp
MCP client manager for connecting to external MCP servers. await this . mcp . registerServer ( id , {
url: "https://mcp-server.example.com" ,
name: "My MCP Server"
});
observability
Observability implementation for emitting events. Defaults to genericObservability.
Static Options
options
Static configuration options for the Agent class. Override in subclasses. class SecureAgent extends Agent {
static options = {
hibernate: true ,
sendIdentityOnConnect: false ,
hungScheduleTimeoutSeconds: 60 ,
retry: {
maxAttempts: 5 ,
baseDelayMs: 200 ,
maxDelayMs: 5000
}
};
}
Show AgentStaticOptions fields
Whether the Agent should hibernate when inactive
Whether to send identity (name, agent) to clients on connect
hungScheduleTimeoutSeconds
Timeout in seconds before a running interval schedule is considered “hung” and force-reset
Default retry options for schedule(), queue(), and this.retry() Maximum number of retry attempts
Base delay in milliseconds for exponential backoff
Maximum delay cap in milliseconds
Methods
setState()
Update the Agent’s state. Persists to storage and broadcasts to all connected clients.
this . setState ({ count: this . state . count + 1 });
Throws an error if called from a readonly connection context.
sql()
query
TemplateStringsArray
required
SQL query template strings
values
(string | number | boolean | null)[]
Values to be inserted into the query
Execute SQL queries against the Agent’s database.
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.
Name of the method to call
Scheduling options Show ScheduleOptions variants
At a specific time: Data to pass to the callback
Retry options for this specific schedule
After a delay: Number of seconds to delay
Cron schedule: Cron expression (e.g., “0 0 * * *”)
Interval: Number of seconds between executions
// 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.
Name of the method to call
Data to pass to the callback
Retry options for this specific queue item
await this . queue ( "processUpload" , {
fileId: "abc123" ,
userId: "user-456"
});
Returns: Promise<void>
retry()
Retry an async operation with exponential backoff and jitter.
fn
(attempt: number) => Promise<T>
required
The async function to retry. Receives the current attempt number (1-indexed).
Retry configuration (falls back to static options) shouldRetry
(err: unknown, nextAttempt: number) => boolean
Predicate to determine if an error should be retried. Return false to stop immediately.
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().
Email subject (defaults to “Re: original subject”)
contentType
string
default: "text/plain"
MIME content type
Secret for signing agent headers (enables secure reply routing). Required if the email was routed via createSecureReplyEmailResolver.
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.
Name of the Workflow binding in env
Parameters to pass to the workflow
Unique workflow instance ID (auto-generated if not provided)
Custom metadata to store with the workflow
const instanceId = await this . runWorkflow ( "ProcessingWorkflow" , {
taskId: "task-123" ,
data: "input data"
});
Returns: Promise<string> - Workflow instance ID
getWorkflows()
Query tracked workflows.
Filter by workflow binding name
Filter by status (“queued”, “running”, “complete”, “errored”, etc.)
Maximum number of results
Number of results to skip
const page = await this . getWorkflows ({
status: "running" ,
limit: 10
});
Returns: Promise<WorkflowPage>
approveWorkflow()
Approve a workflow waiting for approval.
Metadata to pass to the workflow
await this . approveWorkflow ( instanceId , { approvedBy: "admin" });
rejectWorkflow()
Reject a workflow waiting for approval.
await this . rejectWorkflow ( instanceId , "Insufficient permissions" );
Lifecycle Hooks
onConnect()
The new WebSocket connection
ctx
ConnectionContext
required
Connection context (includes the upgrade request)
Called when a new WebSocket connection is established.
async onConnect ( connection : Connection , ctx : ConnectionContext ) {
const userId = new URL ( ctx . request . url ). searchParams . get ( "user" );
connection . setState ({ userId });
}
onMessage()
The connection that sent the message
message
string | ArrayBuffer
required
The message data
Called when a WebSocket message is received.
async onMessage ( connection : Connection , message : string | ArrayBuffer ) {
if ( typeof message === "string" ) {
const data = JSON . parse ( message );
// Handle custom message
}
}
onClose()
The connection that closed
Whether the close was clean
Called when a WebSocket connection closes.
async onClose ( connection : Connection , code : number , reason : string ) {
console . log ( `Connection ${ connection . id } closed: ${ reason } ` );
}
onRequest()
Called when an HTTP request is received.
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()
Props passed to the Agent on creation
Called when the Agent is created or wakes from hibernation.
async onStart ( props ?: Props ) {
// Initialize resources, restore state, etc.
}
onEmail()
The incoming email message
Called when an email is routed to this Agent via routeAgentEmail().
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()
state
State | undefined
required
The new state
source
Connection | 'server'
required
Source of the state update
Called after state has been persisted and broadcast. This is a notification hook—errors are routed to onError and do not affect persistence.
async onStateChanged ( state : State , source : Connection | "server" ) {
// Log state changes, trigger side effects, etc.
}
validateStateChange()
source
Connection | 'server'
required
Source of the state update
Called before state is persisted. Throw an error to reject the update. Must be synchronous.
validateStateChange ( nextState : State , source : Connection | "server" ) {
if ( source !== "server" && nextState . adminOnly ) {
throw new Error ( "Only server can set adminOnly fields" );
}
}
onWorkflowProgress()
event
WorkflowProgressCallback
required
Progress event from the workflow
Called when a tracked workflow reports progress.
async onWorkflowProgress ( event : WorkflowProgressCallback ) {
console . log ( `Workflow ${ event . workflowId } progress:` , event . progress );
}
onWorkflowComplete()
event
WorkflowCompleteCallback
required
Completion event from the workflow
Called when a tracked workflow completes.
async onWorkflowComplete ( event : WorkflowCompleteCallback ) {
console . log ( `Workflow ${ event . workflowId } completed:` , event . result );
}
onWorkflowError()
event
WorkflowErrorCallback
required
Error event from the workflow
Called when a tracked workflow errors.
async onWorkflowError ( event : WorkflowErrorCallback ) {
console . error ( `Workflow ${ event . workflowId } failed:` , event . error );
}
onError()
Called when an error occurs. Override to customize error handling.
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.
const connections = this . getConnections ();
for ( const conn of connections ) {
conn . send ( "broadcast message" );
}
Returns: Iterable<Connection>
broadcast()
message
string | ArrayBuffer
required
Message to broadcast
Connection IDs to exclude
Broadcast a message to all connected clients (optionally excluding some).
this . broadcast ( JSON . stringify ({ event: "update" , data }), [ sourceConnectionId ]);
setConnectionReadonly()
Whether the connection should be readonly
Mark a connection as readonly (cannot call setState).
this . setConnectionReadonly ( connection , true );
isConnectionReadonly()
Check if a connection is marked as readonly.
if ( this . isConnectionReadonly ( connection )) {
return new Response ( "Readonly connection" , { status: 403 });
}
Returns: boolean
shouldConnectionBeReadonly()
The connection being established
ctx
ConnectionContext
required
Connection context
Override to determine if a connection should be readonly on connect.
shouldConnectionBeReadonly ( connection : Connection , ctx : ConnectionContext ) {
const url = new URL ( ctx . request . url );
return url . searchParams . get ( "readonly" ) === "true" ;
}
Returns: boolean