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 metadata
  • getWorkflow(workflowId) / getWorkflows(criteria?) — Query workflows with cursor-based pagination
  • approveWorkflow(workflowId) / rejectWorkflow(workflowId) — Human-in-the-loop approval flows
  • pauseWorkflow(), resumeWorkflow(), terminateWorkflow() — Workflow control

State 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" });

  • Client-side RPC timeout — Set timeouts on callable method invocations
  • StreamingResponse.error(message) — Graceful stream error signaling
  • getCallableMethods() — Introspection API for discovering callable methods
  • Connection close handling — Pending calls are automatically rejected on disconnect

await 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 routing
  • Server-sent identity — Agents send name and agent type on connect
  • New onIdentity and onIdentityChange callbacks on the client

const 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.