The latest release of the Agents SDK rewrites observability from scratch with diagnostics_channel, adds keepAlive() to prevent Durable Object eviction during long-running work, and introduces waitForMcpConnections so MCP tools are always available when onChatMessage runs.
Observability rewrite
The previous observability system used console.log() with a custom Observability.emit() interface. v0.7.0 replaces it with structured events published to diagnostics channels — silent by default, zero overhead when nobody is listening.
Every event has a type, payload, and timestamp. Events are routed to seven named channels:
| Channel | Event types |
|---|---|
agents:state | state:update |
agents:rpc | rpc, rpc:error |
agents:message | message:request, message:response, message:clear, message:cancel, message:error, tool:result, tool:approval |
agents:schedule | schedule:create, schedule:execute, schedule:cancel, schedule:retry, schedule:error, queue:retry, queue:error |
agents:lifecycle | connect, destroy |
agents:workflow | workflow:start, workflow:event, workflow:approved, workflow:rejected, workflow:terminated, workflow:paused, workflow:resumed, workflow:restarted |
agents:mcp | mcp:client:preconnect, mcp:client:connect, mcp:client:authorize, mcp:client:discover |
Use the typed subscribe() helper from agents/observability for type-safe access:
JavaScript
import { subscribe } from "agents/observability";const unsub = subscribe("rpc", (event) => {if (event.type === "rpc") {console.log(`RPC call: ${event.payload.method}`);}if (event.type === "rpc:error") {console.error(`RPC failed: ${event.payload.method} — ${event.payload.error}`,);}});// Clean up when doneunsub();TypeScript
import { subscribe } from "agents/observability";const unsub = subscribe("rpc", (event) => {if (event.type === "rpc") {console.log(`RPC call: ${event.payload.method}`);}if (event.type === "rpc:error") {console.error(`RPC failed: ${event.payload.method} — ${event.payload.error}`,);}});// Clean up when doneunsub();
In production, all diagnostics channel messages are automatically forwarded to Tail Workers — no subscription code needed in the agent itself:
JavaScript
export default {async tail(events) {for (const event of events) {for (const msg of event.diagnosticsChannelEvents) {// msg.channel is "agents:rpc", "agents:workflow", etc.console.log(msg.timestamp, msg.channel, msg.message);}}},};TypeScript
export default {async tail(events) {for (const event of events) {for (const msg of event.diagnosticsChannelEvents) {// msg.channel is "agents:rpc", "agents:workflow", etc.console.log(msg.timestamp, msg.channel, msg.message);}}},};
The custom Observability override interface is still supported for users who need to filter or forward events to external services.
For the full event reference, refer to the Observability documentation.
keepAlive() and keepAliveWhile()
Durable Objects are evicted after a period of inactivity (typically 70-140 seconds with no incoming requests, WebSocket messages, or alarms). During long-running operations — streaming LLM responses, waiting on external APIs, running multi-step computations — the agent can be evicted mid-flight.
keepAlive() prevents this by creating a 30-second heartbeat schedule. The alarm firing resets the inactivity timer. Returns a disposer function that cancels the heartbeat when called.
JavaScript
const dispose = await this.keepAlive();try {const result = await longRunningComputation();await sendResults(result);} finally {dispose();}TypeScript
const dispose = await this.keepAlive();try {const result = await longRunningComputation();await sendResults(result);} finally {dispose();}
keepAliveWhile() wraps an async function with automatic cleanup — the heartbeat starts before the function runs and stops when it completes:
JavaScript
const result = await this.keepAliveWhile(async () => {const data = await longRunningComputation();return data;});TypeScript
const result = await this.keepAliveWhile(async () => {const data = await longRunningComputation();return data;});
Key details:
- Multiple concurrent callers — Each
keepAlive()call returns an independent disposer. Disposing one does not affect others. - AIChatAgent built-in —
AIChatAgentautomatically callskeepAlive()during streaming responses. You do not need to add it yourself. - Uses the scheduling system — The heartbeat does not conflict with your own schedules. It shows up in
getSchedules()if you need to inspect it.
For the full API reference and when-to-use guidance, refer to Schedule tasks — Keeping the agent alive.
waitForMcpConnections
AIChatAgent now waits for MCP server connections to settle before calling onChatMessage. This ensures this.mcp.getAITools() returns the full set of tools, especially after Durable Object hibernation when connections are being restored in the background.
JavaScript
export class ChatAgent extends AIChatAgent {// Default — waits up to 10 seconds// waitForMcpConnections = { timeout: 10_000 };// Wait foreverwaitForMcpConnections = true;// Disable waitingwaitForMcpConnections = false;}TypeScript
export class ChatAgent extends AIChatAgent {// Default — waits up to 10 seconds// waitForMcpConnections = { timeout: 10_000 };// Wait foreverwaitForMcpConnections = true;// Disable waitingwaitForMcpConnections = false;}
| Value | Behavior |
|---|---|
{ timeout: 10_000 } | Wait up to 10 seconds (default) |
{ timeout: N } | Wait up to N milliseconds |
true | Wait indefinitely until all connections ready |
false | Do not wait (old behavior before 0.2.0) |
For lower-level control, call this.mcp.waitForConnections() directly inside onChatMessage instead.
Other improvements
- MCP deduplication by name and URL —
addMcpServerwith HTTP transport now deduplicates on both server name and URL. Calling it with the same name but a different URL creates a new connection. URLs are normalized before comparison (trailing slashes, default ports, hostname case). callbackHostoptional for non-OAuth servers —addMcpServerno longer requirescallbackHostwhen connecting to MCP servers that do not use OAuth.- MCP URL security — Server URLs are validated before connection to prevent SSRF. Private IP ranges, loopback addresses, link-local addresses, and cloud metadata endpoints are blocked.
- Custom denial messages —
addToolOutputnow supportsstate: "output-error"witherrorTextfor custom denial messages in human-in-the-loop tool approval flows. requestIdin chat options —onChatMessageoptions now include arequestIdfor logging and correlating events.
Upgrade
To update to the latest version:
npm i agents@latest @cloudflare/ai-chat@latestSource: Cloudflare
Latest Posts
- (Updated) SharePoint Framework domain isolated web parts retirement [MC792601]
![(Updated) SharePoint Framework domain isolated web parts retirement [MC792601] 2 pexels pachon in motion 426015731 16727556](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==)
- Dynamics 365 Customer Service- Generate AI-driven dynamic forecasts with intelligent method selection [MC1242602]
![Dynamics 365 Customer Service- Generate AI-driven dynamic forecasts with intelligent method selection [MC1242602] 3 pexels pachon in motion 426015731 18545020](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==)
- (Updated) Microsoft Teams admin center: New Teams External Collaboration Administrator role [MC1215071]
![(Updated) Microsoft Teams admin center: New Teams External Collaboration Administrator role [MC1215071] 4 pexels stasknop 1298601](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==)
- Microsoft Entra ID: General Availability of passkey profiles and migration for existing Passkeys (FIDO2) tenants [MC1221452]
![Microsoft Entra ID: General Availability of passkey profiles and migration for existing Passkeys (FIDO2) tenants [MC1221452] 5 pexels cottonbro 4268520](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==)

![(Updated) SharePoint Framework domain isolated web parts retirement [MC792601] 2 pexels pachon in motion 426015731 16727556](https://mwpro.co.uk/wp-content/uploads/2024/08/pexels-pachon-in-motion-426015731-16727556-150x150.webp)
![Dynamics 365 Customer Service- Generate AI-driven dynamic forecasts with intelligent method selection [MC1242602] 3 pexels pachon in motion 426015731 18545020](https://mwpro.co.uk/wp-content/uploads/2024/08/pexels-pachon-in-motion-426015731-18545020-150x150.webp)
![(Updated) Microsoft Teams admin center: New Teams External Collaboration Administrator role [MC1215071] 4 pexels stasknop 1298601](https://mwpro.co.uk/wp-content/uploads/2024/08/pexels-stasknop-1298601-150x150.webp)
![Microsoft Entra ID: General Availability of passkey profiles and migration for existing Passkeys (FIDO2) tenants [MC1221452] 5 pexels cottonbro 4268520](https://mwpro.co.uk/wp-content/uploads/2025/06/pexels-cottonbro-4268520-150x150.webp)
![(Updated) Microsoft 365 apps for Mac suite installer now includes the Microsoft 365 Copilot app [MC1230456] 7 (Updated) Microsoft 365 apps for Mac suite installer now includes the Microsoft 365 Copilot app [MC1230456]](https://mwpro.co.uk/wp-content/uploads/2024/08/pexels-jeshoots-234527-150x150.webp)