The latest release of the Agents SDK ↗ brings first-class support for Cloudflare Workflows, synchronous state management, and new scheduling capabilities.
Agents excel at real-time communication and state management. Workflows excel at durable execution. Together, they enable powerful patterns where Agents handle WebSocket connections while Workflows handle long-running tasks, retries, and human-in-the-loop flows.
Use the new AgentWorkflow class to define workflows with typed access to your Agent:
import { AgentWorkflow } from "agents/workflows";
export class ProcessingWorkflow extends AgentWorkflow {
async run(event, step) {
// Call Agent methods via RPC
await this.agent.updateStatus(event.payload.taskId, "processing");
// Non-durable: progress reporting to clients
await this.reportProgress({ step: "process", percent: 0.5 });
this.broadcastToClients({ type: "update", taskId: event.payload.taskId });
// Durable via step: idempotent, won't repeat on retry
await step.mergeAgentState({ taskProgress: 0.5 });
const result = await step.do("process", async () => {
return processData(event.payload.data);
});
await step.reportComplete(result);
return result;
}
}
Start workflows from your Agent with runWorkflow() and handle lifecycle events:
export class MyAgent extends Agent {
async startTask(taskId, data) {
const instanceId = await this.runWorkflow("PROCESSING_WORKFLOW", {
taskId,
data,
});
return { instanceId };
}
async onWorkflowProgress(workflowName, instanceId, progress) {
this.broadcast(JSON.stringify({ type: "progress", progress }));
}
async onWorkflowComplete(workflowName, instanceId, result) {
console.log(`Workflow ${instanceId} completed`);
}
async onWorkflowError(workflowName, instanceId, error) {
console.error(`Workflow ${instanceId} failed:`, error);
}
}
Key workflow methods on your Agent:
runWorkflow(workflowName, params, options?) — Start a workflow with optional metadatagetWorkflow(workflowId) / getWorkflows(criteria?) — Query workflows with cursor-based paginationapproveWorkflow(workflowId) / rejectWorkflow(workflowId) — Human-in-the-loop approval flowspauseWorkflow(), resumeWorkflow(), terminateWorkflow() — Workflow controlState updates are now synchronous with a new validateStateChange() validation hook:
export class MyAgent extends Agent {
validateStateChange(oldState, newState) {
// Return false to reject the change
if (newState.count < 0) return false;
// Return modified state to transform
return { ...newState, lastUpdated: Date.now() };
}
}
The new scheduleEvery() method enables fixed-interval recurring tasks with built-in overlap prevention:
// Run every 5 minutes
await this.scheduleEvery("syncData", 5 * 60 * 1000, { source: "api" });
StreamingResponse.error(message) — Graceful stream error signalinggetCallableMethods() — Introspection API for discovering callable methodsawait agent.call("method", [args], {
timeout: 5000,
stream: { onChunk, onDone, onError },
});
Secure email reply routing — Email replies are now secured with HMAC-SHA256 signed headers, preventing unauthorized routing of emails to agent instances.
Routing improvements:
basePath option to bypass default URL construction for custom routingname and agent type on connectonIdentity and onIdentityChange callbacks on the clientconst agent = useAgent({
basePath: "user",
onIdentity: (name, agentType) => console.log(`Connected to ${name}`),
});
To update to the latest version:
npm i agents@latest
For the complete Workflows API reference and patterns, see Run Workflows.
The latest release of the Agents SDK ↗ brings first-class support for Cloudflare Workflows, synchronous state management, and new scheduling capabilities.
Agents excel at real-time communication and state management. Workflows excel at durable execution. Together, they enable powerful patterns where Agents handle WebSocket connections while Workflows handle long-running tasks, retries, and human-in-the-loop flows.
Use the new AgentWorkflow class to define workflows with typed access to your Agent:
import { AgentWorkflow } from "agents/workflows";
export class ProcessingWorkflow extends AgentWorkflow {
async run(event, step) {
// Call Agent methods via RPC
await this.agent.updateStatus(event.payload.taskId, "processing");
// Non-durable: progress reporting to clients
await this.reportProgress({ step: "process", percent: 0.5 });
this.broadcastToClients({ type: "update", taskId: event.payload.taskId });
// Durable via step: idempotent, won't repeat on retry
await step.mergeAgentState({ taskProgress: 0.5 });
const result = await step.do("process", async () => {
return processData(event.payload.data);
});
await step.reportComplete(result);
return result;
}
}
Start workflows from your Agent with runWorkflow() and handle lifecycle events:
export class MyAgent extends Agent {
async startTask(taskId, data) {
const instanceId = await this.runWorkflow("PROCESSING_WORKFLOW", {
taskId,
data,
});
return { instanceId };
}
async onWorkflowProgress(workflowName, instanceId, progress) {
this.broadcast(JSON.stringify({ type: "progress", progress }));
}
async onWorkflowComplete(workflowName, instanceId, result) {
console.log(`Workflow ${instanceId} completed`);
}
async onWorkflowError(workflowName, instanceId, error) {
console.error(`Workflow ${instanceId} failed:`, error);
}
}
Key workflow methods on your Agent:
runWorkflow(workflowName, params, options?) — Start a workflow with optional metadatagetWorkflow(workflowId) / getWorkflows(criteria?) — Query workflows with cursor-based paginationapproveWorkflow(workflowId) / rejectWorkflow(workflowId) — Human-in-the-loop approval flowspauseWorkflow(), resumeWorkflow(), terminateWorkflow() — Workflow controlState updates are now synchronous with a new validateStateChange() validation hook:
export class MyAgent extends Agent {
validateStateChange(oldState, newState) {
// Return false to reject the change
if (newState.count < 0) return false;
// Return modified state to transform
return { ...newState, lastUpdated: Date.now() };
}
}
The new scheduleEvery() method enables fixed-interval recurring tasks with built-in overlap prevention:
// Run every 5 minutes
await this.scheduleEvery("syncData", 5 * 60 * 1000, { source: "api" });
StreamingResponse.error(message) — Graceful stream error signalinggetCallableMethods() — Introspection API for discovering callable methodsawait agent.call("method", [args], {
timeout: 5000,
stream: { onChunk, onDone, onError },
});
Secure email reply routing — Email replies are now secured with HMAC-SHA256 signed headers, preventing unauthorized routing of emails to agent instances.
Routing improvements:
basePath option to bypass default URL construction for custom routingname and agent type on connectonIdentity and onIdentityChange callbacks on the clientconst agent = useAgent({
basePath: "user",
onIdentity: (name, agentType) => console.log(`Connected to ${name}`),
});
To update to the latest version:
npm i agents@latest
For the complete Workflows API reference and patterns, see Run Workflows.