---
title: Agents SDK v0.3.7: Workflows integration, synchronous state, and scheduleEvery()
description: The Agents SDK v0.3.7 introduces first-class Cloudflare Workflows integration, synchronous setState() with validation hooks, fixed-interval scheduling with scheduleEvery(), and callable system improvements.
image: https://edgetunnel-b2h.pages.dev/changelog-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://edgetunnel-b2h.pages.dev/changelog/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Changelog

New updates and improvements at Cloudflare.

[ Subscribe to RSS ](https://edgetunnel-b2h.pages.dev/changelog/rss/index.xml) [ View RSS feeds ](https://edgetunnel-b2h.pages.dev/fundamentals/new-features/available-rss-feeds/) 

![hero image](https://edgetunnel-b2h.pages.dev/_astro/hero.CVYJHPAd_26AMqX.svg) 

[ ← Back to all posts ](https://edgetunnel-b2h.pages.dev/changelog/) 

## Agents SDK v0.3.7: Workflows integration, synchronous state, and scheduleEvery()

Feb 03, 2026 

[ Agents ](https://edgetunnel-b2h.pages.dev/agents/)[ Workflows ](https://edgetunnel-b2h.pages.dev/workflows/) 

The latest release of the [Agents SDK ↗](https://github.com/cloudflare/agents) brings first-class support for [Cloudflare Workflows](https://edgetunnel-b2h.pages.dev/workflows/), synchronous state management, and new scheduling capabilities.

#### Cloudflare Workflows integration

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:

* [  JavaScript ](#tab-panel-2873)
* [  TypeScript ](#tab-panel-2874)

**JavaScript**

```js
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;
  }
}
```

**TypeScript**

```ts
import { AgentWorkflow } from "agents/workflows";
import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows";


export class ProcessingWorkflow extends AgentWorkflow<MyAgent, TaskParams> {
  async run(event: AgentWorkflowEvent<TaskParams>, step: AgentWorkflowStep) {
    // 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:

* [  JavaScript ](#tab-panel-2875)
* [  TypeScript ](#tab-panel-2876)

**JavaScript**

```js
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);
  }
}
```

**TypeScript**

```ts
export class MyAgent extends Agent {
  async startTask(taskId: string, data: string) {
    const instanceId = await this.runWorkflow("PROCESSING_WORKFLOW", {
      taskId,
      data,
    });
    return { instanceId };
  }


  async onWorkflowProgress(
    workflowName: string,
    instanceId: string,
    progress: unknown,
  ) {
    this.broadcast(JSON.stringify({ type: "progress", progress }));
  }


  async onWorkflowComplete(
    workflowName: string,
    instanceId: string,
    result?: unknown,
  ) {
    console.log(`Workflow ${instanceId} completed`);
  }


  async onWorkflowError(
    workflowName: string,
    instanceId: string,
    error: unknown,
  ) {
    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

#### Synchronous setState()

State updates are now synchronous with a new `validateStateChange()` validation hook:

* [  JavaScript ](#tab-panel-2867)
* [  TypeScript ](#tab-panel-2868)

**JavaScript**

```js
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() };
  }
}
```

**TypeScript**

```ts
export class MyAgent extends Agent<Env, State> {
  validateStateChange(oldState: State, newState: State): State | false {
    // Return false to reject the change
    if (newState.count < 0) return false;
    // Return modified state to transform
    return { ...newState, lastUpdated: Date.now() };
  }
}
```

#### scheduleEvery() for recurring tasks

The new `scheduleEvery()` method enables fixed-interval recurring tasks with built-in overlap prevention:

* [  JavaScript ](#tab-panel-2865)
* [  TypeScript ](#tab-panel-2866)

**JavaScript**

```js
// Run every 5 minutes
await this.scheduleEvery("syncData", 5 * 60 * 1000, { source: "api" });
```

**TypeScript**

```ts
// Run every 5 minutes
await this.scheduleEvery("syncData", 5 * 60 * 1000, { source: "api" });
```

#### Callable system improvements

* **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

* [  JavaScript ](#tab-panel-2869)
* [  TypeScript ](#tab-panel-2870)

**JavaScript**

```js
await agent.call("method", [args], {
  timeout: 5000,
  stream: { onChunk, onDone, onError },
});
```

**TypeScript**

```ts
await agent.call("method", [args], {
  timeout: 5000,
  stream: { onChunk, onDone, onError },
});
```

#### Email and routing enhancements

**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

* [  JavaScript ](#tab-panel-2871)
* [  TypeScript ](#tab-panel-2872)

**JavaScript**

```js
const agent = useAgent({
  basePath: "user",
  onIdentity: (name, agentType) => console.log(`Connected to ${name}`),
});
```

**TypeScript**

```ts
const agent = useAgent({
  basePath: "user",
  onIdentity: (name, agentType) => console.log(`Connected to ${name}`),
});
```

#### Upgrade

To update to the latest version:

```sh
npm i agents@latest
```

For the complete Workflows API reference and patterns, see [Run Workflows](https://edgetunnel-b2h.pages.dev/agents/runtime/execution/run-workflows/).

```json
{"@context":"https://schema.org","@type":"BlogPosting","@id":"https://edgetunnel-b2h.pages.dev/changelog/post/2026-02-03-agents-workflows-integration/#page","headline":"Agents SDK v0.3.7: Workflows integration, synchronous state, and scheduleEvery() · Changelog","description":"The Agents SDK v0.3.7 introduces first-class Cloudflare Workflows integration, synchronous setState() with validation hooks, fixed-interval scheduling with scheduleEvery(), and callable system improvements.","url":"https://edgetunnel-b2h.pages.dev/changelog/post/2026-02-03-agents-workflows-integration/","inLanguage":"en","image":"https://edgetunnel-b2h.pages.dev/changelog-preview.png","dateModified":"2026-02-03","datePublished":"2026-02-03","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://edgetunnel-b2h.pages.dev/#website","name":"Cloudflare Docs","url":"https://edgetunnel-b2h.pages.dev/"}}
```
