Skip to content

Commit 793fb67

Browse files
docs(agents): updates for agents 0.7.0 release (#28695)
* docs(agents): observability, MCP & scheduling updates Revise and expand agent docs: introduce structured observability (diagnostics channels, subscribe helper, Tail Workers) and provide an event reference; update MCP client docs with URL security rules, idempotency/URL normalization details, and this.mcp.waitForConnections(); add AI chat doc improvements (requestId in onChatMessage, waitForMcpConnections option, and addToolOutput for custom denial messages); add keepAlive() and keepAliveWhile() scheduling APIs and usage guidance; clarify transport deduplication rules and adjust a few state handler names in examples. Various table/link updates and examples included for clarity. * Fix broken Tail Workers links in observability docs Co-authored-by: threepointone <[email protected]> --------- Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com> Co-authored-by: threepointone <[email protected]>
1 parent 50032a2 commit 793fb67

8 files changed

Lines changed: 365 additions & 116 deletions

File tree

src/content/docs/agents/api-reference/agents-api.mdx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,21 @@ flowchart TD
7575

7676
## Server-side API reference
7777

78-
| Feature | Methods | Documentation |
79-
| --------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------- |
80-
| **State** | `setState()`, `onStateChanged()`, `initialState` | [Store and sync state](/agents/api-reference/store-and-sync-state/) |
81-
| **Callable methods** | `@callable()` decorator | [Callable methods](/agents/api-reference/callable-methods/) |
82-
| **Scheduling** | `schedule()`, `scheduleEvery()`, `getSchedules()`, `cancelSchedule()` | [Schedule tasks](/agents/api-reference/schedule-tasks/) |
83-
| **Queue** | `queue()`, `dequeue()`, `dequeueAll()`, `getQueue()` | [Queue tasks](/agents/api-reference/queue-tasks/) |
84-
| **WebSockets** | `onConnect()`, `onMessage()`, `onClose()`, `broadcast()` | [WebSockets](/agents/api-reference/websockets/) |
85-
| **HTTP/SSE** | `onRequest()` | [HTTP and SSE](/agents/api-reference/http-sse/) |
86-
| **Email** | `onEmail()`, `replyToEmail()` | [Email routing](/agents/api-reference/email/) |
87-
| **Workflows** | `runWorkflow()`, `waitForApproval()` | [Run Workflows](/agents/api-reference/run-workflows/) |
88-
| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/api-reference/mcp-client-api/) |
89-
| **AI Models** | Workers AI, OpenAI, Anthropic bindings | [Using AI models](/agents/api-reference/using-ai-models/) |
90-
| **Protocol messages** | `shouldSendProtocolMessages()`, `isConnectionProtocolEnabled()` | [Protocol messages](/agents/api-reference/protocol-messages/) |
91-
| **Context** | `getCurrentAgent()` | [getCurrentAgent()](/agents/api-reference/get-current-agent/) |
92-
| **Observability** | `observability.emit()` | [Observability](/agents/api-reference/observability/) |
78+
| Feature | Methods | Documentation |
79+
| --------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
80+
| **State** | `setState()`, `onStateChanged()`, `initialState` | [Store and sync state](/agents/api-reference/store-and-sync-state/) |
81+
| **Callable methods** | `@callable()` decorator | [Callable methods](/agents/api-reference/callable-methods/) |
82+
| **Scheduling** | `schedule()`, `scheduleEvery()`, `getSchedules()`, `cancelSchedule()`, `keepAlive()` | [Schedule tasks](/agents/api-reference/schedule-tasks/) |
83+
| **Queue** | `queue()`, `dequeue()`, `dequeueAll()`, `getQueue()` | [Queue tasks](/agents/api-reference/queue-tasks/) |
84+
| **WebSockets** | `onConnect()`, `onMessage()`, `onClose()`, `broadcast()` | [WebSockets](/agents/api-reference/websockets/) |
85+
| **HTTP/SSE** | `onRequest()` | [HTTP and SSE](/agents/api-reference/http-sse/) |
86+
| **Email** | `onEmail()`, `replyToEmail()` | [Email routing](/agents/api-reference/email/) |
87+
| **Workflows** | `runWorkflow()`, `waitForApproval()` | [Run Workflows](/agents/api-reference/run-workflows/) |
88+
| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/api-reference/mcp-client-api/) |
89+
| **AI Models** | Workers AI, OpenAI, Anthropic bindings | [Using AI models](/agents/api-reference/using-ai-models/) |
90+
| **Protocol messages** | `shouldSendProtocolMessages()`, `isConnectionProtocolEnabled()` | [Protocol messages](/agents/api-reference/protocol-messages/) |
91+
| **Context** | `getCurrentAgent()` | [getCurrentAgent()](/agents/api-reference/get-current-agent/) |
92+
| **Observability** | `subscribe()`, diagnostics channels, Tail Workers | [Observability](/agents/api-reference/observability/) |
9393

