{"id":261,"date":"2026-03-02T00:00:00","date_gmt":"2026-03-02T00:00:00","guid":{"rendered":"https:\/\/wordpress.securinsight.ca\/index.php\/2026\/03\/02\/agents-workers-agents-sdk-v0-7-0-observability-rewrite-keepalive-and-waitformcpconnections\/"},"modified":"2026-03-02T00:00:00","modified_gmt":"2026-03-02T00:00:00","slug":"agents-workers-agents-sdk-v0-7-0-observability-rewrite-keepalive-and-waitformcpconnections","status":"publish","type":"post","link":"https:\/\/wordpress.securinsight.ca\/index.php\/2026\/03\/02\/agents-workers-agents-sdk-v0-7-0-observability-rewrite-keepalive-and-waitformcpconnections\/","title":{"rendered":"Agents, Workers &#8211; Agents SDK v0.7.0: Observability rewrite, keepAlive, and waitForMcpConnections"},"content":{"rendered":"<p>The latest release of the <a href=\"https:\/\/github.com\/cloudflare\/agents\" target=\"_blank\">Agents SDK<\/a> rewrites observability from scratch with <code>diagnostics_channel<\/code>, adds <code>keepAlive()<\/code> to prevent Durable Object eviction during long-running work, and introduces <code>waitForMcpConnections<\/code> so MCP tools are always available when <code>onChatMessage<\/code> runs.<\/p>\n<h4>Observability rewrite<\/h4>\n<p>The previous observability system used <code>console.log()<\/code> with a custom <code>Observability.emit()<\/code> interface. v0.7.0 replaces it with structured events published to <a href=\"https:\/\/developers.cloudflare.com\/workers\/runtime-apis\/nodejs\/diagnostics-channel\/\">diagnostics channels<\/a> \u2014 silent by default, zero overhead when nobody is listening.<\/p>\n<p>Every event has a <code>type<\/code>, <code>payload<\/code>, and <code>timestamp<\/code>. Events are routed to seven named channels:<\/p>\n<table>\n<thead>\n<tr>\n<th>Channel<\/th>\n<th>Event types<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>agents:state<\/code><\/td>\n<td><code>state:update<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>agents:rpc<\/code><\/td>\n<td><code>rpc<\/code>, <code>rpc:error<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>agents:message<\/code><\/td>\n<td><code>message:request<\/code>, <code>message:response<\/code>, <code>message:clear<\/code>, <code>message:cancel<\/code>, <code>message:error<\/code>, <code>tool:result<\/code>, <code>tool:approval<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>agents:schedule<\/code><\/td>\n<td><code>schedule:create<\/code>, <code>schedule:execute<\/code>, <code>schedule:cancel<\/code>, <code>schedule:retry<\/code>, <code>schedule:error<\/code>, <code>queue:retry<\/code>, <code>queue:error<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>agents:lifecycle<\/code><\/td>\n<td><code>connect<\/code>, <code>destroy<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>agents:workflow<\/code><\/td>\n<td><code>workflow:start<\/code>, <code>workflow:event<\/code>, <code>workflow:approved<\/code>, <code>workflow:rejected<\/code>, <code>workflow:terminated<\/code>, <code>workflow:paused<\/code>, <code>workflow:resumed<\/code>, <code>workflow:restarted<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>agents:mcp<\/code><\/td>\n<td><code>mcp:client:preconnect<\/code>, <code>mcp:client:connect<\/code>, <code>mcp:client:authorize<\/code>, <code>mcp:client:discover<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Use the typed <code>subscribe()<\/code> helper from <code>agents\/observability<\/code> for type-safe access:<\/p>\n<ul>\n<li>\n<p>JavaScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"js\"><code class=\"language-js\"><div><div><span>import <\/span><span>{<\/span><span><span> <\/span><span>subscribe<\/span><span> <\/span><\/span><span>}<\/span><span> from <\/span><span>\"agents\/observability\"<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>const<\/span><span> <\/span><span>unsub<\/span><span> <\/span><span>=<\/span><span> <\/span><span>subscribe<\/span><span>(<\/span><span>\"rpc\"<\/span><span>,<\/span><span> <\/span><span>(<\/span><span>event<\/span><span>)<\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>if<\/span><span> (<\/span><span>event<\/span><span>.<\/span><span>type<\/span><span> <\/span><span>===<\/span><span> <\/span><span>\"rpc\"<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>console<\/span><span>.<\/span><span>log<\/span><span>(<\/span><span>`RPC call: <\/span><span>${<\/span><span>event<\/span><span>.<\/span><span>payload<\/span><span>.<\/span><span>method<\/span><span>}<\/span><span>`<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>}<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>if<\/span><span> (<\/span><span>event<\/span><span>.<\/span><span>type<\/span><span> <\/span><span>===<\/span><span> <\/span><span>\"rpc:error\"<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>console<\/span><span>.<\/span><span>error<\/span><span>(<\/span><\/div><\/div><div><div><span>      <\/span><span>`RPC failed: <\/span><span>${<\/span><span>event<\/span><span>.<\/span><span>payload<\/span><span>.<\/span><span>method<\/span><span>}<\/span><span> \u2014 <\/span><span>${<\/span><span>event<\/span><span>.<\/span><span>payload<\/span><span>.<\/span><span>error<\/span><span>}<\/span><span>`<\/span><span>,<\/span><\/div><\/div><div><div><span><span>    <\/span><\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>}<\/span><\/div><\/div><div><div><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>\/\/ Clean up when done<\/span><\/div><\/div><div><div><span>unsub<\/span><span>()<\/span><span>;<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<li>\n<p>TypeScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>import <\/span><span>{<\/span><span><span> <\/span><span>subscribe<\/span><span> <\/span><\/span><span>}<\/span><span> from <\/span><span>\"agents\/observability\"<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>const<\/span><span> <\/span><span>unsub<\/span><span> <\/span><span>=<\/span><span> <\/span><span>subscribe<\/span><span>(<\/span><span>\"rpc\"<\/span><span>,<\/span><span> <\/span><span>(<\/span><span>event<\/span><span>)<\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>if<\/span><span> (<\/span><span>event<\/span><span>.<\/span><span>type<\/span><span> <\/span><span>===<\/span><span> <\/span><span>\"rpc\"<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>console<\/span><span>.<\/span><span>log<\/span><span>(<\/span><span>`RPC call: <\/span><span>${<\/span><span>event<\/span><span>.<\/span><span>payload<\/span><span>.<\/span><span>method<\/span><span>}<\/span><span>`<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>}<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>if<\/span><span> (<\/span><span>event<\/span><span>.<\/span><span>type<\/span><span> <\/span><span>===<\/span><span> <\/span><span>\"rpc:error\"<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>console<\/span><span>.<\/span><span>error<\/span><span>(<\/span><\/div><\/div><div><div><span>      <\/span><span>`RPC failed: <\/span><span>${<\/span><span>event<\/span><span>.<\/span><span>payload<\/span><span>.<\/span><span>method<\/span><span>}<\/span><span> \u2014 <\/span><span>${<\/span><span>event<\/span><span>.<\/span><span>payload<\/span><span>.<\/span><span>error<\/span><span>}<\/span><span>`<\/span><span>,<\/span><\/div><\/div><div><div><span><span>    <\/span><\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>}<\/span><\/div><\/div><div><div><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>\/\/ Clean up when done<\/span><\/div><\/div><div><div><span>unsub<\/span><span>()<\/span><span>;<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<p>In production, all diagnostics channel messages are automatically forwarded to <a href=\"https:\/\/developers.cloudflare.com\/workers\/observability\/logs\/tail-workers\/\">Tail Workers<\/a> \u2014 no subscription code needed in the agent itself:<\/p>\n<ul>\n<li>\n<p>JavaScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"js\"><code class=\"language-js\"><div><div><span>export<\/span><span> <\/span><span>default<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>async<\/span><span> <\/span><span>tail<\/span><span>(<\/span><span>events<\/span><span>)<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>for<\/span><span> (<\/span><span>const<\/span><span> <\/span><span>event<\/span><span> <\/span><span>of<\/span><span> <\/span><span>events<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>      <\/span><span>for<\/span><span> (<\/span><span>const<\/span><span> <\/span><span>msg<\/span><span> <\/span><span>of<\/span><span> <\/span><span>event<\/span><span>.<\/span><span>diagnosticsChannelEvents<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>        <\/span><span>\/\/ msg.channel is \"agents:rpc\", \"agents:workflow\", etc.<\/span><\/div><\/div><div><div><span><span>        <\/span><\/span><span>console<\/span><span>.<\/span><span>log<\/span><span>(<\/span><span>msg<\/span><span>.<\/span><span>timestamp<\/span><span>,<\/span><span> <\/span><span>msg<\/span><span>.<\/span><span>channel<\/span><span>,<\/span><span> <\/span><span>msg<\/span><span>.<\/span><span>message<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>      <\/span><span>}<\/span><\/div><\/div><div><div><span>    <\/span><span>}<\/span><\/div><\/div><div><div><span>  <\/span><span>},<\/span><\/div><\/div><div><div><span>};<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<li>\n<p>TypeScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>export<\/span><span> <\/span><span>default<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>async<\/span><span> <\/span><span>tail<\/span><span>(<\/span><span>events<\/span><span>)<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>for<\/span><span> (<\/span><span>const<\/span><span> <\/span><span>event<\/span><span> <\/span><span>of<\/span><span> <\/span><span>events<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>      <\/span><span>for<\/span><span> (<\/span><span>const<\/span><span> <\/span><span>msg<\/span><span> <\/span><span>of<\/span><span> <\/span><span>event<\/span><span>.<\/span><span>diagnosticsChannelEvents<\/span><span>) <\/span><span>{<\/span><\/div><\/div><div><div><span>        <\/span><span>\/\/ msg.channel is \"agents:rpc\", \"agents:workflow\", etc.<\/span><\/div><\/div><div><div><span><span>        <\/span><\/span><span>console<\/span><span>.<\/span><span>log<\/span><span>(<\/span><span>msg<\/span><span>.<\/span><span>timestamp<\/span><span>,<\/span><span> <\/span><span>msg<\/span><span>.<\/span><span>channel<\/span><span>,<\/span><span> <\/span><span>msg<\/span><span>.<\/span><span>message<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>      <\/span><span>}<\/span><\/div><\/div><div><div><span>    <\/span><span>}<\/span><\/div><\/div><div><div><span>  <\/span><span>},<\/span><\/div><\/div><div><div><span>};<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<p>The custom <code>Observability<\/code> override interface is still supported for users who need to filter or forward events to external services.<\/p>\n<p>For the full event reference, refer to the <a href=\"https:\/\/developers.cloudflare.com\/agents\/api-reference\/observability\/\">Observability documentation<\/a>.<\/p>\n<h4><code>keepAlive()<\/code> and <code>keepAliveWhile()<\/code><\/h4>\n<p>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 \u2014 streaming LLM responses, waiting on external APIs, running multi-step computations \u2014 the agent can be evicted mid-flight.<\/p>\n<p><code>keepAlive()<\/code> 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.<\/p>\n<ul>\n<li>\n<p>JavaScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"js\"><code class=\"language-js\"><div><div><span>const<\/span><span> <\/span><span>dispose<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>this<\/span><span>.<\/span><span>keepAlive<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span>try<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>const<\/span><span> <\/span><span>result<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>longRunningComputation<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>await<\/span><span> <\/span><span>sendResults<\/span><span>(<\/span><span>result<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><span> <\/span><span>finally<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>dispose<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<li>\n<p>TypeScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>const<\/span><span> <\/span><span>dispose<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>this<\/span><span>.<\/span><span>keepAlive<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span>try<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>const<\/span><span> <\/span><span>result<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>longRunningComputation<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>await<\/span><span> <\/span><span>sendResults<\/span><span>(<\/span><span>result<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><span> <\/span><span>finally<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>dispose<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<p><code>keepAliveWhile()<\/code> wraps an async function with automatic cleanup \u2014 the heartbeat starts before the function runs and stops when it completes:<\/p>\n<ul>\n<li>\n<p>JavaScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"js\"><code class=\"language-js\"><div><div><span>const<\/span><span> <\/span><span>result<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>this<\/span><span>.<\/span><span>keepAliveWhile<\/span><span>(<\/span><span>async<\/span><span> <\/span><span>()<\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>const<\/span><span> <\/span><span>data<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>longRunningComputation<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>return<\/span><span> <\/span><span>data<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<li>\n<p>TypeScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>const<\/span><span> <\/span><span>result<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>this<\/span><span>.<\/span><span>keepAliveWhile<\/span><span>(<\/span><span>async<\/span><span> <\/span><span>()<\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>const<\/span><span> <\/span><span>data<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>longRunningComputation<\/span><span>()<\/span><span>;<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>return<\/span><span> <\/span><span>data<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<p>Key details:<\/p>\n<ul>\n<li><strong>Multiple concurrent callers<\/strong> \u2014 Each <code>keepAlive()<\/code> call returns an independent disposer. Disposing one does not affect others.<\/li>\n<li><strong>AIChatAgent built-in<\/strong> \u2014 <code>AIChatAgent<\/code> automatically calls <code>keepAlive()<\/code> during streaming responses. You do not need to add it yourself.<\/li>\n<li><strong>Uses the scheduling system<\/strong> \u2014 The heartbeat does not conflict with your own schedules. It shows up in <code>getSchedules()<\/code> if you need to inspect it.<\/li>\n<\/ul>\n<aside>\n<p>Note<\/p>\n<div>\n<p><code>keepAlive()<\/code> is marked <code>@experimental<\/code> and may change between releases.<\/p>\n<\/div>\n<\/aside>\n<p>For the full API reference and when-to-use guidance, refer to <a href=\"https:\/\/developers.cloudflare.com\/agents\/api-reference\/schedule-tasks\/#keeping-the-agent-alive\">Schedule tasks \u2014 Keeping the agent alive<\/a>.<\/p>\n<h4><code>waitForMcpConnections<\/code><\/h4>\n<p><code>AIChatAgent<\/code> now waits for MCP server connections to settle before calling <code>onChatMessage<\/code>. This ensures <code>this.mcp.getAITools()<\/code> returns the full set of tools, especially after Durable Object hibernation when connections are being restored in the background.<\/p>\n<ul>\n<li>\n<p>JavaScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"js\"><code class=\"language-js\"><div><div><span>export<\/span><span> <\/span><span>class<\/span><span> <\/span><span>ChatAgent<\/span><span> <\/span><span>extends<\/span><span> <\/span><span>AIChatAgent<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>\/\/ Default \u2014 waits up to 10 seconds<\/span><\/div><\/div><div><div><span>  <\/span><span>\/\/ waitForMcpConnections = { timeout: 10_000 };<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>  <\/span><span>\/\/ Wait forever<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>waitForMcpConnections <\/span><span>=<\/span><span> <\/span><span>true<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>  <\/span><span>\/\/ Disable waiting<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>waitForMcpConnections <\/span><span>=<\/span><span> <\/span><span>false<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<li>\n<p>TypeScript<\/p>\n<div>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>export<\/span><span> <\/span><span>class<\/span><span> <\/span><span>ChatAgent<\/span><span> <\/span><span>extends<\/span><span> <\/span><span>AIChatAgent<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>\/\/ Default \u2014 waits up to 10 seconds<\/span><\/div><\/div><div><div><span>  <\/span><span>\/\/ waitForMcpConnections = { timeout: 10_000 };<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>  <\/span><span>\/\/ Wait forever<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>waitForMcpConnections <\/span><span>=<\/span><span> <\/span><span>true<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>  <\/span><span>\/\/ Disable waiting<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>waitForMcpConnections <\/span><span>=<\/span><span> <\/span><span>false<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div><\/div>\n<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th>Value<\/th>\n<th>Behavior<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>{ timeout: 10_000 }<\/code><\/td>\n<td>Wait up to 10 seconds (default)<\/td>\n<\/tr>\n<tr>\n<td><code>{ timeout: N }<\/code><\/td>\n<td>Wait up to <code>N<\/code> milliseconds<\/td>\n<\/tr>\n<tr>\n<td><code>true<\/code><\/td>\n<td>Wait indefinitely until all connections ready<\/td>\n<\/tr>\n<tr>\n<td><code>false<\/code><\/td>\n<td>Do not wait (old behavior before 0.2.0)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For lower-level control, call <code>this.mcp.waitForConnections()<\/code> directly inside <code>onChatMessage<\/code> instead.<\/p>\n<h4>Other improvements<\/h4>\n<ul>\n<li><strong>MCP deduplication by name and URL<\/strong> \u2014 <code>addMcpServer<\/code> with 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).<\/li>\n<li><strong><code>callbackHost<\/code> optional for non-OAuth servers<\/strong> \u2014 <code>addMcpServer<\/code> no longer requires <code>callbackHost<\/code> when connecting to MCP servers that do not use OAuth.<\/li>\n<li><strong>MCP URL security<\/strong> \u2014 Server URLs are validated before connection to prevent SSRF. Private IP ranges, loopback addresses, link-local addresses, and cloud metadata endpoints are blocked.<\/li>\n<li><strong>Custom denial messages<\/strong> \u2014 <code>addToolOutput<\/code> now supports <code>state: \"output-error\"<\/code> with <code>errorText<\/code> for custom denial messages in human-in-the-loop tool approval flows.<\/li>\n<li><strong><code>requestId<\/code> in chat options<\/strong> \u2014 <code>onChatMessage<\/code> options now include a <code>requestId<\/code> for logging and correlating events.<\/li>\n<\/ul>\n<h4>Upgrade<\/h4>\n<p>To update to the latest version:<\/p>\n<div>\n<figure>\n<pre data-language=\"sh\"><code class=\"language-sh\"><div><div><span>npm<\/span><span> <\/span><span>i<\/span><span> <\/span><span>agents@latest<\/span><span> <\/span><span>@cloudflare\/ai-chat@latest<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-261","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/posts\/261","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/comments?post=261"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/posts\/261\/revisions"}],"wp:attachment":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/media?parent=261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/categories?post=261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/tags?post=261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}