Observability Rewrite: Structured Diagnostics Channels
The observability system has been rebuilt to use Node.js diagnostics channels instead of custom console.log() interfaces. Events are silent by default with zero overhead when nobody is listening, making this suitable for production use.
Every event carries a type, payload, and timestamp, routed across seven named channels:
- agents:state — State updates
- agents:rpc — RPC calls and errors
- agents:message — Chat requests, responses, and tool results
- agents:schedule — Task scheduling and queue events
- agents:lifecycle — Agent connection and lifecycle events
- agents:workflow — Workflow state transitions
- agents:mcp — MCP client lifecycle events
Use the typed subscribe() helper for type-safe event handling. In production, all diagnostics channel messages automatically forward to Tail Workers — no subscription code needed in the agent itself.
Preventing Durable Object Eviction with keepAlive()
Durable Objects are evicted after 70-140 seconds of inactivity. Long-running operations like streaming LLM responses or external API calls can trigger mid-flight eviction.
keepAlive() creates a 30-second heartbeat schedule that resets the inactivity timer. Returns a disposer function for cleanup:
const dispose = await this.keepAlive();
try {
const result = await longRunningComputation();
await sendResults(result);
} finally {
dispose();
}
keepAliveWhile() wraps an async function with automatic cleanup:
const result = await this.keepAliveWhile(async () => {
return await longRunningComputation();
});
Key points:
- Multiple concurrent calls return independent disposers
AIChatAgentautomatically applieskeepAlive()during streaming — manual addition not required- Heartbeats show up in
getSchedules()if you need inspection
MCP Connection Guarantees
AIChatAgent now waits for MCP server connections to settle before calling onChatMessage. This ensures this.mcp.getAITools() returns the full tool set, especially after Durable Object hibernation when connections restore in the background.
Configure via the waitForMcpConnections property:
- Default: Waits up to 10 seconds (
{ timeout: 10_000 }) - Disabled: Set to
falseto skip waiting - No timeout: Set to
truefor indefinite waiting