9494
## SQL API
9595

src/content/docs/agents/api-reference/chat-agents.mdx

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,17 @@ export class ChatAgent extends AIChatAgent {
213213
}
214214
```
215215

216-
**Accessing custom body data**:
216+
**Accessing custom body data and request ID**:
217217

218218
```ts
219219
export class ChatAgent extends AIChatAgent {
220220
async onChatMessage(_onFinish, options) {
221221
const { timezone, userId } = options?.body ?? {};
222222
// Use these values in your LLM call or business logic
223+
224+
// options.requestId — unique identifier for this chat request,
225+
// useful for logging and correlating events
226+
console.log("Request ID:", options?.requestId);
223227
}
224228
}
225229
```
@@ -269,6 +273,36 @@ export class ChatAgent extends AIChatAgent {
269273

270274
</TypeScriptExample>
271275

276+
### `waitForMcpConnections`
277+
278+
Controls whether `AIChatAgent` 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.
279+
280+
| Value | Behavior |
281+
| ---------------------- | --------------------------------------------- |
282+
| `{ timeout: 10_000 }` | Wait up to 10 seconds (default) |
283+
| `{ timeout: N }` | Wait up to `N` milliseconds |
284+
| `true` | Wait indefinitely until all connections ready |
285+
| `false` | Do not wait (old behavior before 0.2.0) |
286+
287+
<TypeScriptExample>
288+
289+
```ts
290+
export class ChatAgent extends AIChatAgent {
291+
// Default — waits up to 10 seconds
292+
// waitForMcpConnections = { timeout: 10_000 };
293+
294+
// Wait forever
295+
waitForMcpConnections = true;
296+
297+
// Disable waiting
298+
waitForMcpConnections = false;
299+
}
300+
```
301+
302+
</TypeScriptExample>
303+
304+
For lower-level control, call `this.mcp.waitForConnections()` directly inside your `onChatMessage` instead.
305+
272306
### `persistMessages` and `saveMessages`
273307

274308
For advanced cases, you can manually persist messages:
@@ -550,6 +584,29 @@ const { messages, addToolApprovalResponse } = useAgentChat({ agent });
550584
551585
</TypeScriptExample>
552586
587+
#### Custom denial messages with `addToolOutput`
588+
589+
When a user rejects a tool, `addToolApprovalResponse({ id, approved: false })` sets the tool state to `output-denied` with a generic message. To give the LLM a more specific reason for the denial, use `addToolOutput` with `state: "output-error"` instead:
590+
591+
<TypeScriptExample>
592+
593+
```ts
594+
const { addToolOutput } = useAgentChat({ agent });
595+
596+
// Reject with a custom error message
597+
addToolOutput({
598+
toolCallId: part.toolCallId,
599+
state: "output-error",
600+
errorText: "User declined: insufficient budget for this quarter",
601+
});
602+
```
603+
604+
</TypeScriptExample>
605+
606+
This sends a `tool_result` to the LLM with your custom error text, so it can respond appropriately (for example, suggest an alternative or ask clarifying questions).
607+
608+
`addToolApprovalResponse` (with `approved: false`) auto-continues the conversation when `autoContinueAfterToolResult` is enabled (the default). `addToolOutput` with `state: "output-error"` does **not** auto-continue — call `sendMessage()` afterward if you want the LLM to respond to the error.
609+
553610
For more patterns, refer to [Human-in-the-loop](/agents/concepts/human-in-the-loop/).
554611
555612
## Custom request data

src/content/docs/agents/api-reference/get-current-agent.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class MyAgent extends AIChatAgent {
8282

8383
### Built-in vs custom methods
8484

85-
- **Built-in methods** (`onRequest`, `onEmail`, `onStateUpdate`): Already have context.
85+
- **Built-in methods** (`onRequest`, `onEmail`, `onStateChanged`): Already have context.
8686
- **Custom methods** (your methods): Automatically wrapped during initialization.
8787
- **External functions**: Access context through `getCurrentAgent()`.
8888

src/content/docs/agents/api-reference/mcp-client-api.mdx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ Connections persist in the agent's [SQL storage](/agents/api-reference/store-and
6161

6262
## Adding MCP servers
6363

64-
Use `addMcpServer()` to connect to an MCP server:
64+
Use `addMcpServer()` to connect to an MCP server. For non-OAuth servers, no options are needed:
6565

6666
<TypeScriptExample>
6767

6868
```ts
69-
// Simple connection
69+
// Non-OAuth server — no options required
7070
await this.addMcpServer("notion", "https://mcp.notion.so/mcp");
7171

72-
// With explicit callback host
72+
// OAuth server — provide callbackHost for the OAuth redirect flow
7373
await this.addMcpServer("github", "https://mcp.github.com/mcp", {
7474
callbackHost: "https://my-worker.workers.dev",
7575
});
@@ -119,6 +119,17 @@ await this.addMcpServer("internal", "https://internal-mcp.example.com/mcp", {
119119

120120
</TypeScriptExample>
121121

122+
### URL security
123+
124+
MCP server URLs are validated before connection to prevent Server-Side Request Forgery (SSRF). The following URL targets are blocked:
125+
126+
- Private/internal IP ranges (RFC 1918: `10.x`, `172.16-31.x`, `192.168.x`)
127+
- Loopback addresses (`127.x`, `::1`)
128+
- Link-local addresses (`169.254.x`, `fe80::`)
129+
- Cloud metadata endpoints (`169.254.169.254`)
130+
131+
If you need to connect to an internal MCP server, use the [RPC transport](/agents/model-context-protocol/transport/) with a Durable Object binding instead of HTTP.
132+
122133
### Return value
123134

124135
`addMcpServer()` returns the connection state:
@@ -445,7 +456,13 @@ function Dashboard() {
445456

446457
### `addMcpServer()`
447458

448-
Add a connection to an MCP server and make its tools available to your agent. If `addMcpServer` is called with a `serverName` that already has an active connection, the existing connection is returned instead of creating a duplicate. This makes it safe to call in `onStart()` without worrying about duplicate connections on restart.
459+
Add a connection to an MCP server and make its tools available to your agent.
460+
461+
Calling `addMcpServer` is idempotent when both the server name **and** URL match an existing active connection — the existing connection is returned without creating a duplicate. This makes it safe to call in `onStart()` without worrying about duplicate connections on restart.
462+
463+
If you call `addMcpServer` with the same name but a **different** URL, a new connection is created. Both connections remain active and their tools are merged in `getAITools()`. To replace a server, call `removeMcpServer(oldId)` first.
464+
465+
URLs are normalized before comparison (trailing slashes, default ports, and hostname case are handled), so `https://MCP.Example.com` and `https://mcp.example.com/` are treated as the same URL.
449466

450467
```ts
451468
// HTTP transport (Streamable HTTP, SSE)
@@ -812,6 +829,22 @@ type MCPDiscoverResult = {
812829
}
813830
```
814831
832+
#### `this.mcp.waitForConnections()`
833+
834+
Wait for all in-flight MCP connection and discovery operations to settle. This is useful when you need `this.mcp.getAITools()` to return the full set of tools immediately after the agent wakes from hibernation.
835+
836+
```ts
837+
// Wait indefinitely
838+
await this.mcp.waitForConnections();
839+
840+
// Wait with a timeout (milliseconds)
841+
await this.mcp.waitForConnections({ timeout: 10_000 });
842+
```
843+
844+
:::note
845+
`AIChatAgent` calls this automatically via its [`waitForMcpConnections`](/agents/api-reference/chat-agents/#waitformcpconnections) property (defaults to `{ timeout: 10_000 }`). You only need `waitForConnections()` directly when using `Agent` with MCP, or when you want finer control inside `onChatMessage`.
846+
:::
847+
815848
#### `this.mcp.closeConnection()`
816849

817850
Close the connection to a specific server while keeping it registered.

0 commit comments

Comments
 (0)