From b996da4f54413a2f12ed53a3a0122c829c6283a8 Mon Sep 17 00:00:00 2001 From: Thomas Gauvin Date: Wed, 27 May 2026 17:40:03 -0400 Subject: [PATCH 1/5] [Agents] Restructure docs --- public/__redirects | 125 ++- src/components/AgentsPlatformDiagram.astro | 434 ++++++++++ src/components/index.ts | 1 + .../chat}/autonomous-responses.mdx | 10 +- .../chat}/chat-agents.mdx | 12 +- .../chat}/client-sdk.mdx | 8 +- .../chat}/index.mdx | 6 +- .../email.mdx | 8 +- .../agents/communication-channels/index.mdx | 14 + .../agents/communication-channels/slack.mdx | 486 +++++++++++ .../voice.mdx | 2 +- .../webhooks/index.mdx} | 6 +- .../webhooks}/push-notifications.mdx | 6 +- .../anthropic-agent-patterns.mdx | 4 +- .../docs/agents/concepts/calling-llms.mdx | 14 +- .../agents/concepts/human-in-the-loop.mdx | 617 +++++++++----- .../agents/concepts/long-running-agents.mdx | 24 +- src/content/docs/agents/concepts/memory.mdx | 10 +- .../docs/agents/{ => concepts}/patterns.mdx | 0 .../docs/agents/concepts/what-are-agents.mdx | 6 +- .../docs/agents/concepts/workflows.mdx | 2 +- .../docs/agents/examples/browser-agent.mdx | 411 ++++++++++ .../chat-agent.mdx} | 12 +- .../agents/examples/code-review-agent.mdx | 360 +++++++++ .../docs/agents/examples/document-agent.mdx | 104 +++ .../docs/agents/examples/email-agent.mdx | 763 ++++++++++++++++++ .../{api-reference => examples}/index.mdx | 6 +- .../docs/agents/examples/payment-agent.mdx | 64 ++ .../{guides => examples}/slack-agent.mdx | 10 +- .../voice-agent.mdx} | 10 +- .../add-to-existing-project.mdx | 16 +- .../docs/agents/getting-started/prompting.mdx | 9 - .../agents/getting-started/quick-start.mdx | 18 +- .../docs/agents/guides/human-in-the-loop.mdx | 554 ------------- src/content/docs/agents/harnesses/index.mdx | 55 ++ .../{api-reference => harnesses}/think.mdx | 22 +- src/content/docs/agents/index.mdx | 27 +- .../apis/agent-api.mdx} | 32 +- .../apis/client-api.mdx} | 22 +- .../apis/handler-api.mdx} | 20 +- src/content/docs/agents/mcp/apis/index.mdx | 12 + .../docs/agents/mcp/cloudflare/index.mdx | 12 + .../cloudflare}/mcp-portal.mdx | 0 .../cloudflare/servers-for-cloudflare.mdx} | 68 +- .../{ => mcp}/guides/build-mcp-client.mdx | 6 +- .../{ => mcp}/guides/connect-mcp-client.mdx | 6 +- .../docs/agents/{ => mcp}/guides/index.mdx | 2 +- .../{ => mcp}/guides/oauth-mcp-client.mdx | 4 +- .../{ => mcp}/guides/remote-mcp-server.mdx | 24 +- .../{ => mcp}/guides/securing-mcp-server.mdx | 4 +- .../guides/test-remote-mcp-server.mdx | 2 +- src/content/docs/agents/mcp/index.mdx | 14 + .../protocol}/authorization.mdx | 6 +- .../protocol}/codemode.mdx | 6 +- .../protocol}/governance.mdx | 4 +- .../docs/agents/mcp/protocol/index.mdx | 12 + .../protocol}/tools.mdx | 16 +- .../protocol}/transport.mdx | 16 +- .../agents/model-context-protocol/index.mdx | 38 - .../{platform/limits.mdx => platform.mdx} | 6 +- .../docs/agents/platform/prompt.txt.mdx | 9 - .../docs/agents/platform/prompting.mdx | 9 - .../{api-reference => runtime}/agents-api.mdx | 58 +- .../communication}/http-sse.mdx | 12 +- .../agents/runtime/communication/index.mdx | 12 + .../communication}/protocol-messages.mdx | 16 +- .../communication}/readonly-connections.mdx | 10 +- .../communication}/routing.mdx | 14 +- .../communication}/websockets.mdx | 14 +- .../execution}/durable-execution.mdx | 8 +- .../docs/agents/runtime/execution/index.mdx | 12 + .../execution}/queue-tasks.mdx | 14 +- .../execution}/retries.mdx | 6 +- .../execution}/run-workflows.mdx | 4 +- .../execution}/schedule-tasks.mdx | 12 +- .../execution}/sub-agents.mdx | 6 +- src/content/docs/agents/runtime/index.mdx | 14 + .../lifecycle}/agent-class.mdx | 10 +- .../lifecycle}/callable-methods.mdx | 6 +- .../lifecycle}/get-current-agent.mdx | 6 +- .../docs/agents/runtime/lifecycle/index.mdx | 12 + .../lifecycle}/sessions.mdx | 6 +- .../lifecycle/state.mdx} | 16 +- .../operations}/configuration.mdx | 8 +- .../cross-domain-authentication.mdx | 6 +- .../docs/agents/runtime/operations/index.mdx | 12 + .../operations}/observability.mdx | 4 +- .../operations}/using-ai-models.mdx | 8 +- .../browse-the-web.mdx => tools/browser.mdx} | 8 +- src/content/docs/agents/tools/index.mdx | 14 + .../payments}/index.mdx | 4 +- .../payments/mpp-charge-for-http-content.mdx} | 0 .../mpp/index.mdx => tools/payments/mpp.mdx} | 4 +- .../x402/charge-for-http-content.mdx | 2 +- .../payments}/x402/charge-for-mcp-tools.mdx | 6 +- .../payments}/x402/index.mdx | 8 +- .../payments}/x402/pay-from-agents-sdk.mdx | 6 +- .../payments}/x402/pay-with-tool-plugins.mdx | 6 +- .../agents/{api-reference => tools}/rag.mdx | 8 +- src/content/docs/agents/tools/sandbox.mdx | 125 +++ .../guides => workers/demos}/chatgpt-app.mdx | 6 +- 101 files changed, 3910 insertions(+), 1179 deletions(-) create mode 100644 src/components/AgentsPlatformDiagram.astro rename src/content/docs/agents/{guides => communication-channels/chat}/autonomous-responses.mdx (98%) rename src/content/docs/agents/{api-reference => communication-channels/chat}/chat-agents.mdx (98%) rename src/content/docs/agents/{api-reference => communication-channels/chat}/client-sdk.mdx (98%) rename src/content/docs/agents/{platform => communication-channels/chat}/index.mdx (68%) rename src/content/docs/agents/{api-reference => communication-channels}/email.mdx (99%) create mode 100644 src/content/docs/agents/communication-channels/index.mdx create mode 100644 src/content/docs/agents/communication-channels/slack.mdx rename src/content/docs/agents/{api-reference => communication-channels}/voice.mdx (99%) rename src/content/docs/agents/{guides/webhooks.mdx => communication-channels/webhooks/index.mdx} (99%) rename src/content/docs/agents/{guides => communication-channels/webhooks}/push-notifications.mdx (98%) rename src/content/docs/agents/{guides => concepts}/anthropic-agent-patterns.mdx (80%) rename src/content/docs/agents/{ => concepts}/patterns.mdx (100%) create mode 100644 src/content/docs/agents/examples/browser-agent.mdx rename src/content/docs/agents/{getting-started/build-a-chat-agent.mdx => examples/chat-agent.mdx} (97%) create mode 100644 src/content/docs/agents/examples/code-review-agent.mdx create mode 100644 src/content/docs/agents/examples/document-agent.mdx create mode 100644 src/content/docs/agents/examples/email-agent.mdx rename src/content/docs/agents/{api-reference => examples}/index.mdx (55%) create mode 100644 src/content/docs/agents/examples/payment-agent.mdx rename src/content/docs/agents/{guides => examples}/slack-agent.mdx (98%) rename src/content/docs/agents/{guides/build-a-voice-agent.mdx => examples/voice-agent.mdx} (97%) delete mode 100644 src/content/docs/agents/getting-started/prompting.mdx delete mode 100644 src/content/docs/agents/guides/human-in-the-loop.mdx create mode 100644 src/content/docs/agents/harnesses/index.mdx rename src/content/docs/agents/{api-reference => harnesses}/think.mdx (97%) rename src/content/docs/agents/{api-reference/mcp-agent-api.mdx => mcp/apis/agent-api.mdx} (89%) rename src/content/docs/agents/{api-reference/mcp-client-api.mdx => mcp/apis/client-api.mdx} (95%) rename src/content/docs/agents/{api-reference/mcp-handler-api.mdx => mcp/apis/handler-api.mdx} (91%) create mode 100644 src/content/docs/agents/mcp/apis/index.mdx create mode 100644 src/content/docs/agents/mcp/cloudflare/index.mdx rename src/content/docs/agents/{model-context-protocol => mcp/cloudflare}/mcp-portal.mdx (100%) rename src/content/docs/agents/{model-context-protocol/mcp-servers-for-cloudflare.mdx => mcp/cloudflare/servers-for-cloudflare.mdx} (77%) rename src/content/docs/agents/{ => mcp}/guides/build-mcp-client.mdx (54%) rename src/content/docs/agents/{ => mcp}/guides/connect-mcp-client.mdx (96%) rename src/content/docs/agents/{ => mcp}/guides/index.mdx (93%) rename src/content/docs/agents/{ => mcp}/guides/oauth-mcp-client.mdx (99%) rename src/content/docs/agents/{ => mcp}/guides/remote-mcp-server.mdx (89%) rename src/content/docs/agents/{ => mcp}/guides/securing-mcp-server.mdx (98%) rename src/content/docs/agents/{ => mcp}/guides/test-remote-mcp-server.mdx (97%) create mode 100644 src/content/docs/agents/mcp/index.mdx rename src/content/docs/agents/{model-context-protocol => mcp/protocol}/authorization.mdx (96%) rename src/content/docs/agents/{api-reference => mcp/protocol}/codemode.mdx (99%) rename src/content/docs/agents/{model-context-protocol => mcp/protocol}/governance.mdx (64%) create mode 100644 src/content/docs/agents/mcp/protocol/index.mdx rename src/content/docs/agents/{model-context-protocol => mcp/protocol}/tools.mdx (86%) rename src/content/docs/agents/{model-context-protocol => mcp/protocol}/transport.mdx (92%) delete mode 100644 src/content/docs/agents/model-context-protocol/index.mdx rename src/content/docs/agents/{platform/limits.mdx => platform.mdx} (93%) delete mode 100644 src/content/docs/agents/platform/prompt.txt.mdx delete mode 100644 src/content/docs/agents/platform/prompting.mdx rename src/content/docs/agents/{api-reference => runtime}/agents-api.mdx (83%) rename src/content/docs/agents/{api-reference => runtime/communication}/http-sse.mdx (92%) create mode 100644 src/content/docs/agents/runtime/communication/index.mdx rename src/content/docs/agents/{api-reference => runtime/communication}/protocol-messages.mdx (88%) rename src/content/docs/agents/{api-reference => runtime/communication}/readonly-connections.mdx (97%) rename src/content/docs/agents/{api-reference => runtime/communication}/routing.mdx (97%) rename src/content/docs/agents/{api-reference => runtime/communication}/websockets.mdx (97%) rename src/content/docs/agents/{api-reference => runtime/execution}/durable-execution.mdx (97%) create mode 100644 src/content/docs/agents/runtime/execution/index.mdx rename src/content/docs/agents/{api-reference => runtime/execution}/queue-tasks.mdx (94%) rename src/content/docs/agents/{api-reference => runtime/execution}/retries.mdx (98%) rename src/content/docs/agents/{api-reference => runtime/execution}/run-workflows.mdx (99%) rename src/content/docs/agents/{api-reference => runtime/execution}/schedule-tasks.mdx (98%) rename src/content/docs/agents/{api-reference => runtime/execution}/sub-agents.mdx (96%) create mode 100644 src/content/docs/agents/runtime/index.mdx rename src/content/docs/agents/{concepts => runtime/lifecycle}/agent-class.mdx (96%) rename src/content/docs/agents/{api-reference => runtime/lifecycle}/callable-methods.mdx (99%) rename src/content/docs/agents/{api-reference => runtime/lifecycle}/get-current-agent.mdx (98%) create mode 100644 src/content/docs/agents/runtime/lifecycle/index.mdx rename src/content/docs/agents/{api-reference => runtime/lifecycle}/sessions.mdx (98%) rename src/content/docs/agents/{api-reference/store-and-sync-state.mdx => runtime/lifecycle/state.mdx} (95%) rename src/content/docs/agents/{api-reference => runtime/operations}/configuration.mdx (98%) rename src/content/docs/agents/{guides => runtime/operations}/cross-domain-authentication.mdx (98%) create mode 100644 src/content/docs/agents/runtime/operations/index.mdx rename src/content/docs/agents/{api-reference => runtime/operations}/observability.mdx (99%) rename src/content/docs/agents/{api-reference => runtime/operations}/using-ai-models.mdx (92%) rename src/content/docs/agents/{api-reference/browse-the-web.mdx => tools/browser.mdx} (97%) create mode 100644 src/content/docs/agents/tools/index.mdx rename src/content/docs/agents/{agentic-payments => tools/payments}/index.mdx (96%) rename src/content/docs/agents/{agentic-payments/mpp/charge-for-http-content.mdx => tools/payments/mpp-charge-for-http-content.mdx} (100%) rename src/content/docs/agents/{agentic-payments/mpp/index.mdx => tools/payments/mpp.mdx} (93%) rename src/content/docs/agents/{agentic-payments => tools/payments}/x402/charge-for-http-content.mdx (95%) rename src/content/docs/agents/{agentic-payments => tools/payments}/x402/charge-for-mcp-tools.mdx (89%) rename src/content/docs/agents/{agentic-payments => tools/payments}/x402/index.mdx (95%) rename src/content/docs/agents/{agentic-payments => tools/payments}/x402/pay-from-agents-sdk.mdx (82%) rename src/content/docs/agents/{agentic-payments => tools/payments}/x402/pay-with-tool-plugins.mdx (93%) rename src/content/docs/agents/{api-reference => tools}/rag.mdx (78%) create mode 100644 src/content/docs/agents/tools/sandbox.mdx rename src/content/docs/{agents/guides => workers/demos}/chatgpt-app.mdx (99%) diff --git a/public/__redirects b/public/__redirects index 7382c12e6314881..c3fea4aed54c6cf 100644 --- a/public/__redirects +++ b/public/__redirects @@ -179,23 +179,112 @@ # agents /agents/build/prompts/ /workers/get-started/prompting/ 301 -/agents/examples/browse-the-web/ /agents/api-reference/browse-the-web/ 301 -/agents/examples/manage-and-sync-state/ /agents/api-reference/store-and-sync-state/ 301 -/agents/examples/rag/ /agents/api-reference/rag/ 301 -/agents/examples/run-workflows/ /agents/api-reference/run-workflows/ 301 -/agents/examples/schedule-tasks/ /agents/api-reference/schedule-tasks/ 301 -/agents/examples/using-ai-models/ /agents/api-reference/using-ai-models/ 301 -/agents/examples/websockets/ /agents/api-reference/websockets/ 301 -/agents/examples/sdk/ /agents/api-reference/agents-api/ 301 -/agents/examples/build-mcp-server/ /agents/guides/remote-mcp-server/ 301 -/agents/api-reference/build-mcp-server/ /agents/guides/remote-mcp-server/ 301 -/agents/api-reference/sdk/ /agents/api-reference/ 301 -/agents/guides/build-mcp-server/ /agents/guides/remote-mcp-server/ 301 -/agents/capabilities/mcp-server/ /agents/model-context-protocol/ 301 -/agents/model-context-protocol/mcp-agent-api/ /agents/api-reference/mcp-agent-api/ 301 -/agents/model-context-protocol/mcp-client-api/ /agents/api-reference/mcp-client-api/ 301 -/agents/model-context-protocol/mcp-handler-api/ /agents/api-reference/mcp-handler-api/ 301 -/agents/api-reference/calling-agents/ /agents/api-reference/routing/ 301 +/agents/getting-started/build-a-chat-agent/ /agents/examples/chat-agent/ 301 +/agents/examples/browse-the-web/ /agents/tools/browser/ 301 +/agents/examples/manage-and-sync-state/ /agents/runtime/lifecycle/state/ 301 +/agents/examples/rag/ /agents/tools/rag/ 301 +/agents/examples/run-workflows/ /agents/runtime/execution/run-workflows/ 301 +/agents/examples/schedule-tasks/ /agents/runtime/execution/schedule-tasks/ 301 +/agents/examples/using-ai-models/ /agents/runtime/operations/using-ai-models/ 301 +/agents/examples/websockets/ /agents/runtime/communication/websockets/ 301 +/agents/examples/sdk/ /agents/runtime/agents-api/ 301 +/agents/examples/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/api-reference/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/api-reference/sdk/ /agents/runtime/agents-api/ 301 +/agents/guides/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/capabilities/mcp-server/ /agents/mcp/ 301 +/agents/model-context-protocol/mcp-agent-api/ /agents/mcp/apis/agent-api/ 301 +/agents/model-context-protocol/mcp-client-api/ /agents/mcp/apis/client-api/ 301 +/agents/model-context-protocol/mcp-handler-api/ /agents/mcp/apis/handler-api/ 301 +/agents/api-reference/calling-agents/ /agents/runtime/communication/routing/ 301 +/agents/community-mcp-server/ /agents/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 +/agents/patterns/ /agents/concepts/patterns/ 301 +/agents/api-reference/agents-api/ /agents/runtime/agents-api/ 301 +/agents/api-reference/browse-the-web/ /agents/tools/browser/ 301 +/agents/api-reference/callable-methods/ /agents/runtime/lifecycle/callable-methods/ 301 +/agents/api-reference/chat-agents/ /agents/communication-channels/chat/chat-agents/ 301 +/agents/api-reference/client-sdk/ /agents/communication-channels/chat/client-sdk/ 301 +/agents/api-reference/codemode/ /agents/mcp/protocol/codemode/ 301 +/agents/api-reference/configuration/ /agents/runtime/operations/configuration/ 301 +/agents/api-reference/durable-execution/ /agents/runtime/execution/durable-execution/ 301 +/agents/api-reference/email/ /agents/communication-channels/email/ 301 +/agents/api-reference/get-current-agent/ /agents/runtime/lifecycle/get-current-agent/ 301 +/agents/api-reference/http-sse/ /agents/runtime/communication/http-sse/ 301 +/agents/api-reference/mcp-agent-api/ /agents/mcp/apis/agent-api/ 301 +/agents/api-reference/mcp-client-api/ /agents/mcp/apis/client-api/ 301 +/agents/api-reference/mcp-handler-api/ /agents/mcp/apis/handler-api/ 301 +/agents/api-reference/observability/ /agents/runtime/operations/observability/ 301 +/agents/api-reference/protocol-messages/ /agents/runtime/communication/protocol-messages/ 301 +/agents/api-reference/queue-tasks/ /agents/runtime/execution/queue-tasks/ 301 +/agents/api-reference/rag/ /agents/tools/rag/ 301 +/agents/api-reference/readonly-connections/ /agents/runtime/communication/readonly-connections/ 301 +/agents/api-reference/retries/ /agents/runtime/execution/retries/ 301 +/agents/api-reference/routing/ /agents/runtime/communication/routing/ 301 +/agents/api-reference/run-workflows/ /agents/runtime/execution/run-workflows/ 301 +/agents/api-reference/schedule-tasks/ /agents/runtime/execution/schedule-tasks/ 301 +/agents/api-reference/sessions/ /agents/runtime/lifecycle/sessions/ 301 +/agents/api-reference/store-and-sync-state/ /agents/runtime/lifecycle/state/ 301 +/agents/api-reference/sub-agents/ /agents/runtime/execution/sub-agents/ 301 +/agents/api-reference/think/ /agents/harnesses/think/ 301 +/agents/api-reference/using-ai-models/ /agents/runtime/operations/using-ai-models/ 301 +/agents/api-reference/voice/ /agents/communication-channels/voice/ 301 +/agents/api-reference/websockets/ /agents/runtime/communication/websockets/ 301 +/agents/guides/anthropic-agent-patterns/ /agents/concepts/anthropic-agent-patterns/ 301 +/agents/guides/autonomous-responses/ /agents/communication-channels/chat/autonomous-responses/ 301 +/agents/guides/build-a-voice-agent/ /agents/examples/voice-agent/ 301 +/agents/guides/build-mcp-client/ /agents/mcp/guides/build-mcp-client/ 301 +/agents/guides/chatgpt-app/ /workers/demos/chatgpt-app/ 301 +/agents/communication-channels/chat/chatgpt-app/ /workers/demos/chatgpt-app/ 301 +/agents/guides/connect-mcp-client/ /agents/mcp/guides/connect-mcp-client/ 301 +/agents/guides/cross-domain-authentication/ /agents/runtime/operations/cross-domain-authentication/ 301 +/agents/guides/human-in-the-loop/ /agents/concepts/human-in-the-loop/ 301 +/agents/guides/oauth-mcp-client/ /agents/mcp/guides/oauth-mcp-client/ 301 +/agents/guides/push-notifications/ /agents/communication-channels/webhooks/push-notifications/ 301 +/agents/guides/remote-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/guides/securing-mcp-server/ /agents/mcp/guides/securing-mcp-server/ 301 +/agents/guides/slack-agent/ /agents/examples/slack-agent/ 301 +/agents/guides/test-remote-mcp-server/ /agents/mcp/guides/test-remote-mcp-server/ 301 +/agents/guides/webhooks/ /agents/communication-channels/webhooks/webhooks/ 301 +/agents/model-context-protocol/authorization/ /agents/mcp/protocol/authorization/ 301 +/agents/model-context-protocol/governance/ /agents/mcp/protocol/governance/ 301 +/agents/model-context-protocol/mcp-portal/ /agents/mcp/cloudflare/mcp-portal/ 301 +/agents/model-context-protocol/mcp-servers-for-cloudflare/ /agents/mcp/cloudflare/servers-for-cloudflare/ 301 +/agents/model-context-protocol/mcp-servers-for-cloudflare/community-mcp-server/ /agents/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 +/agents/model-context-protocol/tools/ /agents/mcp/protocol/tools/ 301 +/agents/model-context-protocol/transport/ /agents/mcp/protocol/transport/ 301 +/agents/agentic-payments/ /agents/tools/payments/ 301 +/agents/agentic-payments/x402/ /agents/tools/payments/x402/ 301 +/agents/agentic-payments/mpp/ /agents/tools/payments/mpp/ 301 +/agents/concepts/agent-class/ /agents/runtime/lifecycle/agent-class/ 301 +/agents/getting-started/prompting/ /workers/get-started/prompting/ 301 +/agents/platform/prompting/ /workers/get-started/prompting/ 301 +/agents/platform/prompt.txt/ /workers/prompt.txt 301 +/agents/channels/chat/ /agents/communication-channels/chat/ 301 +/agents/channels/chat/chat-agents/ /agents/communication-channels/chat/chat-agents/ 301 +/agents/channels/chat/client-sdk/ /agents/communication-channels/chat/client-sdk/ 301 +/agents/channels/chat/autonomous-responses/ /agents/communication-channels/chat/autonomous-responses/ 301 +/agents/channels/chat/chatgpt-app/ /agents/communication-channels/chat/chatgpt-app/ 301 +/agents/channels/voice/ /agents/communication-channels/voice/ 301 +/agents/channels/voice/voice/ /agents/communication-channels/voice/ 301 +/agents/channels/voice/build-a-voice-agent/ /agents/examples/voice-agent/ 301 +/agents/channels/email/ /agents/communication-channels/email/ 301 +/agents/channels/email/email/ /agents/communication-channels/email/ 301 +/agents/channels/slack/ /agents/communication-channels/slack/ 301 +/agents/channels/slack/slack-agent/ /agents/examples/slack-agent/ 301 +/agents/channels/webhooks/ /agents/communication-channels/webhooks/ 301 +/agents/channels/webhooks/webhooks/ /agents/communication-channels/webhooks/webhooks/ 301 +/agents/channels/webhooks/push-notifications/ /agents/communication-channels/webhooks/push-notifications/ 301 +/agents/communication-channels/voice/voice/ /agents/communication-channels/voice/ 301 +/agents/communication-channels/voice/build-a-voice-agent/ /agents/examples/voice-agent/ 301 +/agents/communication-channels/email/email/ /agents/communication-channels/email/ 301 +/agents/communication-channels/slack/slack-agent/ /agents/examples/slack-agent/ 301 +/agents/tools/browser/browse-the-web/ /agents/tools/browser/ 301 +/agents/tools/rag/rag/ /agents/tools/rag/ 301 +/agents/tools/sandbox/codemode/ /agents/mcp/protocol/codemode/ 301 +/agents/harnesses/ /agents/harnesses/think/ 301 +/agents/platform/limits/ /agents/platform/ 301 +/agents/tools/payments/mpp/charge-for-http-content/ /agents/tools/payments/mpp-charge-for-http-content/ 301 +/agents/agentic-payments/mpp/charge-for-http-content/ /agents/tools/payments/mpp-charge-for-http-content/ 301 # ai-audit /ai-audit/features/detect-ai-crawlers/ /ai-crawl-control/features/analyze-ai-crawlers/ 301 @@ -2774,7 +2863,7 @@ /cloudflare-one/team-and-resources/devices/warp/* /cloudflare-one/team-and-resources/devices/cloudflare-one-client/:splat 301 # Agents x402 (moved under agentic-payments) -/agents/x402/* /agents/agentic-payments/x402/:splat 301 +/agents/x402/* /agents/tools/payments/x402/:splat 301 # AI Gateway models (unified under /ai/models/) /ai-gateway/models/* /ai/models/:splat 301 diff --git a/src/components/AgentsPlatformDiagram.astro b/src/components/AgentsPlatformDiagram.astro new file mode 100644 index 000000000000000..01a174313f40276 --- /dev/null +++ b/src/components/AgentsPlatformDiagram.astro @@ -0,0 +1,434 @@ +--- +const channels = [ + { type: "Chat", name: "AIChatAgent", href: "/agents/communication-channels/chat/" }, + { type: "Email", name: "onEmail", href: "/agents/communication-channels/email/" }, + { type: "Voice", name: "withVoice", href: "/agents/communication-channels/voice/" }, + { type: "Slack", name: "Events", href: "/agents/communication-channels/slack/" }, + { type: "Webhook", name: "HTTP", href: "/agents/communication-channels/webhooks/" }, +]; + +const runtime = [ + { label: "State", href: "/agents/runtime/lifecycle/state/" }, + { label: "Sessions", href: "/agents/runtime/lifecycle/sessions/" }, + { label: "Routing", href: "/agents/runtime/communication/routing/" }, + { label: "WebSockets", href: "/agents/runtime/communication/websockets/" }, + { label: "Scheduling", href: "/agents/runtime/execution/schedule-tasks/" }, + { label: "Fibers", href: "/agents/runtime/execution/durable-execution/" }, +]; + +const tools = [ + { type: "Browser", name: "CDP", href: "/agents/tools/browser/" }, + { type: "Sandbox", name: "Linux", href: "/agents/tools/sandbox/" }, + { type: "AI Search", name: "RAG", href: "/agents/tools/rag/" }, + { type: "MCP", name: "Servers", href: "/agents/mcp/" }, + { type: "Payments", name: "x402 · MPP", href: "/agents/tools/payments/" }, +]; +--- + +
+
+ + +
+
+

Communication channels

+ {channels.length} +
+
+ {channels.map((item) => ( + + {item.type} + {item.name} + + ))} +
+
+ +
+
+
+ +

Agent

+ +
+ +
+
+
Agent harness
+

Controls planning, tool use, and response flow.

+
+ +
+ +
+
+
Agents SDK runtime
+

Durable identity, state, connections, scheduling, and recovery.

+
+ Agent class +
+ {runtime.map((item) => {item.label})} +
+
+
+
+ +
+
+

Tools

+ {tools.length} +
+
+ {tools.map((item) => ( + + {item.type} + {item.name} + + ))} +
+
+ + + Observability + Logs · metrics · traces + +
+
+ + diff --git a/src/components/index.ts b/src/components/index.ts index 76598a6230d979f..e9342081f73893b 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -6,6 +6,7 @@ export { Icon as AstroIcon } from "astro-icon/components"; // Custom components export { default as AnchorHeading } from "./AnchorHeading.astro"; export { default as AnimatedWorkflowDiagram } from "./AnimatedWorkflowDiagram.astro"; +export { default as AgentsPlatformDiagram } from "./AgentsPlatformDiagram.astro"; export { default as APIRequest } from "./APIRequest.astro"; export { default as AutoconfigDiagram } from "./AutoconfigDiagram.astro"; export { default as AvailableNotifications } from "./AvailableNotifications.astro"; diff --git a/src/content/docs/agents/guides/autonomous-responses.mdx b/src/content/docs/agents/communication-channels/chat/autonomous-responses.mdx similarity index 98% rename from src/content/docs/agents/guides/autonomous-responses.mdx rename to src/content/docs/agents/communication-channels/chat/autonomous-responses.mdx index f20a627c9f05a0c..a2b73b60bc9c84c 100644 --- a/src/content/docs/agents/guides/autonomous-responses.mdx +++ b/src/content/docs/agents/communication-channels/chat/autonomous-responses.mdx @@ -111,7 +111,7 @@ export class DigestAgent extends AIChatAgent { -The function form of `saveMessages` — `saveMessages((messages) => [...])` — reads the latest persisted messages at execution time. This avoids stale baselines when multiple calls queue up (for example, rapid webhook arrivals). Refer to [Schedule tasks](/agents/api-reference/schedule-tasks/) for more on `schedule()` and cron syntax. +The function form of `saveMessages` — `saveMessages((messages) => [...])` — reads the latest persisted messages at execution time. This avoids stale baselines when multiple calls queue up (for example, rapid webhook arrivals). Refer to [Schedule tasks](/agents/runtime/execution/schedule-tasks/) for more on `schedule()` and cron syntax. ### Processing a queue @@ -424,24 +424,24 @@ The `messageConcurrency` setting on `AIChatAgent` controls how overlapping user diff --git a/src/content/docs/agents/api-reference/chat-agents.mdx b/src/content/docs/agents/communication-channels/chat/chat-agents.mdx similarity index 98% rename from src/content/docs/agents/api-reference/chat-agents.mdx rename to src/content/docs/agents/communication-channels/chat/chat-agents.mdx index b3c0970ce12edc3..7fe99267a8827cc 100644 --- a/src/content/docs/agents/api-reference/chat-agents.mdx +++ b/src/content/docs/agents/communication-channels/chat/chat-agents.mdx @@ -532,7 +532,7 @@ If you do not pass `abortSignal` to `streamText`, the LLM call will continue run ### Stream recovery -When a Durable Object is evicted mid-stream (code update, inactivity timeout, resource limit), the LLM connection is severed permanently and the in-memory streaming state is lost. `chatRecovery` wraps each chat turn in a [`runFiber()`](/agents/api-reference/durable-execution/), providing automatic `keepAlive` during streaming and a recovery hook on restart. +When a Durable Object is evicted mid-stream (code update, inactivity timeout, resource limit), the LLM connection is severed permanently and the in-memory streaming state is lost. `chatRecovery` wraps each chat turn in a [`runFiber()`](/agents/runtime/execution/durable-execution/), providing automatic `keepAlive` during streaming and a recovery hook on restart. @@ -652,7 +652,7 @@ The right strategy depends on whether the provider supports assistant prefill an | OpenAI (Responses API) | Retrieve completed response by ID — zero wasted tokens | Zero | | Anthropic | Persist partial, send a synthetic user message to continue | Medium | -For how chat recovery fits into the broader long-running agents story, refer to [Long-running agents: Recovering interrupted LLM streams](/agents/concepts/long-running-agents/#recovering-interrupted-llm-streams). For the underlying fiber API, refer to [Durable Execution](/agents/api-reference/durable-execution/). +For how chat recovery fits into the broader long-running agents story, refer to [Long-running agents: Recovering interrupted LLM streams](/agents/concepts/long-running-agents/#recovering-interrupted-llm-streams). For the underlying fiber API, refer to [Durable Execution](/agents/runtime/execution/durable-execution/). ## Client API @@ -1371,7 +1371,7 @@ export class ChatAgent extends AIChatAgent { :::note -This section covers **in-process** subagents using the AI SDK's `ToolLoopAgent`. For **Durable Object sub-agents** with their own isolated storage and typed RPC, refer to [Sub-agents](/agents/api-reference/sub-agents/). For streaming full LLM turns through a child agent, refer to [Think: Sub-agent RPC](/agents/api-reference/think/#sub-agent-rpc-and-programmatic-turns). +This section covers **in-process** subagents using the AI SDK's `ToolLoopAgent`. For **Durable Object sub-agents** with their own isolated storage and typed RPC, refer to [Sub-agents](/agents/runtime/execution/sub-agents/). For streaming full LLM turns through a child agent, refer to [Think: Sub-agent RPC](/agents/harnesses/think/#sub-agent-rpc-and-programmatic-turns). ::: @@ -1530,7 +1530,7 @@ If you are upgrading from an earlier version, replace deprecated calls with thei @@ -1542,13 +1542,13 @@ If you are upgrading from an earlier version, replace deprecated calls with thei diff --git a/src/content/docs/agents/api-reference/client-sdk.mdx b/src/content/docs/agents/communication-channels/chat/client-sdk.mdx similarity index 98% rename from src/content/docs/agents/api-reference/client-sdk.mdx rename to src/content/docs/agents/communication-channels/chat/client-sdk.mdx index 30eae814560022d..766a06b5ab99b7a 100644 --- a/src/content/docs/agents/api-reference/client-sdk.mdx +++ b/src/content/docs/agents/communication-channels/chat/client-sdk.mdx @@ -615,24 +615,24 @@ client.addEventListener("message", () => {}); diff --git a/src/content/docs/agents/platform/index.mdx b/src/content/docs/agents/communication-channels/chat/index.mdx similarity index 68% rename from src/content/docs/agents/platform/index.mdx rename to src/content/docs/agents/communication-channels/chat/index.mdx index a5d58fd2013052d..d11fc13760b2e78 100644 --- a/src/content/docs/agents/platform/index.mdx +++ b/src/content/docs/agents/communication-channels/chat/index.mdx @@ -1,8 +1,8 @@ --- -pcx_content_type: reference -title: Platform +title: Chat +pcx_content_type: navigation sidebar: - order: 7 + order: 1 group: hideIndex: true --- diff --git a/src/content/docs/agents/api-reference/email.mdx b/src/content/docs/agents/communication-channels/email.mdx similarity index 99% rename from src/content/docs/agents/api-reference/email.mdx rename to src/content/docs/agents/communication-channels/email.mdx index 816fd5d968a5166..adbd0fc7d4a88d2 100644 --- a/src/content/docs/agents/api-reference/email.mdx +++ b/src/content/docs/agents/communication-channels/email.mdx @@ -2,7 +2,7 @@ title: Email pcx_content_type: concept sidebar: - order: 16 + order: 3 --- import { TypeScriptExample, WranglerConfig, LinkCard } from "~/components"; @@ -746,18 +746,18 @@ Useful when sending emails through external services while maintaining secure re diff --git a/src/content/docs/agents/communication-channels/index.mdx b/src/content/docs/agents/communication-channels/index.mdx new file mode 100644 index 000000000000000..935c15443eb22a3 --- /dev/null +++ b/src/content/docs/agents/communication-channels/index.mdx @@ -0,0 +1,14 @@ +--- +title: Communication channels +pcx_content_type: navigation +sidebar: + order: 3 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + +Communication channels define how agents communicate with users and external systems. + + diff --git a/src/content/docs/agents/communication-channels/slack.mdx b/src/content/docs/agents/communication-channels/slack.mdx new file mode 100644 index 000000000000000..9a7dedf538a1ecb --- /dev/null +++ b/src/content/docs/agents/communication-channels/slack.mdx @@ -0,0 +1,486 @@ +--- +pcx_content_type: concept +title: Slack +sidebar: + order: 4 +--- + +import { + Details, + Render, + PackageManagers, + WranglerConfig, + LinkCard, +} from "~/components"; + +## Deploy your first Slack Agent + +This guide will show you how to build and deploy an AI-powered Slack bot on Cloudflare Workers that can: + +- Respond to direct messages +- Reply when mentioned in channels +- Maintain conversation context in threads +- Use AI to generate intelligent responses + +Your Slack Agent will be a multi-tenant application, meaning a single deployment can serve multiple Slack workspaces. Each workspace gets its own isolated agent instance with dedicated storage, powered by the [Agents SDK](/agents/). + +You can view the full code for this example [here](https://github.com/cloudflare/awesome-agents/tree/69963298b359ddd66331e8b3b378bb9ae666629f/agents/slack). + +## Prerequisites + +Before you begin, you will need: + +- A [Cloudflare account](https://dash.cloudflare.com/sign-up) +- [Node.js](https://nodejs.org/) installed (v18 or later) +- A [Slack workspace](https://slack.com/create) where you have permission to install apps +- An [OpenAI API key](https://platform.openai.com/api-keys) (or another LLM provider) + +## 1. Create a Slack App + +First, create a new Slack App that your agent will use to interact with Slack: + +1. Go to [api.slack.com/apps](https://api.slack.com/apps) and select **Create New App**. +2. Select **From scratch**. +3. Give your app a name (for example, "My AI Assistant") and select your workspace. +4. Select **Create App**. + +### Configure OAuth & Permissions + +In your Slack App settings, go to **OAuth & Permissions** and add the following **Bot Token Scopes**: + +- `chat:write` — Send messages as the bot +- `chat:write.public` — Send messages to channels without joining +- `channels:history` — View messages in public channels +- `app_mentions:read` — Receive mentions +- `im:write` — Send direct messages +- `im:history` — View direct message history + +### Enable Event Subscriptions + +You will later configure the Event Subscriptions URL after deploying your agent. But for now, go to **Event Subscriptions** in your Slack App settings and prepare to enable it. + +Subscribe to the following bot events: + +- `app_mention` — When the bot is @mentioned +- `message.im` — Direct messages to the bot + +Do not enable it yet. You will enable it after deployment. + +### Get your Slack credentials + +From your Slack App settings, collect these values: + +1. **Basic Information** > **App Credentials**: + - **Client ID** + - **Client Secret** + - **Signing Secret** + +Keep these handy — you will need them in the next step. + +## 2. Create your Slack Agent project + +1. Create a new project for your Slack Agent: + + + +2. Navigate into your project: + +```sh +cd my-slack-agent +``` + +3. Install the required dependencies: + +```sh +npm install agents openai +``` + +## 3. Set up your environment variables + +1. Create a `.env` file in your project root for local development secrets: + +```sh +touch .env +``` + +2. Add your credentials to `.env`: + +```sh +SLACK_CLIENT_ID="your-slack-client-id" +SLACK_CLIENT_SECRET="your-slack-client-secret" +SLACK_SIGNING_SECRET="your-slack-signing-secret" +OPENAI_API_KEY="your-openai-api-key" +OPENAI_BASE_URL="https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT_ID/YOUR_GATEWAY/openai" +``` + +:::note +The `OPENAI_BASE_URL` is optional but recommended. Using [Cloudflare AI Gateway](/ai-gateway/) gives you caching, rate limiting, and analytics for your AI requests. +::: + +3. Update your `wrangler.jsonc` to configure your Agent: + + +```jsonc +{ + "$schema": "./node_modules/wrangler/config-schema.json", + "name": "my-slack-agent", + "main": "src/index.ts", + "compatibility_date": "$today", + "compatibility_flags": [ + "nodejs_compat" + ], + "durable_objects": { + "bindings": [ + { + "name": "MyAgent", + "class_name": "MyAgent", + "script_name": "my-slack-agent" + } + ] + }, + "migrations": [ + { + "tag": "v1", + "new_classes": [ + "MyAgent" + ] + } + ] +} +``` + + +## 4. Create your Slack Agent + +1. First, create the base `SlackAgent` class at `src/slack.ts`. This class handles OAuth, request verification, and event routing. You can view the [full implementation on GitHub](https://github.com/cloudflare/awesome-agents/blob/69963298b359ddd66331e8b3b378bb9ae666629f/agents/slack/src/slack.ts). + +2. Now create your agent implementation at `src/index.ts`: + +```ts +import { env } from "cloudflare:workers"; +import { SlackAgent } from "./slack"; +import { OpenAI } from "openai"; + +const openai = new OpenAI({ + apiKey: env.OPENAI_API_KEY, + baseURL: env.OPENAI_BASE_URL, +}); + +type SlackMsg = { + user?: string; + text?: string; + ts: string; + thread_ts?: string; + subtype?: string; + bot_id?: string; +}; + +function normalizeForLLM(msgs: SlackMsg[], selfUserId: string) { + return msgs.map((m) => { + const role = m.user && m.user !== selfUserId ? "user" : "assistant"; + const text = (m.text ?? "").replace(/<@([A-Z0-9]+)>/g, "@$1"); + return { role, content: text }; + }); +} + +export class MyAgent extends SlackAgent { + async generateAIReply(conversation: SlackMsg[]) { + const selfId = await this.ensureAppUserId(); + const messages = normalizeForLLM(conversation, selfId); + + const system = `You are a helpful AI assistant in Slack. +Be brief, specific, and actionable. If you're unsure, ask a single clarifying question.`; + + const input = [{ role: "system", content: system }, ...messages]; + + const response = await openai.chat.completions.create({ + model: "gpt-4o-mini", + messages: input, + }); + + const msg = response.choices[0].message.content; + if (!msg) throw new Error("No message from AI"); + + return msg; + } + + async onSlackEvent(event: { type: string } & Record) { + // Ignore bot messages and subtypes (edits, joins, etc.) + if (event.bot_id || event.subtype) return; + + // Handle direct messages + if (event.type === "message") { + const e = event as unknown as SlackMsg & { channel: string }; + const isDM = (e.channel || "").startsWith("D"); + const mentioned = (e.text || "").includes( + `<@${await this.ensureAppUserId()}>`, + ); + + if (!isDM && !mentioned) return; + + const conversation = await this.fetchConversation(e.channel); + const content = await this.generateAIReply(conversation); + await this.sendMessage(content, { channel: e.channel }); + return; + } + + // Handle @mentions in channels + if (event.type === "app_mention") { + const e = event as unknown as SlackMsg & { + channel: string; + text?: string; + }; + const thread = await this.fetchThread(e.channel, e.thread_ts || e.ts); + const content = await this.generateAIReply(thread); + await this.sendMessage(content, { + channel: e.channel, + thread_ts: e.thread_ts || e.ts, + }); + return; + } + } +} + +export default MyAgent.listen({ + clientId: env.SLACK_CLIENT_ID, + clientSecret: env.SLACK_CLIENT_SECRET, + slackSigningSecret: env.SLACK_SIGNING_SECRET, + scopes: [ + "chat:write", + "chat:write.public", + "channels:history", + "app_mentions:read", + "im:write", + "im:history", + ], +}); +``` + +## 5. Test locally + +Start your development server: + +```sh +npm run dev +``` + +Your agent is now running at `http://localhost:8787`. + +### Configure Slack Event Subscriptions + +Now that your agent is running locally, you need to expose it to Slack. Use [Cloudflare Tunnel](/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/trycloudflare/) to create a secure tunnel: + +```sh +npx cloudflared tunnel --url http://localhost:8787 +``` + +This will output a public URL like `https://random-subdomain.trycloudflare.com`. + +Go back to your Slack App settings: + +1. Go to **Event Subscriptions**. +2. Toggle **Enable Events** to **On**. +3. Enter your Request URL: `https://random-subdomain.trycloudflare.com/slack`. +4. Slack will send a verification request — if your agent is running correctly, it should show **Verified**. + +5. Under **Subscribe to bot events**, add: + - `app_mention` + - `message.im` + +6. Select **Save Changes**. + +:::note +Cloudflare Tunnel URLs are temporary. When testing locally, you will need to update the Request URL each time you restart the tunnel. +::: + +### Install your app to Slack + +Visit `http://localhost:8787/install` in your browser. This will redirect you to Slack's authorization page. Select **Allow** to install the app to your workspace. + +After authorization, you should see "Successfully registered!" in your browser. + +### Test your agent + +Open Slack. Then: + +1. Send a DM to your bot — it should respond with an AI-generated message. +2. Mention your bot in a channel (e.g., `@My AI Assistant hello`) — it should reply in a thread. + +If everything works, you're ready to deploy to production! + +## 6. Deploy to production + +1. Before deploying, add your secrets to Cloudflare: + +```sh +npx wrangler secret put SLACK_CLIENT_ID +npx wrangler secret put SLACK_CLIENT_SECRET +npx wrangler secret put SLACK_SIGNING_SECRET +npx wrangler secret put OPENAI_API_KEY +npx wrangler secret put OPENAI_BASE_URL +``` + +:::note +You can skip `OPENAI_BASE_URL` if you're not using AI Gateway. +::: + +2. Deploy your agent: + +```sh +npx wrangler deploy +``` + +After deploying, you will get a production URL like: + +``` +https://my-slack-agent.your-account.workers.dev +``` + +### Update Slack Event Subscriptions + +Go back to your Slack App settings: + +1. Go to **Event Subscriptions**. +2. Update the Request URL to your production URL: `https://my-slack-agent.your-account.workers.dev/slack`. +3. Select **Save Changes**. + +### Distribute your app + +Now that your agent is deployed, you can share it with others: + +- **Single workspace**: Install it via `https://my-slack-agent.your-account.workers.dev/install`. +- **Public distribution**: Submit your app to the [Slack App Directory](https://api.slack.com/start/distributing). + +Each workspace that installs your app will get its own isolated agent instance with dedicated storage. + +## How it works + +### Multi-tenancy with Durable Objects + +Your Slack Agent uses [Durable Objects](/durable-objects/) to provide isolated, stateful instances for each Slack workspace: + +- Each workspace's `team_id` is used as the Durable Object ID. +- Each agent instance stores its own Slack access token in KV storage. +- Conversations are fetched on-demand from Slack's API. +- All agent logic runs in an isolated, consistent environment. + +### OAuth flow + +The agent handles Slack's OAuth 2.0 flow: + +1. User visits `/install` > redirected to Slack authorization. +2. User selects **Allow** > Slack redirects to `/accept` with an authorization code. +3. Agent exchanges code for access token. +4. Agent stores token in the workspace's Durable Object. + +### Event handling + +When Slack sends an event: + +1. Request arrives at `/slack` endpoint. +2. Agent verifies the request signature using HMAC-SHA256. +3. Agent routes the event to the correct workspace's Durable Object. +4. `onSlackEvent` method processes the event and generates a response. + +## Customizing your agent + +### Change the AI model + +Update the model in `src/index.ts`: + +```ts +const response = await openai.chat.completions.create({ + model: "gpt-4o", // or any other model + messages: input, +}); +``` + +### Add conversation memory + +Store conversation history in Durable Object storage: + +```ts +async storeMessage(channel: string, message: SlackMsg) { + const history = await this.ctx.storage.kv.get(`history:${channel}`) || []; + history.push(message); + await this.ctx.storage.kv.put(`history:${channel}`, history); +} +``` + +### React to specific keywords + +Add custom logic in `onSlackEvent`: + +```ts +async onSlackEvent(event: { type: string } & Record) { + if (event.type === "message") { + const e = event as unknown as SlackMsg & { channel: string }; + + if (e.text?.includes("help")) { + await this.sendMessage("Here's how I can help...", { + channel: e.channel + }); + return; + } + } + + // ... rest of your event handling +} +``` + +### Use different LLM providers + +Replace OpenAI with [Workers AI](/workers-ai/): + +```ts +import { Ai } from "@cloudflare/ai"; + +export class MyAgent extends SlackAgent { + async generateAIReply(conversation: SlackMsg[]) { + const ai = new Ai(this.ctx.env.AI); + const response = await ai.run("@cf/meta/llama-3-8b-instruct", { + messages: normalizeForLLM(conversation, await this.ensureAppUserId()), + }); + return response.response; + } +} +``` + +## Next steps + +- Add [Slack Interactive Components](https://api.slack.com/interactivity) (buttons, modals) +- Connect your Agent to an [MCP server](/agents/mcp/apis/client-api/) +- Add rate limiting to prevent abuse +- Implement conversation state management +- Use [Workers Analytics Engine](/analytics/analytics-engine/) to track usage +- Add [schedules](/agents/runtime/execution/schedule-tasks/) for scheduled tasks + +## Related resources + + + + + + + + diff --git a/src/content/docs/agents/api-reference/voice.mdx b/src/content/docs/agents/communication-channels/voice.mdx similarity index 99% rename from src/content/docs/agents/api-reference/voice.mdx rename to src/content/docs/agents/communication-channels/voice.mdx index 8ec860e21a58664..d81e849bab4bd5e 100644 --- a/src/content/docs/agents/api-reference/voice.mdx +++ b/src/content/docs/agents/communication-channels/voice.mdx @@ -2,7 +2,7 @@ title: Voice agents pcx_content_type: reference sidebar: - order: 16 + order: 2 --- import { diff --git a/src/content/docs/agents/guides/webhooks.mdx b/src/content/docs/agents/communication-channels/webhooks/index.mdx similarity index 99% rename from src/content/docs/agents/guides/webhooks.mdx rename to src/content/docs/agents/communication-channels/webhooks/index.mdx index 3d874bb9e8e8937..18ad93c4b53f3a8 100644 --- a/src/content/docs/agents/guides/webhooks.mdx +++ b/src/content/docs/agents/communication-channels/webhooks/index.mdx @@ -637,18 +637,18 @@ const secret = this.env.GITHUB_WEBHOOK_SECRET; diff --git a/src/content/docs/agents/guides/push-notifications.mdx b/src/content/docs/agents/communication-channels/webhooks/push-notifications.mdx similarity index 98% rename from src/content/docs/agents/guides/push-notifications.mdx rename to src/content/docs/agents/communication-channels/webhooks/push-notifications.mdx index 7f427a227923a3f..c5733836d648e33 100644 --- a/src/content/docs/agents/guides/push-notifications.mdx +++ b/src/content/docs/agents/communication-channels/webhooks/push-notifications.mdx @@ -401,18 +401,18 @@ try { diff --git a/src/content/docs/agents/guides/anthropic-agent-patterns.mdx b/src/content/docs/agents/concepts/anthropic-agent-patterns.mdx similarity index 80% rename from src/content/docs/agents/guides/anthropic-agent-patterns.mdx rename to src/content/docs/agents/concepts/anthropic-agent-patterns.mdx index b08e8bc2c4447f2..0b9b157721d03c4 100644 --- a/src/content/docs/agents/guides/anthropic-agent-patterns.mdx +++ b/src/content/docs/agents/concepts/anthropic-agent-patterns.mdx @@ -1,9 +1,9 @@ --- pcx_content_type: navigation -title: Implement Effective Agent Patterns +title: Implement effective agent patterns external_link: https://github.com/cloudflare/agents/tree/main/guides/anthropic-patterns sidebar: - order: 2 + order: 9 head: [] description: Implement common agent patterns using the Agents SDK framework. --- diff --git a/src/content/docs/agents/concepts/calling-llms.mdx b/src/content/docs/agents/concepts/calling-llms.mdx index 529590ff99d5e6e..485bc5c78376156 100644 --- a/src/content/docs/agents/concepts/calling-llms.mdx +++ b/src/content/docs/agents/concepts/calling-llms.mdx @@ -11,11 +11,11 @@ import { TypeScriptExample, LinkCard } from "~/components"; Agents change how you work with LLMs. In a stateless Worker, every request starts from scratch — you reconstruct context, call a model, return the response, and forget everything. An Agent keeps state between calls, stays connected to clients over WebSocket, and can call models on its own schedule without a user present. -This page covers the patterns that become possible when your LLM calls happen inside a stateful Agent. For provider setup and code examples, refer to [Using AI Models](/agents/api-reference/using-ai-models/). +This page covers the patterns that become possible when your LLM calls happen inside a stateful Agent. For provider setup and code examples, refer to [Using AI Models](/agents/runtime/operations/using-ai-models/). ## State as context -Every Agent has a built-in [SQL database](/agents/api-reference/store-and-sync-state/) and key-value state. Instead of passing an entire conversation history from the client on every request, the Agent stores it and builds prompts from its own storage. +Every Agent has a built-in [SQL database](/agents/runtime/lifecycle/state/) and key-value state. Instead of passing an entire conversation history from the client on every request, the Agent stores it and builds prompts from its own storage. @@ -79,7 +79,7 @@ export class MyAgent extends Agent { -With [`AIChatAgent`](/agents/api-reference/chat-agents/), this is handled automatically — messages are persisted to SQLite and streams resume on reconnect. +With [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/), this is handled automatically — messages are persisted to SQLite and streams resume on reconnect. ## Autonomous model calls @@ -199,24 +199,24 @@ For provider-level caching and rate limit management across multiple agents, use diff --git a/src/content/docs/agents/concepts/human-in-the-loop.mdx b/src/content/docs/agents/concepts/human-in-the-loop.mdx index ee09ab0da5f3692..cedc6ea06b0942b 100644 --- a/src/content/docs/agents/concepts/human-in-the-loop.mdx +++ b/src/content/docs/agents/concepts/human-in-the-loop.mdx @@ -1,20 +1,21 @@ --- -title: Human in the Loop -pcx_content_type: concept +title: Human-in-the-loop patterns +pcx_content_type: how-to sidebar: - order: 5 + order: 3 +description: Implement human-in-the-loop functionality using Cloudflare Agents for workflow approvals and MCP elicitation --- -import { TypeScriptExample, LinkCard } from "~/components"; +import { TypeScriptExample, WranglerConfig, LinkCard } from "~/components"; -Human-in-the-Loop (HITL) workflows integrate human judgment and oversight into automated processes. These workflows pause at critical points for human review, validation, or decision-making before proceeding. +Human-in-the-loop (HITL) patterns allow agents to pause execution and wait for human approval, confirmation, or input before proceeding. This is essential for compliance, safety, and oversight in agentic systems. ## Why human-in-the-loop? -- **Compliance**: Regulatory requirements may mandate human approval for certain actions. -- **Safety**: High-stakes operations (payments, deletions, external communications) need oversight. -- **Quality**: Human review catches errors AI might miss. -- **Trust**: Users feel more confident when they can approve critical actions. +- **Compliance**: Regulatory requirements may mandate human approval for certain actions +- **Safety**: High-stakes operations (payments, deletions, external communications) need oversight +- **Quality**: Human review catches errors AI might miss +- **Trust**: Users feel more confident when they can approve critical actions ### Common use cases @@ -26,178 +27,380 @@ Human-in-the-Loop (HITL) workflows integrate human judgment and oversight into a | AI tool execution | Confirming tool calls before running | | Access control | Granting permissions, role changes | -## Choosing an approach +## Choosing a pattern -The Agents SDK provides five patterns for human-in-the-loop. Choose based on your architecture: +Cloudflare provides two main patterns for human-in-the-loop: -| Use Case | Pattern | Best For | -| --- | --- | --- | -| Long-running workflows | Workflow Approval | Multi-step processes, durable approval gates that can wait hours or weeks | -| AIChatAgent tools | `needsApproval` | Chat-based tool calls with server-side approval before execution | -| Client-side tools | `onToolCall` | Tools that need browser APIs or user interaction before execution | -| MCP servers | Elicitation | MCP tools requesting structured user input during execution | -| Simple confirmations | State + WebSocket | Lightweight approval flows without AI chat or workflows | +| Pattern | Best for | Key API | +| --------------------- | -------------------------------------------- | ------------------- | +| **Workflow approval** | Multi-step processes, durable approval gates | `waitForApproval()` | +| **MCP elicitation** | MCP servers requesting structured user input | `elicitInput()` | -### Decision tree +Decision guide: -``` -Is this part of a multi-step workflow? -├── Yes → Use Workflow Approval (waitForApproval) -└── No → Are you building an MCP server? - ├── Yes → Use MCP Elicitation (elicitInput) - └── No → Is this an AI chat interaction? - ├── Yes → Does the tool need browser APIs? - │ ├── Yes → Use onToolCall (client-side execution) - │ └── No → Use needsApproval (server-side with approval) - └── No → Use State + WebSocket for simple confirmations -``` +- Use **Workflow approval** when you need durable, multi-step processes with approval gates that can wait hours, days, or weeks +- Use **MCP elicitation** when building MCP servers that need to request additional structured input from users during tool execution -## Pattern 1: Workflow approval +## Workflow-based approval -For durable, multi-step processes with approval gates that can wait hours, days, or weeks. Use [Cloudflare Workflows](/workflows/) with the `waitForApproval()` method. +For durable, multi-step processes, use [Cloudflare Workflows](/workflows/) with the `waitForApproval()` method. The workflow pauses until a human approves or rejects. -**Key APIs:** +### Basic pattern -- `waitForApproval(step, { timeout })` — Pause workflow until approved -- `approveWorkflow(workflowId, { reason?, metadata? })` — Approve a waiting workflow -- `rejectWorkflow(workflowId, { reason? })` — Reject a waiting workflow + -**Best for:** Expense approvals, content publishing pipelines, data export requests +```ts +import { Agent } from "agents"; +import { AgentWorkflow } from "agents/workflows"; +import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows"; + +type ExpenseParams = { + amount: number; + description: string; + requestedBy: string; +}; + +export class ExpenseWorkflow extends AgentWorkflow< + ExpenseAgent, + ExpenseParams +> { + async run(event: AgentWorkflowEvent, step: AgentWorkflowStep) { + const expense = event.payload; + + // Step 1: Validate the expense + const validated = await step.do("validate", async () => { + if (expense.amount <= 0) { + throw new Error("Invalid expense amount"); + } + return { ...expense, validatedAt: Date.now() }; + }); + + // Step 2: Report that we are waiting for approval + await this.reportProgress({ + step: "approval", + status: "pending", + message: `Awaiting approval for $${expense.amount}`, + }); + + // Step 3: Wait for human approval (pauses the workflow) + const approval = await this.waitForApproval<{ approvedBy: string }>(step, { + timeout: "7 days", + }); + + console.log(`Approved by: ${approval?.approvedBy}`); + + // Step 4: Process the approved expense + const result = await step.do("process", async () => { + return { expenseId: crypto.randomUUID(), ...validated }; + }); + + await step.reportComplete(result); + return result; + } +} +``` -## Pattern 2: `needsApproval` (AI chat tools) + + +### Agent methods for approval -For `AIChatAgent` tools that should pause for user confirmation before executing. Define `needsApproval` on the tool — it can be a boolean or an async predicate based on the tool arguments: +The agent provides methods to approve or reject waiting workflows: ```ts -tools: { - processPayment: tool({ - description: "Process a payment", - inputSchema: z.object({ - amount: z.number(), - recipient: z.string(), - }), - needsApproval: async ({ amount }) => amount > 100, - execute: async ({ amount, recipient }) => charge(amount, recipient), - }); +import { Agent, callable } from "agents"; + +type PendingApproval = { + workflowId: string; + amount: number; + description: string; + requestedBy: string; + requestedAt: number; +}; + +type ExpenseState = { + pendingApprovals: PendingApproval[]; +}; + +export class ExpenseAgent extends Agent { + initialState: ExpenseState = { + pendingApprovals: [], + }; + + // Approve a waiting workflow + @callable() + async approve(workflowId: string, approvedBy: string): Promise { + await this.approveWorkflow(workflowId, { + reason: "Expense approved", + metadata: { approvedBy, approvedAt: Date.now() }, + }); + + // Update state to reflect approval + this.setState({ + ...this.state, + pendingApprovals: this.state.pendingApprovals.filter( + (p) => p.workflowId !== workflowId, + ), + }); + } + + // Reject a waiting workflow + @callable() + async reject(workflowId: string, reason: string): Promise { + await this.rejectWorkflow(workflowId, { reason }); + + this.setState({ + ...this.state, + pendingApprovals: this.state.pendingApprovals.filter( + (p) => p.workflowId !== workflowId, + ), + }); + } + + // Track workflow progress to update pending approvals + async onWorkflowProgress( + workflowName: string, + workflowId: string, + progress: unknown, + ): Promise { + const p = progress as { step: string; status: string; message?: string }; + + if (p.step === "approval" && p.status === "pending") { + // Add to pending approvals list for UI display + this.setState({ + ...this.state, + pendingApprovals: [ + ...this.state.pendingApprovals, + { + workflowId, + amount: 0, // Would come from workflow params + description: p.message || "", + requestedBy: "user", + requestedAt: Date.now(), + }, + ], + }); + } + } } ``` -On the client, render pending approvals from message parts and call `addToolApprovalResponse`: +### Timeout handling + +Set timeouts to prevent workflows from waiting indefinitely: ```ts -const { messages, addToolApprovalResponse } = useAgentChat({ agent }); +const approval = await this.waitForApproval<{ approvedBy: string }>(step, { + timeout: "7 days", // Also supports: "1 hour", "30 minutes", etc. +}); -{ - messages.map((msg) => - msg.parts - .filter( - (part) => part.type === "tool" && part.state === "approval-required", - ) - .map((part) => ( -
-

- Approve {part.toolName}? -

- - -
- )), - ); +if (!approval) { + // Timeout expired - escalate or auto-reject + await step.reportError("Approval timeout - escalating to manager"); + throw new Error("Approval timeout"); } ```
-For custom denial messages, use `addToolOutput` with `state: "output-error"` instead of `addToolApprovalResponse`: +### Escalation with scheduling + +Use `schedule()` to set up escalation reminders: ```ts -addToolOutput({ - toolCallId: part.toolCallId, - state: "output-error", - errorText: "User declined: insufficient budget for this quarter", -}); +import { Agent, callable } from "agents"; + +class ExpenseAgent extends Agent { + @callable() + async submitForApproval(expense: ExpenseParams): Promise { + // Start the approval workflow + const workflowId = await this.runWorkflow("EXPENSE_WORKFLOW", expense); + + // Schedule reminder after 4 hours + await this.schedule(Date.now() + 4 * 60 * 60 * 1000, "sendReminder", { + workflowId, + }); + + // Schedule escalation after 24 hours + await this.schedule(Date.now() + 24 * 60 * 60 * 1000, "escalateApproval", { + workflowId, + }); + + return workflowId; + } + + async sendReminder(payload: { workflowId: string }) { + const workflow = this.getWorkflow(payload.workflowId); + if (workflow?.status === "waiting") { + // Send reminder notification + console.log("Reminder: approval still pending"); + } + } + + async escalateApproval(payload: { workflowId: string }) { + const workflow = this.getWorkflow(payload.workflowId); + if (workflow?.status === "waiting") { + // Escalate to manager + console.log("Escalating to manager"); + } + } +} ``` -## Pattern 3: `onToolCall` (client-side execution) +### Audit trail with SQL -For tools that need browser APIs (geolocation, clipboard, camera) or user interaction before returning a result. Define the tool on the server without `execute`, then handle it on the client: +Use `this.sql` to maintain an immutable audit trail: ```ts -const { messages, sendMessage } = useAgentChat({ - agent, - onToolCall: async ({ toolCall, addToolOutput }) => { - if (toolCall.toolName === "getLocation") { - const pos = await new Promise((resolve, reject) => - navigator.geolocation.getCurrentPosition(resolve, reject), - ); - addToolOutput({ - toolCallId: toolCall.toolCallId, - output: { lat: pos.coords.latitude, lng: pos.coords.longitude }, - }); - } - }, -}); +import { Agent, callable } from "agents"; + +class ExpenseAgent extends Agent { + async onStart() { + // Create audit table + this.sql` + CREATE TABLE IF NOT EXISTS approval_audit ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + workflow_id TEXT NOT NULL, + decision TEXT NOT NULL CHECK(decision IN ('approved', 'rejected')), + decided_by TEXT NOT NULL, + decided_at INTEGER NOT NULL, + reason TEXT + ) + `; + } + + @callable() + async approve( + workflowId: string, + userId: string, + reason?: string, + ): Promise { + // Record the decision in SQL (immutable audit log) + this.sql` + INSERT INTO approval_audit (workflow_id, decision, decided_by, decided_at, reason) + VALUES (${workflowId}, 'approved', ${userId}, ${Date.now()}, ${reason || null}) + `; + + // Process the approval + await this.approveWorkflow(workflowId, { + reason: reason || "Approved", + metadata: { approvedBy: userId }, + }); + } +} ``` -When `autoContinueAfterToolResult` is `true` (the default), the conversation automatically continues after the client provides the tool output. +### Configuration -## Pattern 4: MCP elicitation + -For MCP servers that need to request additional structured input from users during tool execution. The MCP client renders a form based on your JSON Schema: +```jsonc +{ + "name": "expense-approval", + "main": "src/index.ts", + "compatibility_date": "$today", + "compatibility_flags": ["nodejs_compat"], + "durable_objects": { + "bindings": [{ "name": "EXPENSE_AGENT", "class_name": "ExpenseAgent" }], + }, + "workflows": [ + { + "name": "expense-workflow", + "binding": "EXPENSE_WORKFLOW", + "class_name": "ExpenseWorkflow", + }, + ], + "migrations": [{ "tag": "v1", "new_sqlite_classes": ["ExpenseAgent"] }], +} +``` + + + +## MCP elicitation + +When building MCP servers with `McpAgent`, you can request additional user input during tool execution using **elicitation**. The MCP client renders a form based on your JSON Schema and returns the user's response. + +### Basic pattern ```ts -export class MyMcpAgent extends McpAgent { +import { McpAgent } from "agents/mcp"; +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { z } from "zod"; + +type State = { counter: number }; + +export class CounterMCP extends McpAgent { + server = new McpServer({ + name: "counter-server", + version: "1.0.0", + }); + + initialState: State = { counter: 0 }; + async init() { - this.server.server.setRequestHandler( - CallToolRequestSchema, - async (request, extra) => { - const result = await this.server.server.elicitInput({ - message: "Please confirm the transfer details", - requestedSchema: { - type: "object", - properties: { - confirmed: { type: "boolean", description: "Confirm transfer?" }, - notes: { type: "string", description: "Optional notes" }, + this.server.tool( + "increase-counter", + "Increase the counter by a user-specified amount", + { confirm: z.boolean().describe("Do you want to increase the counter?") }, + async ({ confirm }, extra) => { + if (!confirm) { + return { content: [{ type: "text", text: "Cancelled." }] }; + } + + // Request additional input from the user + const userInput = await this.server.server.elicitInput( + { + message: "By how much do you want to increase the counter?", + requestedSchema: { + type: "object", + properties: { + amount: { + type: "number", + title: "Amount", + description: "The amount to increase the counter by", + }, + }, + required: ["amount"], }, - required: ["confirmed"], }, - }); + { relatedRequestId: extra.requestId }, + ); - if (result.action === "accept" && result.content?.confirmed) { - return { content: [{ type: "text", text: "Transfer confirmed" }] }; + // Check if user accepted or cancelled + if (userInput.action !== "accept" || !userInput.content) { + return { content: [{ type: "text", text: "Cancelled." }] }; } - return { content: [{ type: "text", text: "Transfer cancelled" }] }; + + // Use the input + const amount = Number(userInput.content.amount); + this.setState({ + ...this.state, + counter: this.state.counter + amount, + }); + + return { + content: [ + { + type: "text", + text: `Counter increased by ${amount}, now at ${this.state.counter}`, + }, + ], + }; }, ); } @@ -206,100 +409,146 @@ export class MyMcpAgent extends McpAgent { -**Best for:** Interactive tool confirmations, gathering additional parameters mid-execution +## Elicitation vs workflow approval -## How workflows handle approvals +| Aspect | MCP Elicitation | Workflow Approval | +| ------------ | ----------------------------- | ----------------------------- | +| **Context** | MCP server tool execution | Multi-step workflow processes | +| **Duration** | Immediate (within tool call) | Can wait hours/days/weeks | +| **UI** | JSON Schema-based form | Custom UI via agent state | +| **State** | MCP session state | Durable workflow state | +| **Use case** | Interactive input during tool | Approval gates in pipelines | -![A human-in-the-loop diagram](~/assets/images/agents/human-in-the-loop.svg) +## Building approval UIs -In a workflow-based approval: +### Pending approvals list -1. The workflow reaches an approval step and calls `waitForApproval()` -2. The workflow pauses and reports progress to the agent -3. The agent updates its state with the pending approval -4. Connected clients see the pending approval and can approve or reject -5. When approved, the workflow resumes with the approval metadata -6. If rejected or timed out, the workflow handles the rejection appropriately +Use the agent's state to display pending approvals in your UI: -## Timeouts and escalation +```tsx +import { useAgent } from "agents/react"; -Set timeouts to prevent workflows from waiting indefinitely: +function PendingApprovals() { + const { state, agent } = useAgent({ + agent: "expense-agent", + name: "main", + }); - + if (!state?.pendingApprovals?.length) { + return

No pending approvals

; + } -```ts -const approval = await this.waitForApproval(step, { - timeout: "7 days", -}); + return ( +
+ {state.pendingApprovals.map((item) => ( +
+

${item.amount}

+

{item.description}

+

Requested by {item.requestedBy}

+ +
+ + +
+
+ ))} +
+ ); +} ``` -
+## Multi-approver patterns -Use [scheduling](/agents/api-reference/schedule-tasks/) for escalation: +For sensitive operations requiring multiple approvers: ```ts -await this.schedule(86400, "sendApprovalReminder", { workflowId }); - -await this.schedule(604800, "escalateToManager", { workflowId }); -``` - - - -## Best practices - -### Audit trails - -Maintain immutable audit logs of all approval decisions using the [SQL API](/agents/api-reference/store-and-sync-state/). Record: - -- Who made the decision -- When the decision was made -- The reason or justification -- Any relevant metadata - -### Long-term state persistence +import { Agent, callable } from "agents"; + +type MultiApproval = { + workflowId: string; + requiredApprovals: number; + currentApprovals: Array<{ userId: string; approvedAt: number }>; + rejections: Array<{ userId: string; rejectedAt: number; reason: string }>; +}; + +type State = { + pendingMultiApprovals: MultiApproval[]; +}; + +class MultiApprovalAgent extends Agent { + @callable() + async approveMulti(workflowId: string, userId: string): Promise { + const approval = this.state.pendingMultiApprovals.find( + (p) => p.workflowId === workflowId, + ); + if (!approval) throw new Error("Approval not found"); -Human review processes do not operate on predictable timelines. A reviewer might need days or weeks to make a decision. Your system needs to maintain state consistency throughout this period — the original request, intermediate decisions, partial progress, and review history. + // Check if user already approved + if (approval.currentApprovals.some((a) => a.userId === userId)) { + throw new Error("Already approved by this user"); + } -:::note[Tip] -[Durable Objects](/durable-objects/) provide persistent compute instances that maintain state for hours, weeks, or months — ideal for long-lived approval flows. -::: + // Add this user's approval + approval.currentApprovals.push({ userId, approvedAt: Date.now() }); -### Continuous improvement + // Check if we have enough approvals + if (approval.currentApprovals.length >= approval.requiredApprovals) { + // Execute the approved action + await this.approveWorkflow(workflowId, { + metadata: { approvers: approval.currentApprovals }, + }); + return true; + } -Human reviewers play a crucial role in evaluating and improving LLM performance: + this.setState({ ...this.state }); + return false; // Still waiting for more approvals + } +} +``` -- **Decision quality assessment**: Have reviewers evaluate the LLM's reasoning process and decision points. -- **Edge case identification**: Use human expertise to identify scenarios where performance could be improved. -- **Feedback collection**: Gather structured feedback that can be used to fine-tune the LLM. [AI Gateway](/ai-gateway/evaluations/add-human-feedback/) can help set up an LLM feedback loop. +
-### Error handling and recovery +## Best practices -Your system should gracefully handle reviewer unavailability, system outages, conflicting reviews, and timeout expiration. Implement clear escalation paths for exceptional cases and automatic checkpointing that allows workflows to resume from the last stable state after any interruption. +1. **Define clear approval criteria** — Only require confirmation for actions with meaningful consequences (payments, emails, data changes) +2. **Provide detailed context** — Show users exactly what the action will do, including all arguments +3. **Implement timeouts** — Use `schedule()` to escalate or auto-reject after reasonable periods +4. **Maintain audit trails** — Use `this.sql` to record all approval decisions for compliance +5. **Handle connection drops** — Store pending approvals in agent state so they survive disconnections +6. **Graceful degradation** — Provide fallback behavior if approvals are rejected ## Next steps diff --git a/src/content/docs/agents/concepts/long-running-agents.mdx b/src/content/docs/agents/concepts/long-running-agents.mdx index b138dd5019e5d71..eae54955bf341ae 100644 --- a/src/content/docs/agents/concepts/long-running-agents.mdx +++ b/src/content/docs/agents/concepts/long-running-agents.mdx @@ -114,7 +114,7 @@ A hibernated agent can be woken by any of these sources: | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | | **HTTP request** | Any request to the agent's URL triggers `onRequest()` | A webhook from GitHub | | **WebSocket connection** | A client connects, triggering `onConnect()` | A team member opens the dashboard | -| **RPC call** | Another Worker or agent calls a method via [service binding](/workers/runtime-apis/bindings/service-bindings/) or [`@callable`](/agents/api-reference/callable-methods/) | A coordinator agent delegates a task | +| **RPC call** | Another Worker or agent calls a method via [service binding](/workers/runtime-apis/bindings/service-bindings/) or [`@callable`](/agents/runtime/lifecycle/callable-methods/) | A coordinator agent delegates a task | | **Scheduled alarm** | A stored schedule fires, triggering your callback | Daily standup reminder at 9am | | **Email** | An inbound email triggers `onEmail()` | A team member replies to a status email | @@ -216,7 +216,7 @@ try { An agent can be evicted at any time — a deploy, a platform restart, or hitting resource limits. If the agent was mid-task, that work is lost unless it was checkpointed. -[`runFiber()`](/agents/api-reference/durable-execution/) provides crash-recoverable execution. It persists a row in SQLite for the duration of the work, and lets you `stash()` intermediate state. If the agent is evicted, the fiber row survives, and `onFiberRecovered()` is called on the next activation. +[`runFiber()`](/agents/runtime/execution/durable-execution/) provides crash-recoverable execution. It persists a row in SQLite for the duration of the work, and lets you `stash()` intermediate state. If the agent is evicted, the fiber row survives, and `onFiberRecovered()` is called on the next activation. ```ts export class ProjectManager extends Agent { @@ -257,7 +257,7 @@ In `wrangler dev`, fiber recovery works identically to production. Kill the wran ::: -For the full API reference — `FiberContext`, `FiberRecoveryContext`, concurrent fibers, inline vs fire-and-forget patterns — refer to [Durable Execution](/agents/api-reference/durable-execution/). +For the full API reference — `FiberContext`, `FiberRecoveryContext`, concurrent fibers, inline vs fire-and-forget patterns — refer to [Durable Execution](/agents/runtime/execution/durable-execution/). ## Handling long async operations @@ -520,7 +520,7 @@ export class ProjectManager extends Agent { Sub-agents are independent Durable Objects. They have their own state, their own schedules, and their own lifecycle. The parent does not need to stay alive while the sub-agent works — it can start the work, hibernate, and be woken by a callback or scheduled check. -For the full `subAgent()` API — typed RPC stubs, abort, delete, storage isolation, and limitations — refer to [Sub-agents](/agents/api-reference/sub-agents/). For AI-specific sub-agent streaming (running full LLM turns through a child agent), refer to [Think: Sub-agent RPC](/agents/api-reference/think/#sub-agent-rpc-and-programmatic-turns). +For the full `subAgent()` API — typed RPC stubs, abort, delete, storage isolation, and limitations — refer to [Sub-agents](/agents/runtime/execution/sub-agents/). For AI-specific sub-agent streaming (running full LLM turns through a child agent), refer to [Think: Sub-agent RPC](/agents/harnesses/think/#sub-agent-rpc-and-programmatic-turns). ## Recovering interrupted LLM streams @@ -675,13 +675,13 @@ The agent does not need to run continuously to do any of this. It just needs to ## Related -- [Durable Execution](/agents/api-reference/durable-execution/) — `runFiber()`, `stash()`, and crash recovery -- [Schedule tasks](/agents/api-reference/schedule-tasks/) — delayed, cron, and interval tasks -- [Retries](/agents/api-reference/retries/) — retry options and patterns +- [Durable Execution](/agents/runtime/execution/durable-execution/) — `runFiber()`, `stash()`, and crash recovery +- [Schedule tasks](/agents/runtime/execution/schedule-tasks/) — delayed, cron, and interval tasks +- [Retries](/agents/runtime/execution/retries/) — retry options and patterns - [Workflows](/agents/concepts/workflows/) — durable multi-step processing -- [Store and sync state](/agents/api-reference/store-and-sync-state/) — `setState()` and persistence -- [WebSockets](/agents/api-reference/websockets/) — lifecycle hooks and hibernation -- [Callable methods](/agents/api-reference/callable-methods/) — RPC via `@callable` and service bindings -- [Email routing](/agents/api-reference/email/) — receiving inbound email -- [Webhooks](/agents/guides/webhooks/) — receiving external events +- [Store and sync state](/agents/runtime/lifecycle/state/) — `setState()` and persistence +- [WebSockets](/agents/runtime/communication/websockets/) — lifecycle hooks and hibernation +- [Callable methods](/agents/runtime/lifecycle/callable-methods/) — RPC via `@callable` and service bindings +- [Email routing](/agents/communication-channels/email/) — receiving inbound email +- [Webhooks](/agents/communication-channels/webhooks/) — receiving external events - [Human in the loop](/agents/concepts/human-in-the-loop/) — approval flows diff --git a/src/content/docs/agents/concepts/memory.mdx b/src/content/docs/agents/concepts/memory.mdx index 675da7fe8c3d35e..605c408b93f5c76 100644 --- a/src/content/docs/agents/concepts/memory.mdx +++ b/src/content/docs/agents/concepts/memory.mdx @@ -12,7 +12,7 @@ import { TypeScriptExample, LinkCard, WranglerConfig } from "~/components"; Agents need memory to be useful over time. Without it, every conversation starts from zero. The agent forgets who the user is, what it learned, and what it was doing. Memory is what turns a stateless LLM call into a persistent, context-aware agent. -The [Session API](/agents/api-reference/sessions/) provides the memory layer for agents built on the Cloudflare Agents SDK. It manages two kinds of memory: **conversation history** (the messages and tool calls that make up a session) and **context memory** (persistent blocks injected into the system prompt that the agent can read, write, search, and load). +The [Session API](/agents/runtime/lifecycle/sessions/) provides the memory layer for agents built on the Cloudflare Agents SDK. It manages two kinds of memory: **conversation history** (the messages and tool calls that make up a session) and **context memory** (persistent blocks injected into the system prompt that the agent can read, write, search, and load). ## Conversation history @@ -393,7 +393,7 @@ The Session generates tools dynamically based on what provider types are present The tools include descriptions and parameter schemas that tell the LLM which blocks are available and what they are for. The agent decides when and how to use them based on the conversation. -For the full tool signatures and all Session methods, refer to the [Session API reference](/agents/api-reference/sessions/). +For the full tool signatures and all Session methods, refer to the [Session API reference](/agents/runtime/lifecycle/sessions/). ## The system prompt @@ -532,18 +532,18 @@ const truncated = truncateOlderMessages(history); diff --git a/src/content/docs/agents/patterns.mdx b/src/content/docs/agents/concepts/patterns.mdx similarity index 100% rename from src/content/docs/agents/patterns.mdx rename to src/content/docs/agents/concepts/patterns.mdx diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index a8c0390f3082482..02cb7619b015ec1 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -62,7 +62,7 @@ An agent can dynamically generate an itinerary and execute on booking reservatio Agent systems typically have three primary components: - **Decision Engine**: Usually an LLM (Large Language Model) that determines action steps -- **Tool Integration**: APIs, functions, and services the agent can utilize — often via [MCP](/agents/model-context-protocol/) +- **Tool Integration**: APIs, functions, and services the agent can utilize — often via [MCP](/agents/mcp/) - **Memory System**: Maintains context and tracks task progress ### How agents work @@ -94,12 +94,12 @@ The Cloudflare Agents SDK provides the infrastructure for building production ag diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx index cd88097364aa32a..a179ffd3e9a24a6 100644 --- a/src/content/docs/agents/concepts/workflows.mdx +++ b/src/content/docs/agents/concepts/workflows.mdx @@ -183,7 +183,7 @@ A Workflow updates Agent state at key milestones using `step.updateAgentState()` diff --git a/src/content/docs/agents/examples/browser-agent.mdx b/src/content/docs/agents/examples/browser-agent.mdx new file mode 100644 index 000000000000000..4dfda5f981c59e4 --- /dev/null +++ b/src/content/docs/agents/examples/browser-agent.mdx @@ -0,0 +1,411 @@ +--- +title: Browser agent +pcx_content_type: example +sidebar: + order: 3 +--- + +import { + InlineBadge, + TypeScriptExample, + WranglerConfig, + PackageManagers, +} from "~/components"; + +Build an agent that can browse the web, inspect pages, capture screenshots, and debug frontend issues with [Browser Run](/browser-run/) tools. + +Instead of a fixed set of browser actions (click, screenshot, navigate), the LLM writes JavaScript code that runs CDP commands against a live browser session — accessing all domains, commands, events, and types in the protocol. + +Two tools are provided: + +| Tool | Description | +| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `browser_search` | Query the CDP spec to discover commands, events, and types. The spec is fetched dynamically from the browser's CDP endpoint and cached. | +| `browser_execute` | Run CDP commands against a live browser via a `cdp` helper. Each call opens a fresh browser session, executes the code, and closes it. | + +## When to use browser tools + +Browser tools are useful when your agent needs to: + +- **Inspect web pages** — DOM structure, computed styles, accessibility tree +- **Debug frontend issues** — network waterfalls, console errors, performance traces +- **Scrape structured data** — extract content from rendered pages +- **Capture screenshots or PDFs** — visual snapshots of web content +- **Profile performance** — Core Web Vitals, JavaScript profiling, memory analysis + +For basic page fetches that do not need a rendered DOM, use `fetch()` instead. + +## Install + +Browser tools require the Agents SDK and `@cloudflare/codemode`: + +```sh +npm install agents @cloudflare/codemode ai zod +``` + +## Quick start + +### 1. Configure bindings + +Add the Browser Run (formerly Browser Rendering) and Worker Loader bindings to your wrangler configuration: + + + +```jsonc +{ + "compatibility_flags": ["nodejs_compat"], + "browser": { + "binding": "BROWSER", + }, + "worker_loaders": [ + { + "binding": "LOADER", + }, + ], +} +``` + + + +### 2. Create browser tools + + + +```ts +import { createBrowserTools } from "agents/browser/ai"; + +const browserTools = createBrowserTools({ + browser: env.BROWSER, + loader: env.LOADER, +}); +``` + + + +To connect to a custom CDP endpoint instead of the Browser Run binding, pass `cdpUrl`. + +### 3. Use with streamText + +Pass browser tools alongside your other tools. The `model` can be any AI SDK provider — here using Workers AI: + + + +```ts +import { streamText } from "ai"; +import { createWorkersAI } from "workers-ai-provider"; + +const workersai = createWorkersAI({ binding: env.AI }); + +const result = streamText({ + model: workersai("@cf/zai-org/glm-4.7-flash"), + system: "You are a helpful assistant that can inspect web pages.", + messages, + tools: { + ...browserTools, + ...otherTools, + }, +}); +``` + + + +Both tools accept a `code` parameter containing a JavaScript async arrow function. The sandbox injects globals depending on the tool — `spec` for `browser_search` and `cdp` for `browser_execute`. + +When the LLM uses `browser_search`, the code queries the CDP spec via the injected `spec` object: + +```js +async () => { + const s = await spec.get(); + return s.domains + .find((d) => d.name === "Network") + .commands.map((c) => ({ method: c.method, description: c.description })); +}; +``` + +When the LLM uses `browser_execute`, the code runs CDP commands via the injected `cdp` helper: + +```js +async () => { + const { targetId } = await cdp.send("Target.createTarget", { + url: "https://example.com", + }); + const sessionId = await cdp.attachToTarget(targetId); + const { root } = await cdp.send("DOM.getDocument", {}, { sessionId }); + const { outerHTML } = await cdp.send( + "DOM.getOuterHTML", + { nodeId: root.nodeId }, + { sessionId }, + ); + await cdp.send("Target.closeTarget", { targetId }); + return outerHTML; +}; +``` + +## Use with an Agent + +The typical pattern is to create browser tools inside an [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/) message handler, which gives you message persistence and streaming: + + + +```ts +import { AIChatAgent } from "@cloudflare/ai-chat"; +import { createBrowserTools } from "agents/browser/ai"; +import { createWorkersAI } from "workers-ai-provider"; +import { streamText, convertToModelMessages, stepCountIs } from "ai"; + +export class MyAgent extends AIChatAgent { + async onChatMessage() { + const workersai = createWorkersAI({ binding: this.env.AI }); + const browserTools = createBrowserTools({ + browser: this.env.BROWSER, + loader: this.env.LOADER, + }); + + const result = streamText({ + model: workersai("@cf/zai-org/glm-4.7-flash"), + system: "You can browse the web and inspect pages.", + messages: await convertToModelMessages(this.messages), + tools: { + ...browserTools, + }, + stopWhen: stepCountIs(10), + }); + + return result.toUIMessageStreamResponse(); + } +} +``` + + + +## TanStack AI + +For TanStack AI, use the `/tanstack-ai` export: + + + +```ts +import { createBrowserTools } from "agents/browser/tanstack-ai"; +import { chat, workersAIText } from "@tanstack/ai"; + +const browserTools = createBrowserTools({ + browser: env.BROWSER, + loader: env.LOADER, +}); + +const stream = chat({ + adapter: workersAIText(env.AI, "@cf/zai-org/glm-4.7-flash"), + tools: [...browserTools, ...otherTools], + messages, +}); +``` + + + +## Execution model + +- `browser_search` fetches the live CDP protocol from the browser's `/json/protocol` endpoint and caches it briefly. +- `browser_execute` opens a fresh browser session for each call, exposes a small `cdp` helper API to sandboxed code, and closes the session when execution finishes. +- LLM-generated code runs in a Worker sandbox. CDP traffic stays in the host Worker. + +## CDP helper API + +Inside `browser_execute`, the following functions are available to the sandboxed code. + +### `cdp.send(method, params?, options?)` + +Send a CDP command and wait for the response. + +| Parameter | Type | Description | +| ------------------- | --------- | ----------------------------------------------------------------- | +| `method` | `string` | CDP method, for example `"DOM.getDocument"` or `"Network.enable"` | +| `params` | `unknown` | Method parameters | +| `options.timeoutMs` | `number` | Per-command timeout (default: 10 seconds) | +| `options.sessionId` | `string` | Target session ID (required for page-scoped commands) | + +### `cdp.attachToTarget(targetId, options?)` + +Attach to a target and get a session ID. Uses `Target.attachToTarget` with `flatten: true`. + +| Parameter | Type | Description | +| ------------------- | -------- | ------------------------------ | +| `targetId` | `string` | The target to attach to | +| `options.timeoutMs` | `number` | Timeout for the attach command | + +Returns the `sessionId` string. + +### `cdp.getDebugLog(limit?)` + +Get recent CDP debug log entries (sends, receives, errors). Defaults to the last 50 entries, max 400. + +### `cdp.clearDebugLog()` + +Clear the debug log buffer. + +## Configuration + +### `createBrowserTools(options)` + +Returns AI SDK tools (`browser_search` and `browser_execute`). + +| Option | Type | Default | Description | +| ------------ | ------------------------ | -------- | -------------------------------------------------------------- | +| `browser` | `Fetcher` | — | Browser Run binding | +| `cdpUrl` | `string` | — | Optional override for a custom CDP endpoint | +| `cdpHeaders` | `Record` | — | Headers for CDP URL discovery (for example, Cloudflare Access) | +| `loader` | `WorkerLoader` | required | Worker Loader binding for sandboxed execution | +| `timeout` | `number` | `30000` | Execution timeout in milliseconds | + +Either `browser` or `cdpUrl` must be provided. When both are set, `cdpUrl` takes priority. + +### Raw access + +For custom integrations, import the building blocks directly: + + + +```ts +import { + CdpSession, + connectBrowser, + connectUrl, + createBrowserToolHandlers, +} from "agents/browser"; + +// Connect to a custom CDP endpoint +const session = await connectUrl("http://localhost:9222"); +const version = await session.send("Browser.getVersion"); +session.close(); +``` + + + +## Local development + +Recent Wrangler releases support Browser Run in local development. `npx wrangler dev` provisions the browser automatically, so the same `browser: env.BROWSER` setup works locally and when deployed. + +Use `cdpUrl` only when you intentionally want to connect to some other CDP-compatible browser endpoint, such as a tunnel or a manually managed Chrome instance. + +## Security considerations + +- LLM-generated code runs in **isolated Worker sandboxes** — each execution gets its own Worker instance +- External network access (`fetch`, `connect`) is **blocked** in the sandbox at the runtime level +- CDP commands are dispatched via Workers RPC — the WebSocket lives in the host, not the sandbox +- The CDP spec stays on the server — only query results flow to the LLM +- Responses are truncated to approximately 6,000 tokens to prevent context window overflow + +## Current limitations + +- **One session per execute call** — each `browser_execute` invocation opens a fresh browser session. Multi-step workflows must be completed within a single code block. +- **No authenticated sessions** — the browser starts without any cookies or login state. +- Requires `@cloudflare/codemode` as a peer dependency. +- Limited to JavaScript execution in the sandbox (no TypeScript syntax). + +--- + +## Using Puppeteer directly + +If you prefer to control the browser programmatically without LLM-generated code, you can use Puppeteer with the [Browser Run](/browser-run/) API directly. + + + + + +```ts +import puppeteer from "@cloudflare/puppeteer"; + +interface Env { + BROWSER: Fetcher; + AI: Ai; +} + +export class MyAgent extends Agent { + async browse(browserInstance: Fetcher, urls: string[]) { + let responses = []; + for (const url of urls) { + const browser = await puppeteer.launch(browserInstance); + const page = await browser.newPage(); + await page.goto(url); + + await page.waitForSelector("body"); + const bodyContent = await page.$eval( + "body", + (element) => element.innerHTML, + ); + + let resp = await this.env.AI.run("@cf/zai-org/glm-4.7-flash", { + messages: [ + { + role: "user", + content: `Return a JSON object with the product names, prices and URLs from the website content below. ${bodyContent}`, + }, + ], + }); + + responses.push(resp); + await browser.close(); + } + + return responses; + } +} +``` + + + +Add the browser binding to your wrangler configuration: + + + +```jsonc +{ + "ai": { + "binding": "AI", + }, + "browser": { + "binding": "BROWSER", + }, +} +``` + + + +## Using Browserbase + +You can also use [Browserbase](https://docs.browserbase.com/integrations/cloudflare/typescript) by using the Browserbase API directly from within your Agent. + +Once you have your [Browserbase API key](https://docs.browserbase.com/integrations/cloudflare/typescript), you can add it to your Agent by creating a [secret](/workers/configuration/secrets/): + +```sh +cd your-agent-project-folder +npx wrangler@latest secret put BROWSERBASE_API_KEY +``` + +Install the `@cloudflare/puppeteer` package and use it from within your Agent to call the Browserbase API: + + + + + +```ts +import puppeteer from "@cloudflare/puppeteer"; + +interface Env { + BROWSERBASE_API_KEY: string; +} + +export class MyAgent extends Agent { + async browse(url: string) { + const browser = await puppeteer.connect({ + browserWSEndpoint: `wss://connect.browserbase.com?apiKey=${this.env.BROWSERBASE_API_KEY}`, + }); + const page = await browser.newPage(); + await page.goto(url); + const content = await page.content(); + await browser.close(); + return content; + } +} +``` + + diff --git a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx b/src/content/docs/agents/examples/chat-agent.mdx similarity index 97% rename from src/content/docs/agents/getting-started/build-a-chat-agent.mdx rename to src/content/docs/agents/examples/chat-agent.mdx index ee4712430c1cf60..97e0c2ef3cd8229 100644 --- a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx +++ b/src/content/docs/agents/examples/chat-agent.mdx @@ -1,8 +1,8 @@ --- -title: Build a chat agent -pcx_content_type: tutorial +title: Chat agent +pcx_content_type: example sidebar: - order: 4 + order: 1 head: [] description: Build a streaming AI chat agent with tools using Workers AI — no API keys required. --- @@ -347,19 +347,19 @@ Your chat agent has: diff --git a/src/content/docs/agents/examples/code-review-agent.mdx b/src/content/docs/agents/examples/code-review-agent.mdx new file mode 100644 index 000000000000000..a5c67bcffbd0ccd --- /dev/null +++ b/src/content/docs/agents/examples/code-review-agent.mdx @@ -0,0 +1,360 @@ +--- +title: Code review agent +pcx_content_type: example +sidebar: + order: 7 +description: Build an agent that clones repositories, analyzes code with Claude, and posts review comments to GitHub PRs. +reviewed: 2025-10-15 +--- + +import { Render, PackageManagers } from "~/components"; + +Build a code review agent that responds to pull requests, clones the repository in a [Sandbox](/agents/tools/sandbox/), uses Claude to analyze code changes, and posts review comments. + +**Time to complete**: 30 minutes + +## Prerequisites + + + +You'll also need: + +- A [GitHub account](https://github.com/) and [fine-grained personal access token](https://github.com/settings/personal-access-tokens/new) with the following permissions: + - **Repository access**: Select the specific repository you want to test with + - **Permissions** > **Repository permissions**: + - **Metadata**: Read-only (required) + - **Contents**: Read-only (required to clone the repository) + - **Pull requests**: Read and write (required to post review comments) +- An [Anthropic API key](https://console.anthropic.com/) for Claude +- A GitHub repository for testing + +## 1. Create your project + + + +```sh +cd code-review-bot +``` + +## 2. Install dependencies + + + +## 3. Build the webhook handler + +Replace `src/index.ts`: + +```typescript +import { getSandbox, proxyToSandbox, type Sandbox } from "@cloudflare/sandbox"; +import { Octokit } from "@octokit/rest"; +import Anthropic from "@anthropic-ai/sdk"; + +export { Sandbox } from "@cloudflare/sandbox"; + +interface Env { + Sandbox: DurableObjectNamespace; + GITHUB_TOKEN: string; + ANTHROPIC_API_KEY: string; + WEBHOOK_SECRET: string; +} + +export default { + async fetch( + request: Request, + env: Env, + ctx: ExecutionContext, + ): Promise { + const proxyResponse = await proxyToSandbox(request, env); + if (proxyResponse) return proxyResponse; + + const url = new URL(request.url); + + if (url.pathname === "/webhook" && request.method === "POST") { + const signature = request.headers.get("x-hub-signature-256"); + const contentType = request.headers.get("content-type") || ""; + const body = await request.text(); + + // Verify webhook signature + if ( + !signature || + !(await verifySignature(body, signature, env.WEBHOOK_SECRET)) + ) { + return Response.json({ error: "Invalid signature" }, { status: 401 }); + } + + const event = request.headers.get("x-github-event"); + + // Parse payload (GitHub can send as JSON or form-encoded) + let payload; + if (contentType.includes("application/json")) { + payload = JSON.parse(body); + } else { + // Handle form-encoded payload + const params = new URLSearchParams(body); + payload = JSON.parse(params.get("payload") || "{}"); + } + + // Handle opened and reopened PRs + if ( + event === "pull_request" && + (payload.action === "opened" || payload.action === "reopened") + ) { + console.log(`Starting review for PR #${payload.pull_request.number}`); + // Use waitUntil to ensure the review completes even after response is sent + ctx.waitUntil( + reviewPullRequest(payload, env).catch(console.error), + ); + return Response.json({ message: "Review started" }); + } + + return Response.json({ message: "Event ignored" }); + } + + return new Response( + "Code Review Bot\n\nConfigure GitHub webhook to POST /webhook", + ); + }, +}; + +async function verifySignature( + payload: string, + signature: string, + secret: string, +): Promise { + const encoder = new TextEncoder(); + const key = await crypto.subtle.importKey( + "raw", + encoder.encode(secret), + { name: "HMAC", hash: "SHA-256" }, + false, + ["sign"], + ); + + const signatureBytes = await crypto.subtle.sign( + "HMAC", + key, + encoder.encode(payload), + ); + const expected = + "sha256=" + + Array.from(new Uint8Array(signatureBytes)) + .map((b) => b.toString(16).padStart(2, "0")) + .join(""); + + return signature === expected; +} + +async function reviewPullRequest(payload: any, env: Env): Promise { + const pr = payload.pull_request; + const repo = payload.repository; + const octokit = new Octokit({ auth: env.GITHUB_TOKEN }); + const sandbox = getSandbox(env.Sandbox, `review-${pr.number}`); + + try { + // Post initial comment + console.log("Posting initial comment..."); + await octokit.issues.createComment({ + owner: repo.owner.login, + repo: repo.name, + issue_number: pr.number, + body: "Code review in progress...", + }); + // Clone repository + console.log("Cloning repository..."); + const cloneUrl = `https://${env.GITHUB_TOKEN}@github.com/${repo.owner.login}/${repo.name}.git`; + await sandbox.exec( + `git clone --depth=1 --branch=${pr.head.ref} ${cloneUrl} /workspace/repo`, + ); + + // Get changed files + console.log("Fetching changed files..."); + const comparison = await octokit.repos.compareCommits({ + owner: repo.owner.login, + repo: repo.name, + base: pr.base.sha, + head: pr.head.sha, + }); + + const files = []; + for (const file of (comparison.data.files || []).slice(0, 5)) { + if (file.status !== "removed") { + const content = await sandbox.readFile( + `/workspace/repo/${file.filename}`, + ); + files.push({ + path: file.filename, + patch: file.patch || "", + content: content.content, + }); + } + } + + // Generate review with Claude + console.log(`Analyzing ${files.length} files with Claude...`); + const anthropic = new Anthropic({ apiKey: env.ANTHROPIC_API_KEY }); + const response = await anthropic.messages.create({ + model: "claude-sonnet-4-5", + max_tokens: 2048, + messages: [ + { + role: "user", + content: `Review this PR: + +Title: ${pr.title} + +Changed files: +${files.map((f) => `File: ${f.path}\nDiff:\n${f.patch}\n\nContent:\n${f.content.substring(0, 1000)}`).join("\n\n")} + +Provide a brief code review focusing on bugs, security, and best practices.`, + }, + ], + }); + + const review = + response.content[0]?.type === "text" + ? response.content[0].text + : "No review generated"; + + // Post review comment + console.log("Posting review..."); + await octokit.issues.createComment({ + owner: repo.owner.login, + repo: repo.name, + issue_number: pr.number, + body: `## Code Review\n\n${review}\n\n---\n*Generated by Claude*`, + }); + console.log("Review complete!"); + } catch (error: any) { + console.error("Review failed:", error); + await octokit.issues.createComment({ + owner: repo.owner.login, + repo: repo.name, + issue_number: pr.number, + body: `Review failed: ${error.message}`, + }); + } finally { + await sandbox.destroy(); + } +} +``` + +## 4. Set up local environment variables + +Create a `.dev.vars` file in your project root for local development: + +```sh +cat > .dev.vars << EOF +GITHUB_TOKEN=your_github_token_here +ANTHROPIC_API_KEY=your_anthropic_key_here +WEBHOOK_SECRET=your_webhook_secret_here +EOF +``` + +Replace the placeholder values with: + +- `GITHUB_TOKEN`: Your GitHub personal access token with repo permissions +- `ANTHROPIC_API_KEY`: Your API key from the [Anthropic Console](https://console.anthropic.com/) +- `WEBHOOK_SECRET`: A random string (for example: `openssl rand -hex 32`) + +:::note +The `.dev.vars` file is automatically gitignored and only used during local development with `npm run dev`. +::: + +## 5. Expose local server with Cloudflare Tunnel + +To test with real GitHub webhooks locally, use [Cloudflare Tunnel](/cloudflare-one/networks/connectors/cloudflare-tunnel/) to expose your local development server. + +Start the development server: + +```sh +npm run dev +``` + +In a separate terminal, create a tunnel to your local server: + +```sh +cloudflared tunnel --url http://localhost:8787 +``` + +This will output a public URL (for example, `https://example.trycloudflare.com`). Copy this URL for the next step. + +:::note +If you do not have `cloudflared` installed, refer to [Downloads](/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/). +::: + +## 6. Configure GitHub webhook for local testing + +:::note[Important] +Configure this webhook on a **specific GitHub repository** where you will create test pull requests. The bot will only review PRs in repositories where the webhook is configured. +::: + +1. Navigate to your test repository on GitHub +2. Go to **Settings** > **Webhooks** > **Add webhook** +3. Set **Payload URL**: Your Cloudflare Tunnel URL from Step 5 with `/webhook` appended (for example, `https://example.trycloudflare.com/webhook`) +4. Set **Content type**: `application/json` +5. Set **Secret**: Same value you used for `WEBHOOK_SECRET` in your `.dev.vars` file +6. Select **Let me select individual events** → Check **Pull requests** +7. Click **Add webhook** + +## 7. Test locally with a pull request + +Create a test PR: + +```sh +git checkout -b test-review +echo "console.log('test');" > test.js +git add test.js +git commit -m "Add test file" +git push origin test-review +``` + +Open the PR on GitHub. The bot should post a review comment within a few seconds. + +## 8. Deploy to production + +Deploy your Worker: + +```sh +npx wrangler deploy +``` + +Then set your production secrets: + +```sh +# GitHub token (needs repo permissions) +npx wrangler secret put GITHUB_TOKEN + +# Anthropic API key +npx wrangler secret put ANTHROPIC_API_KEY + +# Webhook secret (use the same value from .dev.vars) +npx wrangler secret put WEBHOOK_SECRET +``` + +## 9. Update webhook for production + +1. Go to your repository **Settings** > **Webhooks** +2. Click on your existing webhook +3. Update **Payload URL** to your deployed Worker URL: `https://code-review-bot.YOUR_SUBDOMAIN.workers.dev/webhook` +4. Click **Update webhook** + +Your bot is now running in production and will review all new pull requests automatically. + +## What you built + +A code review agent that: + +- Receives webhook events from GitHub +- Clones repositories in isolated sandboxes +- Uses Claude to analyze code changes +- Posts review comments automatically + +## Next steps + +- [Git operations](/sandbox/api/files/#gitcheckout) - Advanced repository handling +- [Sessions API](/sandbox/api/sessions/) - Manage long-running sandbox operations +- [GitHub Apps](https://docs.github.com/en/apps) - Build a proper GitHub App diff --git a/src/content/docs/agents/examples/document-agent.mdx b/src/content/docs/agents/examples/document-agent.mdx new file mode 100644 index 000000000000000..f077ac7081f97bc --- /dev/null +++ b/src/content/docs/agents/examples/document-agent.mdx @@ -0,0 +1,104 @@ +--- +title: Document agent +pcx_content_type: example +sidebar: + order: 6 +--- + +import { + MetaInfo, + Render, + Type, + TypeScriptExample, + WranglerConfig, +} from "~/components"; + +Build a document agent that uses Retrieval Augmented Generation (RAG) to retrieve relevant information and augment [calls to AI models](/agents/runtime/operations/using-ai-models/). Store a user's chat history to use as context for future conversations, summarize documents to bootstrap an Agent's knowledge base, and/or use data from your Agent's [browser](/agents/tools/browser/) tasks to enhance your Agent's capabilities. + +For long-running document ingestion, indexing, or background research tasks, pair RAG with [durable execution with fibers](/agents/runtime/execution/durable-execution/). Fibers let the agent checkpoint progress with `stash()` and recover work with `onFiberRecovered()` if the Durable Object is evicted mid-task. + +You can use the Agent's own [SQL database](/agents/runtime/lifecycle/state/) as the source of truth for your data and store embeddings in [Vectorize](/vectorize/) (or any other vector-enabled database) to allow your Agent to retrieve relevant information. + +### Vector search + +:::note + +If you're brand-new to vector databases and Vectorize, visit the [Vectorize tutorial](/vectorize/get-started/intro/) to learn the basics, including how to create an index, insert data, and generate embeddings. + +::: + +You can query a vector index (or indexes) from any method on your Agent: any Vectorize index you attach is available on `this.env` within your Agent. If you've [associated metadata](/vectorize/best-practices/insert-vectors/#metadata) with your vectors that maps back to data stored in your Agent, you can then look up the data directly within your Agent using `this.sql`. + +Here's an example of how to give an Agent retrieval capabilities: + + + +```ts +import { Agent } from "agents"; + +interface Env { + AI: Ai; + VECTOR_DB: Vectorize; +} + +export class RAGAgent extends Agent { + // Other methods on our Agent + // ... + // + async queryKnowledge(userQuery: string) { + // Turn a query into an embedding + const queryVector = await this.env.AI.run("@cf/baai/bge-base-en-v1.5", { + text: [userQuery], + }); + + // Retrieve results from our vector index + let searchResults = await this.env.VECTOR_DB.query(queryVector.data[0], { + topK: 10, + returnMetadata: "all", + }); + + let knowledge = []; + for (const match of searchResults.matches) { + console.log(match.metadata); + knowledge.push(match.metadata); + } + + // Use the metadata to re-associate the vector search results + // with data in our Agent's SQL database + let results = this + .sql`SELECT * FROM knowledge WHERE id IN (${knowledge.map((k) => k.id)})`; + + // Return them + return results; + } +} +``` + + + +You'll also need to connect your Agent to your vector indexes: + + + +```jsonc +{ + // ... + "vectorize": [ + { + "binding": "VECTOR_DB", + "index_name": "your-vectorize-index-name", + }, + ], + // ... +} +``` + + + +If you have multiple indexes you want to make available, you can provide an array of `vectorize` bindings. + +#### Next steps + +- Learn more on how to [combine Vectorize and Workers AI](/vectorize/get-started/embeddings/) +- Review the [Vectorize query API](/vectorize/reference/client-api/) +- Use [metadata filtering](/vectorize/reference/metadata-filtering/) to add context to your results diff --git a/src/content/docs/agents/examples/email-agent.mdx b/src/content/docs/agents/examples/email-agent.mdx new file mode 100644 index 000000000000000..a1366b861246bc9 --- /dev/null +++ b/src/content/docs/agents/examples/email-agent.mdx @@ -0,0 +1,763 @@ +--- +title: Email agent +pcx_content_type: example +sidebar: + order: 4 +--- + +import { TypeScriptExample, WranglerConfig, LinkCard } from "~/components"; + +Agents can send and receive email with Cloudflare [Email Service](/email-routing/email-workers/). This guide shows how to send outbound email with the Workers binding, route inbound mail into Agents, and handle follow-up replies securely. + +## Prerequisites + +Before using email with Agents, you need: + +1. A domain onboarded to [Cloudflare Email Service](/email-routing/). +2. A `send_email` binding in `wrangler.jsonc` for outbound email. +3. An Email Service routing rule that sends inbound mail to your Worker. +4. Optional: an `EMAIL_SECRET` secret if you want secure reply routing. + +### Domain setup + +1. Log in to the [Cloudflare Dashboard](https://dash.cloudflare.com). +2. Go to **Compute & AI** > **Email Service**. +3. Select **Onboard Domain** and choose your domain. +4. Add the DNS records (SPF and DKIM) to authorize sending. + +DNS changes usually complete within 5-15 minutes for domains using Cloudflare DNS, but can take up to 24 hours to propagate globally. + +### Wrangler configuration + +Add the email binding to your Worker: + + + +```toml +[[send_email]] +name = "EMAIL" +remote = true +``` + + + +The `remote = true` option lets you call the real Email Service API during local development with `wrangler dev`. + +## Quick start + + + +```ts +import { Agent, callable, routeAgentEmail } from "agents"; +import { createAddressBasedEmailResolver, type AgentEmail } from "agents/email"; +import PostalMime from "postal-mime"; + +export class EmailAgent extends Agent { + @callable() + async sendWelcomeEmail(to: string) { + await this.sendEmail({ + binding: this.env.EMAIL, + to, + from: "support@yourdomain.com", + replyTo: "support@yourdomain.com", + subject: "Welcome to our service", + text: "Thanks for signing up. Reply to this email if you need help.", + }); + } + + async onEmail(email: AgentEmail) { + const raw = await email.getRaw(); + const parsed = await PostalMime.parse(raw); + + console.log("Received email from:", email.from); + console.log("Subject:", parsed.subject); + + await this.replyToEmail(email, { + fromName: "Support Agent", + body: "Thanks for your email! We received it.", + }); + } +} + +export default { + async email(message, env) { + await routeAgentEmail(message, env, { + resolver: createAddressBasedEmailResolver("EmailAgent"), + }); + }, +} satisfies ExportedHandler; +``` + + + +## Sending outbound email + +### Using `sendEmail()` + +`sendEmail()` sends outbound email through a `send_email` binding that you pass explicitly. It automatically injects agent routing headers (`X-Agent-Name`, `X-Agent-ID`) into every message, and optionally signs them with HMAC-SHA256 so that replies can be routed back to the same agent instance. + + + +```ts +class MyAgent extends Agent { + @callable() + async sendReceipt(to: string, orderId: string) { + const result = await this.sendEmail({ + binding: this.env.EMAIL, + to, + from: { email: "billing@yourdomain.com", name: "Billing Bot" }, + replyTo: "billing@yourdomain.com", + subject: `Receipt for order ${orderId}`, + text: `Your receipt for order ${orderId} is ready.`, + secret: this.env.EMAIL_SECRET, + }); + + return result.messageId; + } +} +``` + + + +When `secret` is provided, the agent signs the routing headers so that replies verified by `createSecureReplyEmailResolver` route back to the same agent instance. + +Set `replyTo` to the mailbox that routes back to your Worker when you want recipients to continue the conversation with the same agent. + +## Routing inbound mail + +Resolvers determine which Agent instance receives an incoming email. Choose the resolver that matches your use case. + +For basic Email Service sending and receiving, `createAddressBasedEmailResolver()` is enough. The secure reply resolver below is optional and specific to Agents SDK reply signing, not a requirement of Email Service itself. + +### `createAddressBasedEmailResolver` + +Recommended for inbound mail. Routes emails based on the recipient address. + + + +```ts +import { createAddressBasedEmailResolver } from "agents/email"; + +const resolver = createAddressBasedEmailResolver("EmailAgent"); +``` + + + +**Routing logic:** + +| Recipient Address | Agent Name | Agent ID | +| --------------------------------------- | ---------------------- | --------- | +| `support@example.com` | `EmailAgent` (default) | `support` | +| `sales@example.com` | `EmailAgent` (default) | `sales` | +| `NotificationAgent+user123@example.com` | `NotificationAgent` | `user123` | + +The sub-address format (`agent+id@domain`) allows routing to different agent namespaces and instances from a single email domain. + +:::note +Agent class names in the recipient address are matched case-insensitively. Email infrastructure often lowercases addresses, so `NotificationAgent+user123@example.com` and `notificationagent+user123@example.com` both route to the `NotificationAgent` class. +::: + +### `createSecureReplyEmailResolver` + +For reply flows with signature verification. Verifies that incoming emails are authentic replies to your outbound emails, preventing attackers from routing emails to arbitrary agent instances. + + + +```ts +import { createSecureReplyEmailResolver } from "agents/email"; + +const resolver = createSecureReplyEmailResolver(env.EMAIL_SECRET); +``` + + + +When your agent sends an email with `replyToEmail()` or `sendEmail()` and a `secret`, it signs the routing headers with a timestamp. When a reply comes back, this resolver verifies the signature and checks that it has not expired before routing. + +**Options:** + + + +```ts +const resolver = createSecureReplyEmailResolver(env.EMAIL_SECRET, { + // Maximum age of signature in seconds (default: 30 days) + maxAge: 7 * 24 * 60 * 60, // 7 days + + // Callback for logging/debugging signature failures + onInvalidSignature: (email, reason) => { + console.warn(`Invalid signature from ${email.from}: ${reason}`); + // reason can be: "missing_headers", "expired", "invalid", "malformed_timestamp" + }, +}); +``` + + + +**When to use:** If your agent initiates email conversations and you need replies to route back to the same agent instance securely. + +### `createCatchAllEmailResolver` + +For single-instance routing. Routes all emails to a specific agent instance regardless of the recipient address. + + + +```ts +import { createCatchAllEmailResolver } from "agents/email"; + +const resolver = createCatchAllEmailResolver("EmailAgent", "default"); +``` + + + +**When to use:** When you have a single agent instance that handles all emails (for example, a shared inbox). + +### Combining resolvers + +You can combine resolvers to handle different scenarios: + + + +```ts +export default { + async email(message, env) { + const secureReplyResolver = createSecureReplyEmailResolver( + env.EMAIL_SECRET, + ); + const addressResolver = createAddressBasedEmailResolver("EmailAgent"); + + await routeAgentEmail(message, env, { + resolver: async (email, env) => { + // First, check if this is a signed reply + const replyRouting = await secureReplyResolver(email, env); + if (replyRouting) return replyRouting; + + // Otherwise, route based on recipient address + return addressResolver(email, env); + }, + + // Handle emails that do not match any routing rule + onNoRoute: (email) => { + console.warn(`No route found for email from ${email.from}`); + email.setReject("Unknown recipient"); + }, + }); + }, +} satisfies ExportedHandler; +``` + + + +## Handling emails in your Agent + +### The `AgentEmail` interface + +When your agent's `onEmail` method is called, it receives an `AgentEmail` object: + +```ts +type AgentEmail = { + from: string; // Sender's email address + to: string; // Recipient's email address + headers: Headers; // Email headers (subject, message-id, etc.) + rawSize: number; // Size of the raw email in bytes + + getRaw(): Promise; // Get the full raw email content + reply(options): Promise; // Send a reply + forward(rcptTo, headers?): Promise; // Forward the email + setReject(reason): void; // Reject the email with a reason +}; +``` + +### Parsing email content + +Use a library like [postal-mime](https://www.npmjs.com/package/postal-mime) to parse the raw email: + + + +```ts +import PostalMime from "postal-mime"; + +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + const raw = await email.getRaw(); + const parsed = await PostalMime.parse(raw); + + console.log("Subject:", parsed.subject); + console.log("Text body:", parsed.text); + console.log("HTML body:", parsed.html); + console.log("Attachments:", parsed.attachments); + } +} +``` + + + +### Detecting auto-reply emails + +Use `isAutoReplyEmail()` to detect auto-reply emails and avoid mail loops: + + + +```ts +import { isAutoReplyEmail } from "agents/email"; +import PostalMime from "postal-mime"; + +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + const raw = await email.getRaw(); + const parsed = await PostalMime.parse(raw); + + // Detect auto-reply emails to avoid sending duplicate responses + if (isAutoReplyEmail(parsed.headers)) { + console.log("Skipping auto-reply email"); + return; + } + + // Process the email... + } +} +``` + + + +This checks for standard RFC 3834 headers (`Auto-Submitted`, `X-Auto-Response-Suppress`, `Precedence`) that indicate an email is an auto-reply. + +### Replying to emails + +Use `this.replyToEmail()` to send a reply through the inbound email's reply channel: + + + +```ts +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + await this.replyToEmail(email, { + fromName: "Support Bot", // Display name for the sender + subject: "Re: Your inquiry", // Optional, defaults to "Re: " + body: "Thanks for contacting us!", // Email body + contentType: "text/plain", // Optional, defaults to "text/plain" + headers: { + // Optional custom headers + "X-Custom-Header": "value", + }, + secret: this.env.EMAIL_SECRET, // Optional, signs headers for secure reply routing + }); + } +} +``` + + + +### Deferred replies + +`replyToEmail()` requires a live `AgentEmail` object, so it only works inside `onEmail()`. If you need to reply later — from a scheduled task, a callable method, or after a human-in-the-loop approval — store the sender info in state and use `sendEmail()`: + + + +```ts +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + const raw = await email.getRaw(); + const parsed = await PostalMime.parse(raw); + + this.setState({ + ...this.state, + pendingReply: { + to: email.from, + messageId: parsed.messageId, + subject: parsed.subject, + }, + }); + } + + @callable() + async sendDelayedReply(body: string) { + const { pendingReply } = this.state; + if (!pendingReply) return; + + await this.sendEmail({ + binding: this.env.EMAIL, + to: pendingReply.to, + from: "support@yourdomain.com", + subject: `Re: ${pendingReply.subject}`, + text: body, + inReplyTo: pendingReply.messageId, + secret: this.env.EMAIL_SECRET, + }); + } +} +``` + + + +The `inReplyTo` field sets the `In-Reply-To` header so mail clients thread the reply correctly. The `secret` signs the agent routing headers so that follow-up replies route back to this agent instance via `createSecureReplyEmailResolver`. + +### Forwarding emails + + + +```ts +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + await email.forward("admin@example.com"); + } +} +``` + + + +### Rejecting emails + + + +```ts +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + if (isSpam(email)) { + email.setReject("Message rejected as spam"); + return; + } + // Process the email... + } +} +``` + + + +## Error handling + +When sending emails via `sendEmail()` or `replyToEmail()`, handle these common errors: + + + +```ts +class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + try { + await this.replyToEmail(email, { + fromName: "Support Bot", + body: "Thanks for your email!", + }); + } catch (error) { + switch (error.code) { + case "E_SENDER_NOT_VERIFIED": + console.error("Sender domain not verified. Verify in dashboard."); + break; + case "E_RATE_LIMIT_EXCEEDED": + console.error("Rate limit exceeded. Back off and retry."); + break; + case "E_DAILY_LIMIT_EXCEEDED": + console.error("Daily sending quota reached."); + break; + case "E_CONTENT_TOO_LARGE": + console.error("Email content exceeds size limit."); + break; + default: + console.error("Email sending failed:", error.message); + } + } + } +} +``` + + + +### Common error codes + +| Error Code | Description | Solution | +| ------------------------- | ---------------------------------- | ------------------------------------ | +| `E_SENDER_NOT_VERIFIED` | Sender domain/address not verified | Verify in Cloudflare dashboard | +| `E_RATE_LIMIT_EXCEEDED` | Sending rate limit reached | Implement exponential backoff | +| `E_DAILY_LIMIT_EXCEEDED` | Daily quota exceeded | Wait for quota reset or upgrade plan | +| `E_CONTENT_TOO_LARGE` | Email exceeds size limit | Reduce attachments or content | +| `E_RECIPIENT_NOT_ALLOWED` | Recipient not in allowed list | Check allowed destination addresses | +| `E_RECIPIENT_SUPPRESSED` | Recipient is on suppression list | Remove from suppression list | +| `E_VALIDATION_ERROR` | Invalid email format | Check email addresses | +| `E_TOO_MANY_RECIPIENTS` | More than 50 recipients | Split into multiple sends | + +## Secure reply routing + +When your agent sends emails and expects replies, use secure reply routing to prevent attackers from forging headers to route emails to arbitrary agent instances. + +### How it works + +1. **Outbound:** When you call `replyToEmail()` or `sendEmail()` with a `secret`, the agent signs the routing headers (`X-Agent-Name`, `X-Agent-ID`) using HMAC-SHA256. +2. **Inbound:** `createSecureReplyEmailResolver` verifies the signature before routing. +3. **Enforcement:** If an email was routed via the secure resolver, `replyToEmail()` requires a secret (or explicit `null` to opt-out). + +### Setup + +1. Add a secret to your Worker: + + + + ```toml + [vars] + EMAIL_SECRET = "change-me-in-production" + ``` + + + + For production, use Wrangler secrets instead: + + ```sh + npx wrangler secret put EMAIL_SECRET + ``` + +2. Use the combined resolver pattern: + + + + ```ts + export default { + async email(message, env) { + const secureReplyResolver = createSecureReplyEmailResolver( + env.EMAIL_SECRET, + ); + const addressResolver = createAddressBasedEmailResolver("EmailAgent"); + + await routeAgentEmail(message, env, { + resolver: async (email, env) => { + const replyRouting = await secureReplyResolver(email, env); + if (replyRouting) return replyRouting; + return addressResolver(email, env); + }, + }); + }, + } satisfies ExportedHandler; + ``` + + + +3. Sign outbound emails: + + + + ```ts + class MyAgent extends Agent { + async onEmail(email: AgentEmail) { + await this.replyToEmail(email, { + fromName: "My Agent", + body: "Thanks for your email!", + secret: this.env.EMAIL_SECRET, // Signs the routing headers + }); + } + } + ``` + + + +### Enforcement behavior + +When an email is routed via `createSecureReplyEmailResolver`, the `replyToEmail()` method enforces signing: + +| `secret` value | Behavior | +| --------------------- | ------------------------------------------------------------ | +| `"my-secret"` | Signs headers (secure) | +| `undefined` (omitted) | **Throws error** - must provide secret or explicit opt-out | +| `null` | Allowed but not recommended - explicitly opts out of signing | + +## Complete example + +Here is a complete Email Service agent that sends outbound mail and handles secure replies: + + + +```ts +import { Agent, callable, routeAgentEmail } from "agents"; +import { + createAddressBasedEmailResolver, + createSecureReplyEmailResolver, + type AgentEmail, +} from "agents/email"; +import PostalMime from "postal-mime"; + +interface Env { + EmailAgent: DurableObjectNamespace; + EMAIL: SendEmail; + EMAIL_SECRET: string; +} + +export class EmailAgent extends Agent { + @callable() + async sendWelcome(to: string) { + return this.sendEmail({ + binding: this.env.EMAIL, + to, + from: "support@yourdomain.com", + subject: "Welcome!", + text: "Thanks for signing up.", + secret: this.env.EMAIL_SECRET, + }); + } + + async onEmail(email: AgentEmail) { + const raw = await email.getRaw(); + const parsed = await PostalMime.parse(raw); + + console.log(`Email from ${email.from}: ${parsed.subject}`); + + const emails = this.state.emails || []; + emails.push({ + from: email.from, + subject: parsed.subject, + receivedAt: new Date().toISOString(), + }); + this.setState({ ...this.state, emails }); + + await this.replyToEmail(email, { + fromName: "Support Bot", + body: `Thanks for your email! We received: "${parsed.subject}"`, + secret: this.env.EMAIL_SECRET, + }); + } +} + +export default { + async email(message, env: Env) { + const secureReplyResolver = createSecureReplyEmailResolver( + env.EMAIL_SECRET, + { + maxAge: 7 * 24 * 60 * 60, // 7 days + onInvalidSignature: (email, reason) => { + console.warn(`Invalid signature from ${email.from}: ${reason}`); + }, + }, + ); + const addressResolver = createAddressBasedEmailResolver("EmailAgent"); + + await routeAgentEmail(message, env, { + resolver: async (email, env) => { + const replyRouting = await secureReplyResolver(email, env); + if (replyRouting) return replyRouting; + return addressResolver(email, env); + }, + onNoRoute: (email) => { + console.warn(`No route found for email from ${email.from}`); + email.setReject("Unknown recipient"); + }, + }); + }, +} satisfies ExportedHandler; +``` + + + +## API reference + +### `sendEmail` + +```ts +async sendEmail(options: { + binding: EmailSendBinding; + to: string | string[]; + from: string | { email: string; name?: string }; + subject: string; + text?: string; + html?: string; + replyTo?: string | { email: string; name?: string }; + cc?: string | string[]; + bcc?: string | string[]; + inReplyTo?: string; + headers?: Record; + secret?: string; +}): Promise; +``` + +Send an outbound email through the Email Service binding. Automatically injects `X-Agent-Name` and `X-Agent-ID` headers. When `secret` is provided, signs headers with HMAC-SHA256 for secure reply routing. + +| Option | Description | +| ----------- | ------------------------------------------------------------------------- | +| `binding` | The `send_email` binding (for example, `this.env.EMAIL`). Required. | +| `to` | Recipient address or array of addresses | +| `from` | Sender address, or `\{ email, name \}` object | +| `subject` | Email subject line | +| `text` | Plain text body (at least one of `text`/`html` required) | +| `html` | HTML body (at least one of `text`/`html` required) | +| `replyTo` | Reply-to address for the recipient | +| `cc` | CC recipient(s) | +| `bcc` | BCC recipient(s) | +| `inReplyTo` | Message-ID for threading (sets the `In-Reply-To` header) | +| `headers` | Additional custom headers (agent headers take precedence if they collide) | +| `secret` | Secret for HMAC signing of agent routing headers | + +### `routeAgentEmail` + +```ts +function routeAgentEmail( + email: ForwardableEmailMessage, + env: Env, + options: { + resolver: EmailResolver; + onNoRoute?: (email: ForwardableEmailMessage) => void | Promise; + }, +): Promise; +``` + +Routes an incoming email to the appropriate Agent based on the resolver's decision. + +| Option | Description | +| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `resolver` | Function that determines which agent to route the email to | +| `onNoRoute` | Optional callback invoked when no routing information is found. Use this to reject the email or perform custom handling. If not provided, a warning is logged and the email is dropped. | + +### `createSecureReplyEmailResolver` + +```ts +function createSecureReplyEmailResolver( + secret: string, + options?: { + maxAge?: number; + onInvalidSignature?: ( + email: ForwardableEmailMessage, + reason: SignatureFailureReason, + ) => void; + }, +): EmailResolver; + +type SignatureFailureReason = + | "missing_headers" + | "expired" + | "invalid" + | "malformed_timestamp"; +``` + +Creates a resolver for routing email replies with signature verification. + +| Option | Description | +| -------------------- | ------------------------------------------------------------------------ | +| `secret` | Secret key for HMAC verification (must match the key used to sign) | +| `maxAge` | Maximum age of signature in seconds (default: 30 days / 2592000 seconds) | +| `onInvalidSignature` | Optional callback for logging when signature verification fails | + +### `signAgentHeaders` + +```ts +function signAgentHeaders( + secret: string, + agentName: string, + agentId: string, +): Promise>; +``` + +Manually sign agent routing headers. Returns an object with `X-Agent-Name`, `X-Agent-ID`, `X-Agent-Sig`, and `X-Agent-Sig-Ts` headers. + +Useful when sending emails through external services while maintaining secure reply routing. The signature includes a timestamp and will be valid for 30 days by default. + +## Next steps + + + + + + diff --git a/src/content/docs/agents/api-reference/index.mdx b/src/content/docs/agents/examples/index.mdx similarity index 55% rename from src/content/docs/agents/api-reference/index.mdx rename to src/content/docs/agents/examples/index.mdx index 3588c9aa8c61d2c..a2852fa3c62408d 100644 --- a/src/content/docs/agents/api-reference/index.mdx +++ b/src/content/docs/agents/examples/index.mdx @@ -1,14 +1,14 @@ --- -title: API Reference +title: Examples pcx_content_type: navigation sidebar: - order: 5 + order: 8 group: hideIndex: true --- import { DirectoryListing } from "~/components"; -Learn more about what Agents can do, the `Agent` class, and the APIs that Agents expose: +End-to-end examples showing how to build complete agents. diff --git a/src/content/docs/agents/examples/payment-agent.mdx b/src/content/docs/agents/examples/payment-agent.mdx new file mode 100644 index 000000000000000..61923d7a2df288c --- /dev/null +++ b/src/content/docs/agents/examples/payment-agent.mdx @@ -0,0 +1,64 @@ +--- +title: Payment agent +pcx_content_type: example +sidebar: + order: 5 +description: Use withX402Client to pay for resources from a Cloudflare Agent. +--- + +Build an agent that can pay for x402-protected tools. The Agents SDK includes an MCP client that can pay for protected resources from your Agents or any MCP client connection. + +```ts +import { Agent } from "agents"; +import { withX402Client } from "agents/x402"; +import { privateKeyToAccount } from "viem/accounts"; + +export class MyAgent extends Agent { + // Your Agent definitions... + + async onStart() { + const { id } = await this.mcp.connect(`${this.env.WORKER_URL}/mcp`); + const account = privateKeyToAccount(this.env.MY_PRIVATE_KEY); + + this.x402Client = withX402Client(this.mcp.mcpConnections[id].client, { + network: "base-sepolia", + account, + }); + } + + onPaymentRequired(paymentRequirements): Promise { + // Your human-in-the-loop confirmation flow... + } + + async onToolCall(toolName: string, toolArgs: unknown) { + // The first parameter is the confirmation callback. + // Set to `null` for the agent to pay automatically. + return await this.x402Client.callTool(this.onPaymentRequired, { + name: toolName, + arguments: toolArgs, + }); + } +} +``` + +For a complete working example, see [x402-mcp on GitHub](https://github.com/cloudflare/agents/tree/main/examples/x402-mcp). + +## Environment setup + +Store your private key securely: + +```sh +# Local development (.dev.vars) +MY_PRIVATE_KEY="0x..." + +# Production +npx wrangler secret put MY_PRIVATE_KEY +``` + +Use `base-sepolia` for testing. Get test USDC from the [Circle faucet](https://faucet.circle.com/). + +## Related + +- [Charge for MCP tools](/agents/tools/payments/x402/charge-for-mcp-tools/) — Build servers that charge for tools +- [Pay from coding tools](/agents/tools/payments/x402/pay-with-tool-plugins/) — Add payments to OpenCode or Claude Code +- [Human-in-the-loop guide](/agents/concepts/human-in-the-loop/) — Implement approval workflows diff --git a/src/content/docs/agents/guides/slack-agent.mdx b/src/content/docs/agents/examples/slack-agent.mdx similarity index 98% rename from src/content/docs/agents/guides/slack-agent.mdx rename to src/content/docs/agents/examples/slack-agent.mdx index 568eff53b577d5a..bbb2cf900becc68 100644 --- a/src/content/docs/agents/guides/slack-agent.mdx +++ b/src/content/docs/agents/examples/slack-agent.mdx @@ -1,8 +1,8 @@ --- -pcx_content_type: concept -title: Build a Slack Agent +pcx_content_type: example +title: Slack agent sidebar: - order: 5 + order: 1 --- import { @@ -453,11 +453,11 @@ export class MyAgent extends SlackAgent { ## Next steps - Add [Slack Interactive Components](https://api.slack.com/interactivity) (buttons, modals) -- Connect your Agent to an [MCP server](/agents/api-reference/mcp-client-api/) +- Connect your Agent to an [MCP server](/agents/mcp/apis/client-api/) - Add rate limiting to prevent abuse - Implement conversation state management - Use [Workers Analytics Engine](/analytics/analytics-engine/) to track usage -- Add [schedules](/agents/api-reference/schedule-tasks/) for scheduled tasks +- Add [schedules](/agents/runtime/execution/schedule-tasks/) for scheduled tasks ## Related resources diff --git a/src/content/docs/agents/guides/build-a-voice-agent.mdx b/src/content/docs/agents/examples/voice-agent.mdx similarity index 97% rename from src/content/docs/agents/guides/build-a-voice-agent.mdx rename to src/content/docs/agents/examples/voice-agent.mdx index 71893f6ed55808e..f8dbe56e6a5bf26 100644 --- a/src/content/docs/agents/guides/build-a-voice-agent.mdx +++ b/src/content/docs/agents/examples/voice-agent.mdx @@ -1,8 +1,8 @@ --- -title: Build a voice agent +title: Voice agent pcx_content_type: tutorial sidebar: - order: 15 + order: 2 products: - workers difficulty: Intermediate @@ -290,18 +290,18 @@ export class MyVoiceAgent extends VoiceAgent { diff --git a/src/content/docs/agents/getting-started/add-to-existing-project.mdx b/src/content/docs/agents/getting-started/add-to-existing-project.mdx index 1c4f3101cc2dbed..e06f8a839e2e2c3 100644 --- a/src/content/docs/agents/getting-started/add-to-existing-project.mdx +++ b/src/content/docs/agents/getting-started/add-to-existing-project.mdx @@ -12,7 +12,7 @@ import { LinkCard, } from "~/components"; -This guide shows how to add agents to an existing Cloudflare Workers project. If you are starting fresh, refer to [Building a chat agent](/agents/getting-started/build-a-chat-agent/) instead. +This guide shows how to add agents to an existing Cloudflare Workers project. If you are starting fresh, refer to [Building a chat agent](/agents/examples/chat-agent/) instead. ## Prerequisites @@ -143,7 +143,7 @@ export default defineConfig({ If your project does not use Vite, the `tsconfig.json` change alone is sufficient — your bundler must support TC39 decorators (stage 3, version `2023-11`). -For more details, refer to the [TypeScript configuration](/agents/api-reference/configuration/#typescript-configuration) and [Vite configuration](/agents/api-reference/configuration/#vite-configuration) reference. +For more details, refer to the [TypeScript configuration](/agents/runtime/operations/configuration/#typescript-configuration) and [Vite configuration](/agents/runtime/operations/configuration/#vite-configuration) reference. ## 5. Export the Agent class @@ -268,7 +268,7 @@ npx wrangler types This creates a type definition file with all your bindings typed, including your agent Durable Object namespaces. The `Agent` class defaults to using the generated `Env` type, so you do not need to pass it as a type parameter — `extends Agent` is sufficient unless you need to pass a second type parameter for state (for example, `Agent`). -Refer to [Configuration](/agents/api-reference/configuration/#generating-types) for more details on type generation. +Refer to [Configuration](/agents/runtime/operations/configuration/#generating-types) for more details on type generation. ## 8. Connect from the frontend @@ -423,7 +423,7 @@ const agentResponse = await routeAgentRequest(request, env, { -Refer to [Routing](/agents/api-reference/routing/) for more options including CORS, custom instance naming, and location hints. +Refer to [Routing](/agents/runtime/communication/routing/) for more options including CORS, custom instance naming, and location hints. ### Accessing agents from server code @@ -505,24 +505,24 @@ Check that: diff --git a/src/content/docs/agents/getting-started/prompting.mdx b/src/content/docs/agents/getting-started/prompting.mdx deleted file mode 100644 index ec20e7d4ac0f13a..000000000000000 --- a/src/content/docs/agents/getting-started/prompting.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: Prompt an AI model -external_link: /workers/get-started/prompting/ -sidebar: - order: 5 -head: [] -description: Use the Workers "mega prompt" to build a Agents using your preferred AI tools and/or IDEs. The prompt understands the Agents SDK APIs, best practices and guidelines, and makes it easier to build valid Agents and Workers. ---- diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index f3f66c69ce0f78d..4bea0cc212cbad1 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -331,34 +331,34 @@ Now that you have a working agent, explore these topics: | Learn how to | Refer to | | ------------------------ | --------------------------------------------------------- | -| Add AI/LLM capabilities | [Using AI models](/agents/api-reference/using-ai-models/) | -| Expose tools via MCP | [MCP servers](/agents/api-reference/mcp-agent-api/) | -| Run background tasks | [Schedule tasks](/agents/api-reference/schedule-tasks/) | -| Handle emails | [Email routing](/agents/api-reference/email/) | -| Use Cloudflare Workflows | [Run Workflows](/agents/api-reference/run-workflows/) | +| Add AI/LLM capabilities | [Using AI models](/agents/runtime/operations/using-ai-models/) | +| Expose tools via MCP | [MCP servers](/agents/mcp/apis/agent-api/) | +| Run background tasks | [Schedule tasks](/agents/runtime/execution/schedule-tasks/) | +| Handle emails | [Email routing](/agents/communication-channels/email/) | +| Use Cloudflare Workflows | [Run Workflows](/agents/runtime/execution/run-workflows/) | ### Explore more diff --git a/src/content/docs/agents/guides/human-in-the-loop.mdx b/src/content/docs/agents/guides/human-in-the-loop.mdx deleted file mode 100644 index f61318f630b1ce0..000000000000000 --- a/src/content/docs/agents/guides/human-in-the-loop.mdx +++ /dev/null @@ -1,554 +0,0 @@ ---- -title: Human-in-the-loop patterns -pcx_content_type: how-to -sidebar: - order: 3 -description: Implement human-in-the-loop functionality using Cloudflare Agents for workflow approvals and MCP elicitation ---- - -import { TypeScriptExample, WranglerConfig, LinkCard } from "~/components"; - -Human-in-the-loop (HITL) patterns allow agents to pause execution and wait for human approval, confirmation, or input before proceeding. This is essential for compliance, safety, and oversight in agentic systems. - -## Why human-in-the-loop? - -- **Compliance**: Regulatory requirements may mandate human approval for certain actions -- **Safety**: High-stakes operations (payments, deletions, external communications) need oversight -- **Quality**: Human review catches errors AI might miss -- **Trust**: Users feel more confident when they can approve critical actions - -### Common use cases - -| Use Case | Example | -| ------------------- | ------------------------------------ | -| Financial approvals | Expense reports, payment processing | -| Content moderation | Publishing, email sending | -| Data operations | Bulk deletions, exports | -| AI tool execution | Confirming tool calls before running | -| Access control | Granting permissions, role changes | - -## Choosing a pattern - -Cloudflare provides two main patterns for human-in-the-loop: - -| Pattern | Best for | Key API | -| --------------------- | -------------------------------------------- | ------------------- | -| **Workflow approval** | Multi-step processes, durable approval gates | `waitForApproval()` | -| **MCP elicitation** | MCP servers requesting structured user input | `elicitInput()` | - -Decision guide: - -- Use **Workflow approval** when you need durable, multi-step processes with approval gates that can wait hours, days, or weeks -- Use **MCP elicitation** when building MCP servers that need to request additional structured input from users during tool execution - -## Workflow-based approval - -For durable, multi-step processes, use [Cloudflare Workflows](/workflows/) with the `waitForApproval()` method. The workflow pauses until a human approves or rejects. - -### Basic pattern - - - -```ts -import { Agent } from "agents"; -import { AgentWorkflow } from "agents/workflows"; -import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows"; - -type ExpenseParams = { - amount: number; - description: string; - requestedBy: string; -}; - -export class ExpenseWorkflow extends AgentWorkflow< - ExpenseAgent, - ExpenseParams -> { - async run(event: AgentWorkflowEvent, step: AgentWorkflowStep) { - const expense = event.payload; - - // Step 1: Validate the expense - const validated = await step.do("validate", async () => { - if (expense.amount <= 0) { - throw new Error("Invalid expense amount"); - } - return { ...expense, validatedAt: Date.now() }; - }); - - // Step 2: Report that we are waiting for approval - await this.reportProgress({ - step: "approval", - status: "pending", - message: `Awaiting approval for $${expense.amount}`, - }); - - // Step 3: Wait for human approval (pauses the workflow) - const approval = await this.waitForApproval<{ approvedBy: string }>(step, { - timeout: "7 days", - }); - - console.log(`Approved by: ${approval?.approvedBy}`); - - // Step 4: Process the approved expense - const result = await step.do("process", async () => { - return { expenseId: crypto.randomUUID(), ...validated }; - }); - - await step.reportComplete(result); - return result; - } -} -``` - - - -### Agent methods for approval - -The agent provides methods to approve or reject waiting workflows: - - - -```ts -import { Agent, callable } from "agents"; - -type PendingApproval = { - workflowId: string; - amount: number; - description: string; - requestedBy: string; - requestedAt: number; -}; - -type ExpenseState = { - pendingApprovals: PendingApproval[]; -}; - -export class ExpenseAgent extends Agent { - initialState: ExpenseState = { - pendingApprovals: [], - }; - - // Approve a waiting workflow - @callable() - async approve(workflowId: string, approvedBy: string): Promise { - await this.approveWorkflow(workflowId, { - reason: "Expense approved", - metadata: { approvedBy, approvedAt: Date.now() }, - }); - - // Update state to reflect approval - this.setState({ - ...this.state, - pendingApprovals: this.state.pendingApprovals.filter( - (p) => p.workflowId !== workflowId, - ), - }); - } - - // Reject a waiting workflow - @callable() - async reject(workflowId: string, reason: string): Promise { - await this.rejectWorkflow(workflowId, { reason }); - - this.setState({ - ...this.state, - pendingApprovals: this.state.pendingApprovals.filter( - (p) => p.workflowId !== workflowId, - ), - }); - } - - // Track workflow progress to update pending approvals - async onWorkflowProgress( - workflowName: string, - workflowId: string, - progress: unknown, - ): Promise { - const p = progress as { step: string; status: string; message?: string }; - - if (p.step === "approval" && p.status === "pending") { - // Add to pending approvals list for UI display - this.setState({ - ...this.state, - pendingApprovals: [ - ...this.state.pendingApprovals, - { - workflowId, - amount: 0, // Would come from workflow params - description: p.message || "", - requestedBy: "user", - requestedAt: Date.now(), - }, - ], - }); - } - } -} -``` - - - -### Timeout handling - -Set timeouts to prevent workflows from waiting indefinitely: - - - -```ts -const approval = await this.waitForApproval<{ approvedBy: string }>(step, { - timeout: "7 days", // Also supports: "1 hour", "30 minutes", etc. -}); - -if (!approval) { - // Timeout expired - escalate or auto-reject - await step.reportError("Approval timeout - escalating to manager"); - throw new Error("Approval timeout"); -} -``` - - - -### Escalation with scheduling - -Use `schedule()` to set up escalation reminders: - - - -```ts -import { Agent, callable } from "agents"; - -class ExpenseAgent extends Agent { - @callable() - async submitForApproval(expense: ExpenseParams): Promise { - // Start the approval workflow - const workflowId = await this.runWorkflow("EXPENSE_WORKFLOW", expense); - - // Schedule reminder after 4 hours - await this.schedule(Date.now() + 4 * 60 * 60 * 1000, "sendReminder", { - workflowId, - }); - - // Schedule escalation after 24 hours - await this.schedule(Date.now() + 24 * 60 * 60 * 1000, "escalateApproval", { - workflowId, - }); - - return workflowId; - } - - async sendReminder(payload: { workflowId: string }) { - const workflow = this.getWorkflow(payload.workflowId); - if (workflow?.status === "waiting") { - // Send reminder notification - console.log("Reminder: approval still pending"); - } - } - - async escalateApproval(payload: { workflowId: string }) { - const workflow = this.getWorkflow(payload.workflowId); - if (workflow?.status === "waiting") { - // Escalate to manager - console.log("Escalating to manager"); - } - } -} -``` - - - -### Audit trail with SQL - -Use `this.sql` to maintain an immutable audit trail: - - - -```ts -import { Agent, callable } from "agents"; - -class ExpenseAgent extends Agent { - async onStart() { - // Create audit table - this.sql` - CREATE TABLE IF NOT EXISTS approval_audit ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - workflow_id TEXT NOT NULL, - decision TEXT NOT NULL CHECK(decision IN ('approved', 'rejected')), - decided_by TEXT NOT NULL, - decided_at INTEGER NOT NULL, - reason TEXT - ) - `; - } - - @callable() - async approve( - workflowId: string, - userId: string, - reason?: string, - ): Promise { - // Record the decision in SQL (immutable audit log) - this.sql` - INSERT INTO approval_audit (workflow_id, decision, decided_by, decided_at, reason) - VALUES (${workflowId}, 'approved', ${userId}, ${Date.now()}, ${reason || null}) - `; - - // Process the approval - await this.approveWorkflow(workflowId, { - reason: reason || "Approved", - metadata: { approvedBy: userId }, - }); - } -} -``` - - - -### Configuration - - - -```jsonc -{ - "name": "expense-approval", - "main": "src/index.ts", - "compatibility_date": "$today", - "compatibility_flags": ["nodejs_compat"], - "durable_objects": { - "bindings": [{ "name": "EXPENSE_AGENT", "class_name": "ExpenseAgent" }], - }, - "workflows": [ - { - "name": "expense-workflow", - "binding": "EXPENSE_WORKFLOW", - "class_name": "ExpenseWorkflow", - }, - ], - "migrations": [{ "tag": "v1", "new_sqlite_classes": ["ExpenseAgent"] }], -} -``` - - - -## MCP elicitation - -When building MCP servers with `McpAgent`, you can request additional user input during tool execution using **elicitation**. The MCP client renders a form based on your JSON Schema and returns the user's response. - -### Basic pattern - - - -```ts -import { McpAgent } from "agents/mcp"; -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; - -type State = { counter: number }; - -export class CounterMCP extends McpAgent { - server = new McpServer({ - name: "counter-server", - version: "1.0.0", - }); - - initialState: State = { counter: 0 }; - - async init() { - this.server.tool( - "increase-counter", - "Increase the counter by a user-specified amount", - { confirm: z.boolean().describe("Do you want to increase the counter?") }, - async ({ confirm }, extra) => { - if (!confirm) { - return { content: [{ type: "text", text: "Cancelled." }] }; - } - - // Request additional input from the user - const userInput = await this.server.server.elicitInput( - { - message: "By how much do you want to increase the counter?", - requestedSchema: { - type: "object", - properties: { - amount: { - type: "number", - title: "Amount", - description: "The amount to increase the counter by", - }, - }, - required: ["amount"], - }, - }, - { relatedRequestId: extra.requestId }, - ); - - // Check if user accepted or cancelled - if (userInput.action !== "accept" || !userInput.content) { - return { content: [{ type: "text", text: "Cancelled." }] }; - } - - // Use the input - const amount = Number(userInput.content.amount); - this.setState({ - ...this.state, - counter: this.state.counter + amount, - }); - - return { - content: [ - { - type: "text", - text: `Counter increased by ${amount}, now at ${this.state.counter}`, - }, - ], - }; - }, - ); - } -} -``` - - - -## Elicitation vs workflow approval - -| Aspect | MCP Elicitation | Workflow Approval | -| ------------ | ----------------------------- | ----------------------------- | -| **Context** | MCP server tool execution | Multi-step workflow processes | -| **Duration** | Immediate (within tool call) | Can wait hours/days/weeks | -| **UI** | JSON Schema-based form | Custom UI via agent state | -| **State** | MCP session state | Durable workflow state | -| **Use case** | Interactive input during tool | Approval gates in pipelines | - -## Building approval UIs - -### Pending approvals list - -Use the agent's state to display pending approvals in your UI: - -```tsx -import { useAgent } from "agents/react"; - -function PendingApprovals() { - const { state, agent } = useAgent({ - agent: "expense-agent", - name: "main", - }); - - if (!state?.pendingApprovals?.length) { - return

No pending approvals

; - } - - return ( -
- {state.pendingApprovals.map((item) => ( -
-

${item.amount}

-

{item.description}

-

Requested by {item.requestedBy}

- -
- - -
-
- ))} -
- ); -} -``` - -## Multi-approver patterns - -For sensitive operations requiring multiple approvers: - - - -```ts -import { Agent, callable } from "agents"; - -type MultiApproval = { - workflowId: string; - requiredApprovals: number; - currentApprovals: Array<{ userId: string; approvedAt: number }>; - rejections: Array<{ userId: string; rejectedAt: number; reason: string }>; -}; - -type State = { - pendingMultiApprovals: MultiApproval[]; -}; - -class MultiApprovalAgent extends Agent { - @callable() - async approveMulti(workflowId: string, userId: string): Promise { - const approval = this.state.pendingMultiApprovals.find( - (p) => p.workflowId === workflowId, - ); - if (!approval) throw new Error("Approval not found"); - - // Check if user already approved - if (approval.currentApprovals.some((a) => a.userId === userId)) { - throw new Error("Already approved by this user"); - } - - // Add this user's approval - approval.currentApprovals.push({ userId, approvedAt: Date.now() }); - - // Check if we have enough approvals - if (approval.currentApprovals.length >= approval.requiredApprovals) { - // Execute the approved action - await this.approveWorkflow(workflowId, { - metadata: { approvers: approval.currentApprovals }, - }); - return true; - } - - this.setState({ ...this.state }); - return false; // Still waiting for more approvals - } -} -``` - - - -## Best practices - -1. **Define clear approval criteria** — Only require confirmation for actions with meaningful consequences (payments, emails, data changes) -2. **Provide detailed context** — Show users exactly what the action will do, including all arguments -3. **Implement timeouts** — Use `schedule()` to escalate or auto-reject after reasonable periods -4. **Maintain audit trails** — Use `this.sql` to record all approval decisions for compliance -5. **Handle connection drops** — Store pending approvals in agent state so they survive disconnections -6. **Graceful degradation** — Provide fallback behavior if approvals are rejected - -## Next steps - - - - - - - - diff --git a/src/content/docs/agents/harnesses/index.mdx b/src/content/docs/agents/harnesses/index.mdx new file mode 100644 index 000000000000000..a441066cbf68c05 --- /dev/null +++ b/src/content/docs/agents/harnesses/index.mdx @@ -0,0 +1,55 @@ +--- +title: Harnesses +pcx_content_type: concept +sidebar: + order: 5 + group: + hideIndex: true +--- + +import { DirectoryListing, LinkCard } from "~/components"; + +A harness is the loop that runs an agent. It decides how the agent receives a message, calls a model, selects tools, handles tool results, streams output, persists state, and decides whether to continue or stop. + +You can build this loop yourself with the [Agents SDK runtime](/agents/runtime/agents-api/), or use an opinionated harness like [Project Think](/agents/harnesses/think/). + +## Harnesses and runtime + +Harnesses sit on top of the Agents SDK runtime: + +- **The runtime** provides durable infrastructure: the `Agent` class, state, sessions, routing, WebSockets, scheduling, fibers, and observability. +- **The harness** provides agent behavior: the model call, prompt construction, tool selection, stream handling, memory strategy, and extension points. + +Use the runtime directly when you need full control over every part of the loop. Use a harness when you want common agent behavior packaged into a reusable base class. + +## Current harnesses + + + +## Related resources + + + + + + + +## All harness pages + + diff --git a/src/content/docs/agents/api-reference/think.mdx b/src/content/docs/agents/harnesses/think.mdx similarity index 97% rename from src/content/docs/agents/api-reference/think.mdx rename to src/content/docs/agents/harnesses/think.mdx index e1dad2a6ed0a5a4..2b26b75d681f05f 100644 --- a/src/content/docs/agents/api-reference/think.mdx +++ b/src/content/docs/agents/harnesses/think.mdx @@ -5,7 +5,7 @@ description: Opinionated chat agent framework with built-in tools, persistent me tags: - AI sidebar: - order: 7 + order: 1 --- import { @@ -125,7 +125,7 @@ tag = "v1" ## Think vs AIChatAgent -Both Think and [`AIChatAgent`](/agents/api-reference/chat-agents/) extend `Agent` and speak the same `cf_agent_chat_*` WebSocket protocol. They serve different goals. +Both Think and [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/) extend `Agent` and speak the same `cf_agent_chat_*` WebSocket protocol. They serve different goals. **AIChatAgent** is a protocol adapter. You override `onChatMessage` and are responsible for calling `streamText`, wiring tools, converting messages, and returning a `Response`. AIChatAgent handles the plumbing — message persistence, streaming, abort, resume — but the LLM call is entirely your concern. @@ -165,7 +165,7 @@ Both Think and [`AIChatAgent`](/agents/api-reference/chat-agents/) extend `Agent | `getSystemPrompt()` | `"You are a helpful assistant."` | System prompt (fallback when no context blocks) | | `getTools()` | `{}` | AI SDK `ToolSet` for the agentic loop | | `maxSteps` | `10` | Max tool-call rounds per turn | -| `configureSession()` | identity | Add context blocks, compaction, search, skills — refer to [Sessions](/agents/api-reference/sessions/) | +| `configureSession()` | identity | Add context blocks, compaction, search, skills — refer to [Sessions](/agents/runtime/lifecycle/sessions/) | | `messageConcurrency` | `"queue"` | How overlapping submits behave — refer to [Message concurrency](#message-concurrency) | | `waitForMcpConnections` | `false` | Wait for MCP servers before inference | | `chatRecovery` | `true` | Wrap turns in `runFiber` for durable execution | @@ -221,7 +221,7 @@ export class MyAgent extends Think { ## Session integration -Think uses [Session](/agents/api-reference/sessions/) for conversation storage. Override `configureSession` to add persistent memory, compaction, search, and skills: +Think uses [Session](/agents/runtime/lifecycle/sessions/) for conversation storage. Override `configureSession` to add persistent memory, compaction, search, and skills: @@ -251,7 +251,7 @@ export class MyAgent extends Think { When `configureSession` adds context blocks, Think builds the system prompt from those blocks instead of using `getSystemPrompt()`. Think's `this.messages` getter reads directly from Session's tree-structured storage. -For the full Session API — context blocks, compaction, search, skills, and multi-session support — refer to the [Sessions documentation](/agents/api-reference/sessions/). +For the full Session API — context blocks, compaction, search, skills, and multi-session support — refer to the [Sessions documentation](/agents/runtime/lifecycle/sessions/). ## Tools @@ -562,7 +562,7 @@ createBrowserTools({ -For the full CDP helper API, refer to [Browse the web](/agents/api-reference/browse-the-web/). +For the full CDP helper API, refer to [Browser](/agents/tools/browser/). ### Extensions @@ -1366,9 +1366,9 @@ Think's design is inspired by [Pi](https://pi.dev). ## Related -- [Sessions](/agents/api-reference/sessions/) — context blocks, compaction, search, multi-session (the storage layer Think builds on) -- [Sub-agents](/agents/api-reference/sub-agents/) — `subAgent()`, `abortSubAgent()`, `deleteSubAgent()` (the base Agent methods for spawning children) -- [Chat agents](/agents/api-reference/chat-agents/) — `AIChatAgent` for when you need full control over the LLM call +- [Sessions](/agents/runtime/lifecycle/sessions/) — context blocks, compaction, search, multi-session (the storage layer Think builds on) +- [Sub-agents](/agents/runtime/execution/sub-agents/) — `subAgent()`, `abortSubAgent()`, `deleteSubAgent()` (the base Agent methods for spawning children) +- [Chat agents](/agents/communication-channels/chat/chat-agents/) — `AIChatAgent` for when you need full control over the LLM call - [Long-running agents](/agents/concepts/long-running-agents/) — sub-agent delegation patterns for multi-week agent lifetimes -- [Durable execution](/agents/api-reference/durable-execution/) — `runFiber()` and crash recovery (used by `chatRecovery`) -- [Browse the web](/agents/api-reference/browse-the-web/) — full CDP helper API reference +- [Durable execution](/agents/runtime/execution/durable-execution/) — `runFiber()` and crash recovery (used by `chatRecovery`) +- [Browser](/agents/tools/browser/) — full CDP helper API reference diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 32d033361f1e38b..eb3a12dc136e6fa 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -13,6 +13,7 @@ head: import { CardGrid, + AgentsPlatformDiagram, Description, Feature, LinkButton, @@ -30,6 +31,8 @@ import { Most AI applications today are stateless — they process a request, return a response, and forget everything. Real agents need more. They need to remember conversations, act on schedules, call tools, coordinate with other agents, and stay connected to users in real-time. The Agents SDK gives you all of this as a TypeScript class. + + Each agent runs on a [Durable Object](/durable-objects/) — a stateful micro-server with its own SQL database, WebSocket connections, and scheduling. Deploy once and Cloudflare runs your agents across its global network, scaling to tens of millions of instances. No infrastructure to manage, no sessions to reconstruct, no state to externalize. ### Get started @@ -42,11 +45,11 @@ cd agents-starter && npm install npm run dev ``` -The starter includes streaming AI chat, server-side and client-side tools, human-in-the-loop approval, and task scheduling — a foundation you can build on or tear apart. You can also swap in [OpenAI, Anthropic, Google Gemini, or any other provider](/agents/api-reference/using-ai-models/). +The starter includes streaming AI chat, server-side and client-side tools, human-in-the-loop approval, and task scheduling — a foundation you can build on or tear apart. You can also swap in [OpenAI, Anthropic, Google Gemini, or any other provider](/agents/runtime/operations/using-ai-models/). @@ -58,15 +61,15 @@ The starter includes streaming AI chat, server-side and client-side tools, human ### What agents can do -- **Remember everything** — Every agent has a built-in [SQL database](/agents/api-reference/store-and-sync-state/) and key-value state that syncs to connected clients in real-time. State survives restarts, deploys, and hibernation. -- **Build AI chat** — [`AIChatAgent`](/agents/api-reference/chat-agents/) gives you streaming AI chat with automatic message persistence, resumable streams, and tool support. Pair it with the [`useAgentChat`](/agents/api-reference/chat-agents/) React hook to build chat UIs in minutes. -- **Think with any model** — Call [any AI model](/agents/api-reference/using-ai-models/) — Workers AI, OpenAI, Anthropic, Gemini — and stream responses over [WebSockets](/agents/api-reference/websockets/) or [Server-Sent Events](/agents/api-reference/http-sse/). Long-running reasoning models that take minutes to respond work out of the box. -- **Use and serve tools** — Define server-side tools, client-side tools that run in the browser, and [human-in-the-loop](/agents/concepts/human-in-the-loop/) approval flows. Expose your agent's tools to other agents and LLMs via [MCP](/agents/api-reference/mcp-agent-api/). -- **Act on their own** — [Schedule tasks](/agents/api-reference/schedule-tasks/) on a delay, at a specific time, or on a cron. Agents can wake themselves up, do work, and go back to sleep — without a user present. -- **Browse the web** — Give your agents [browser tools](/agents/api-reference/browse-the-web/) powered by the Chrome DevTools Protocol to scrape, screenshot, debug, and interact with web pages. -- **Talk to users** — Build real-time [voice agents](/agents/api-reference/voice/) with speech-to-text, text-to-speech, and conversation persistence — audio streams over WebSocket. -- **Orchestrate work** — Run multi-step [workflows](/agents/api-reference/run-workflows/) with automatic retries, or coordinate across multiple agents. -- **React to events** — Handle [inbound email](/agents/api-reference/email/), HTTP requests, WebSocket messages, and state changes — all from the same class. +- **Remember everything** — Every agent has a built-in [SQL database](/agents/runtime/lifecycle/state/) and key-value state that syncs to connected clients in real-time. State survives restarts, deploys, and hibernation. +- **Build AI chat** — [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/) gives you streaming AI chat with automatic message persistence, resumable streams, and tool support. Pair it with the [`useAgentChat`](/agents/communication-channels/chat/chat-agents/) React hook to build chat UIs in minutes. +- **Think with any model** — Call [any AI model](/agents/runtime/operations/using-ai-models/) — Workers AI, OpenAI, Anthropic, Gemini — and stream responses over [WebSockets](/agents/runtime/communication/websockets/) or [Server-Sent Events](/agents/runtime/communication/http-sse/). Long-running reasoning models that take minutes to respond work out of the box. +- **Use and serve tools** — Define server-side tools, client-side tools that run in the browser, and [human-in-the-loop](/agents/concepts/human-in-the-loop/) approval flows. Expose your agent's tools to other agents and LLMs via [MCP](/agents/mcp/apis/agent-api/). +- **Act on their own** — [Schedule tasks](/agents/runtime/execution/schedule-tasks/) on a delay, at a specific time, or on a cron. Agents can wake themselves up, do work, and go back to sleep — without a user present. +- **Browse the web** — Give your agents [browser tools](/agents/tools/browser/) powered by the Chrome DevTools Protocol to scrape, screenshot, debug, and interact with web pages. +- **Talk to users** — Build real-time [voice agents](/agents/communication-channels/voice/) with speech-to-text, text-to-speech, and conversation persistence — audio streams over WebSocket. +- **Orchestrate work** — Run multi-step [workflows](/agents/runtime/execution/run-workflows/) with automatic retries, or coordinate across multiple agents. +- **React to events** — Handle [inbound email](/agents/communication-channels/email/), HTTP requests, WebSocket messages, and state changes — all from the same class. ### How it works @@ -127,7 +130,7 @@ export class ChatAgent extends AIChatAgent { -Refer to the [quick start](/agents/getting-started/quick-start/) for a full walkthrough, the [chat agents guide](/agents/api-reference/chat-agents/) for the full chat API, or the [Agents API reference](/agents/api-reference/agents-api/) for the complete SDK. +Refer to the [quick start](/agents/getting-started/quick-start/) for a full walkthrough, the [chat agents guide](/agents/communication-channels/chat/chat-agents/) for the full chat API, or the [Agents API reference](/agents/runtime/agents-api/) for the complete SDK. --- diff --git a/src/content/docs/agents/api-reference/mcp-agent-api.mdx b/src/content/docs/agents/mcp/apis/agent-api.mdx similarity index 89% rename from src/content/docs/agents/api-reference/mcp-agent-api.mdx rename to src/content/docs/agents/mcp/apis/agent-api.mdx index 2613aa848983fc5..9a4a5aefb78d3a0 100644 --- a/src/content/docs/agents/api-reference/mcp-agent-api.mdx +++ b/src/content/docs/agents/mcp/apis/agent-api.mdx @@ -35,9 +35,9 @@ export class MyMCP extends McpAgent { -This means that each instance of your MCP server has its own durable state, backed by a [Durable Object](/durable-objects/), with its own [SQL database](/agents/api-reference/store-and-sync-state). +This means that each instance of your MCP server has its own durable state, backed by a [Durable Object](/durable-objects/), with its own [SQL database](/agents/runtime/lifecycle/state/). -Your MCP server doesn't necessarily have to be an Agent. You can build MCP servers that are stateless, and just add [tools](/agents/model-context-protocol/tools) to your MCP server using the `@modelcontextprotocol/sdk` package. +Your MCP server doesn't necessarily have to be an Agent. You can build MCP servers that are stateless, and just add [tools](/agents/mcp/tools) to your MCP server using the `@modelcontextprotocol/sdk` package. But if you want your MCP server to: @@ -155,7 +155,7 @@ Hibernation is enabled by default and requires no additional configuration. ## Authentication and authorization -The McpAgent class provides seamless integration with the [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) for [authentication and authorization](/agents/model-context-protocol/authorization/). +The McpAgent class provides seamless integration with the [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) for [authentication and authorization](/agents/mcp/protocol/authorization/). When a user authenticates to your MCP server, their identity information and tokens are made available through the `props` parameter, allowing you to: @@ -166,16 +166,16 @@ When a user authenticates to your MCP server, their identity information and tok ## State synchronization APIs -The `McpAgent` class provides full access to the [Agent state APIs](/agents/api-reference/store-and-sync-state/): +The `McpAgent` class provides full access to the [Agent state APIs](/agents/runtime/lifecycle/state/): -- [`state`](/agents/api-reference/store-and-sync-state/) — Current persisted state -- [`initialState`](/agents/api-reference/store-and-sync-state/#set-the-initial-state-for-an-agent) — Default state when instance starts -- [`setState`](/agents/api-reference/store-and-sync-state/) — Update and persist state -- [`onStateChanged`](/agents/api-reference/store-and-sync-state/#synchronizing-state) — React to state changes -- [`sql`](/agents/api-reference/agents-api/#sql-api) — Execute SQL queries on embedded database +- [`state`](/agents/runtime/lifecycle/state/) — Current persisted state +- [`initialState`](/agents/runtime/lifecycle/state/#set-the-initial-state-for-an-agent) — Default state when instance starts +- [`setState`](/agents/runtime/lifecycle/state/) — Update and persist state +- [`onStateChanged`](/agents/runtime/lifecycle/state/#synchronizing-state) — React to state changes +- [`sql`](/agents/runtime/agents-api/#sql-api) — Execute SQL queries on embedded database :::note[State resets after the session ends] -Currently, each client session is backed by an instance of the `McpAgent` class. This is handled automatically for you, as shown in the [getting started guide](/agents/guides/remote-mcp-server). This means that when the same client reconnects, they will start a new session, and the state will be reset. +Currently, each client session is backed by an instance of the `McpAgent` class. This is handled automatically for you, as shown in the [getting started guide](/agents/mcp/guides/remote-mcp-server/). This means that when the same client reconnects, they will start a new session, and the state will be reset. ::: For example, the following code implements an MCP server that remembers a counter value, and updates the counter when the `add` tool is called: @@ -397,36 +397,36 @@ switch (result.action) { Elicitation requires MCP client support. Not all MCP clients implement the elicitation capability. Check the client documentation for compatibility. ::: -For more human-in-the-loop patterns including workflow-based approval, refer to [Human-in-the-loop patterns](/agents/guides/human-in-the-loop/). +For more human-in-the-loop patterns including workflow-based approval, refer to [Human-in-the-loop patterns](/agents/concepts/human-in-the-loop/). ## Next steps diff --git a/src/content/docs/agents/api-reference/mcp-client-api.mdx b/src/content/docs/agents/mcp/apis/client-api.mdx similarity index 95% rename from src/content/docs/agents/api-reference/mcp-client-api.mdx rename to src/content/docs/agents/mcp/apis/client-api.mdx index 25452c489f5f7f8..6dce035d4360bc3 100644 --- a/src/content/docs/agents/api-reference/mcp-client-api.mdx +++ b/src/content/docs/agents/mcp/apis/client-api.mdx @@ -9,7 +9,7 @@ sidebar: import { Render, TypeScriptExample, LinkCard } from "~/components"; -Connect your agent to external [Model Context Protocol (MCP)](/agents/model-context-protocol/) servers to use their tools, resources, and prompts. This enables your agent to interact with GitHub, Slack, databases, and other services through a standardized protocol. +Connect your agent to external [Model Context Protocol (MCP)](/agents/mcp/) servers to use their tools, resources, and prompts. This enables your agent to interact with GitHub, Slack, databases, and other services through a standardized protocol. ## Overview @@ -22,7 +22,7 @@ The MCP client capability lets your agent: :::note -This page covers connecting to MCP servers as a client. To create your own MCP server, refer to [Creating MCP servers](/agents/api-reference/mcp-agent-api/). +This page covers connecting to MCP servers as a client. To create your own MCP server, refer to [Creating MCP servers](/agents/mcp/apis/agent-api/). ::: @@ -57,7 +57,7 @@ export class MyAgent extends Agent { -Connections persist in the agent's [SQL storage](/agents/api-reference/store-and-sync-state/), and when an agent connects to an MCP server, all tools from that server become available automatically. +Connections persist in the agent's [SQL storage](/agents/runtime/lifecycle/state/), and when an agent connects to an MCP server, all tools from that server become available automatically. ## Adding MCP servers @@ -133,7 +133,7 @@ MCP server URLs are validated before connection to prevent Server-Side Request F Loopback addresses (`localhost`, `127.x.x.x`, `[::1]`) are **allowed** for local development. -For production connections to internal services, use the [RPC transport](/agents/model-context-protocol/transport/) with a Durable Object binding instead of HTTP. +For production connections to internal services, use the [RPC transport](/agents/mcp/protocol/transport/) with a Durable Object binding instead of HTTP. ### Return value @@ -514,7 +514,7 @@ async addMcpServer( - `transport` — Transport layer configuration: - `headers` — Custom HTTP headers for authentication - `type` — Transport type: `"auto"` (default), `"streamable-http"`, or `"sse"` - - `retry` — Retry options for connection and reconnection attempts. Persisted and used when restoring connections after hibernation or after OAuth completion. Default: 3 attempts, 500ms base delay, 5s max delay. Refer to [Retries](/agents/api-reference/retries/) for details on `RetryOptions`. + - `retry` — Retry options for connection and reconnection attempts. Persisted and used when restoring connections after hibernation or after OAuth completion. Default: 3 attempts, 500ms base delay, 5s max delay. Refer to [Retries](/agents/runtime/execution/retries/) for details on `RetryOptions`. #### Parameters (RPC transport) @@ -525,7 +525,7 @@ async addMcpServer( - `client` — MCP client configuration options - `retry` — Retry options for the connection -RPC transport connects your Agent directly to an `McpAgent` via Durable Object bindings without HTTP overhead. Refer to [MCP Transport](/agents/model-context-protocol/transport/) for details on configuring RPC transport. +RPC transport connects your Agent directly to an `McpAgent` via Durable Object bindings without HTTP overhead. Refer to [MCP Transport](/agents/mcp/protocol/transport/) for details on configuring RPC transport. #### Returns @@ -782,7 +782,7 @@ const disposable = this.mcp.onServerStateChanged(() => { :::note -MCP server list broadcasts (`cf_agent_mcp_servers`) are automatically filtered to exclude connections where [`shouldSendProtocolMessages`](/agents/api-reference/protocol-messages/) returned `false`. +MCP server list broadcasts (`cf_agent_mcp_servers`) are automatically filtered to exclude connections where [`shouldSendProtocolMessages`](/agents/runtime/communication/protocol-messages/) returned `false`. ::: ### Lifecycle methods @@ -847,7 +847,7 @@ await this.mcp.waitForConnections({ timeout: 10_000 }); ``` :::note -`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`. +`AIChatAgent` calls this automatically via its [`waitForMcpConnections`](/agents/communication-channels/chat/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`. ::: #### `this.mcp.closeConnection()` @@ -941,18 +941,18 @@ export class MyAgent extends Agent { diff --git a/src/content/docs/agents/api-reference/mcp-handler-api.mdx b/src/content/docs/agents/mcp/apis/handler-api.mdx similarity index 91% rename from src/content/docs/agents/api-reference/mcp-handler-api.mdx rename to src/content/docs/agents/mcp/apis/handler-api.mdx index c5e9b353c4ae8e1..6e741f5a7c89a27 100644 --- a/src/content/docs/agents/api-reference/mcp-handler-api.mdx +++ b/src/content/docs/agents/mcp/apis/handler-api.mdx @@ -9,7 +9,7 @@ sidebar: import { TypeScriptExample, LinkCard } from "~/components"; -The `createMcpHandler` function creates a fetch handler to serve your [MCP server](/agents/model-context-protocol/). Use it when you want a stateless MCP server that runs in a plain Worker (no Durable Object). For stateful MCP servers that persist state across requests, use the [`McpAgent`](/agents/api-reference/mcp-agent-api) class instead. +The `createMcpHandler` function creates a fetch handler to serve your [MCP server](/agents/mcp/). Use it when you want a stateless MCP server that runs in a plain Worker (no Durable Object). For stateful MCP servers that persist state across requests, use the [`McpAgent`](/agents/mcp/apis/agent-api/) class instead. It uses an implementation of the MCP Transport interface, `WorkerTransport`, built on top of web standards, which conforms to the [streamable-http](https://modelcontextprotocol.io/specification/draft/basic/transports/#streamable-http) transport specification. @@ -86,9 +86,9 @@ const handler = createMcpHandler(server, { #### authContext -An authentication context object that will be available to MCP tools via [`getMcpAuthContext()`](/agents/api-reference/mcp-handler-api#authentication-context). +An authentication context object that will be available to MCP tools via [`getMcpAuthContext()`](/agents/mcp/apis/handler-api/#authentication-context). -When using the [`OAuthProvider`](/agents/model-context-protocol/authorization/) from `@cloudflare/workers-oauth-provider`, the authentication context is automatically populated with information from the OAuth flow. You typically don't need to set this manually. +When using the [`OAuthProvider`](/agents/mcp/protocol/authorization/) from `@cloudflare/workers-oauth-provider`, the authentication context is automatically populated with information from the OAuth flow. You typically don't need to set this manually. #### transport @@ -124,7 +124,7 @@ MCP SDK 1.26.0 introduces a guard that prevents connecting to a server instance **If your stateless MCP server declares `McpServer` or transport instances in the global scope, you must create new instances per request.** -See the [migration guide](/agents/api-reference/mcp-handler-api/#migration-guide-for-mcp-sdk-1260) below for details. +See the [migration guide](/agents/mcp/apis/handler-api/#migration-guide-for-mcp-sdk-1260) below for details. ::: @@ -543,7 +543,7 @@ const transport = new WorkerTransport({ ## Authentication Context -When using [OAuth authentication](/agents/model-context-protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available. +When using [OAuth authentication](/agents/mcp/protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available. ```ts interface McpAuthContext { @@ -592,7 +592,7 @@ function createServer() { :::note -For a complete guide on setting up OAuth authentication with MCP servers, see the [MCP Authorization documentation](/agents/model-context-protocol/authorization/). View the [complete authenticated MCP server in a Worker example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). +For a complete guide on setting up OAuth authentication with MCP servers, see the [MCP Authorization documentation](/agents/mcp/protocol/authorization/). View the [complete authenticated MCP server in a Worker example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). ::: ## Error Handling @@ -628,24 +628,24 @@ server.tool("riskyOperation", "An operation that might fail", {}, async () => { diff --git a/src/content/docs/agents/mcp/apis/index.mdx b/src/content/docs/agents/mcp/apis/index.mdx new file mode 100644 index 000000000000000..5e9a4fa782e63ed --- /dev/null +++ b/src/content/docs/agents/mcp/apis/index.mdx @@ -0,0 +1,12 @@ +--- +title: APIs +pcx_content_type: navigation +sidebar: + order: 1 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/mcp/cloudflare/index.mdx b/src/content/docs/agents/mcp/cloudflare/index.mdx new file mode 100644 index 000000000000000..0d398f640fa5a3a --- /dev/null +++ b/src/content/docs/agents/mcp/cloudflare/index.mdx @@ -0,0 +1,12 @@ +--- +title: Cloudflare +pcx_content_type: navigation +sidebar: + order: 4 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/model-context-protocol/mcp-portal.mdx b/src/content/docs/agents/mcp/cloudflare/mcp-portal.mdx similarity index 100% rename from src/content/docs/agents/model-context-protocol/mcp-portal.mdx rename to src/content/docs/agents/mcp/cloudflare/mcp-portal.mdx diff --git a/src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx b/src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx similarity index 77% rename from src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx rename to src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx index be28173c3eaef55..ca46db66dfddc82 100644 --- a/src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx +++ b/src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx @@ -15,7 +15,7 @@ These MCP servers allow your MCP client to read configurations from your account The [Cloudflare API MCP server](https://github.com/cloudflare/mcp) provides access to the entire [Cloudflare API](/api/) — over 2,500 endpoints across DNS, Workers, R2, Zero Trust, and every other product — through just two tools: `search()` and `execute()`. -It uses [Codemode](/agents/api-reference/codemode/), a technique where the model writes JavaScript against a typed representation of the OpenAPI spec and the Cloudflare API client, rather than loading individual tool definitions for each endpoint. The generated code runs inside an isolated [Dynamic Worker](/workers/runtime-apis/bindings/worker-loader/) sandbox. +It uses [Codemode](/agents/mcp/protocol/codemode/), a technique where the model writes JavaScript against a typed representation of the OpenAPI spec and the Cloudflare API client, rather than loading individual tool definitions for each endpoint. The generated code runs inside an isolated [Dynamic Worker](/workers/runtime-apis/bindings/worker-loader/) sandbox. This approach uses approximately 1,000 tokens regardless of how many API endpoints exist. An equivalent MCP server that exposed every endpoint as a native tool would consume over 1 million tokens — more than the entire context window of most foundation models. @@ -105,3 +105,69 @@ In addition to the Cloudflare API MCP server, Cloudflare provides product-specif | [Agents SDK Documentation server](https://github.com/cloudflare/agents/tree/main/site/agents) | Token-efficient search of the Cloudflare Agents SDK documentation | `https://agents.cloudflare.com/mcp` | Check the [GitHub page](https://github.com/cloudflare/mcp-server-cloudflare) to learn how to use Cloudflare's remote MCP servers with different MCP clients. + +## Cloudflare Community MCP server + +The [Cloudflare Community MCP server](https://community.cloudflare.com/.well-known/mcp.json) lets AI agents search the Cloudflare Community forum, read topics and posts, look up users, and filter public content. It is powered by [`@discourse/mcp`](https://www.npmjs.com/package/@discourse/mcp), the official Discourse MCP server. + +No API key is required to read public forum data. API keys are only required for write operations, such as posting or moderation. + +### Install + +```sh +npx @discourse/mcp@latest +``` + +### Configure a local MCP client + +Add the Discourse server to your MCP client configuration. For example: + +```json +{ + "mcpServers": { + "discourse": { + "command": "npx", + "args": ["-y", "@discourse/mcp@latest"] + } + } +} +``` + +For OpenCode, add the following inside the `"mcp"` block in `~/.config/opencode/opencode.jsonc`: + +```jsonc +"discourse": { + "type": "local", + "command": ["npx", "-y", "@discourse/mcp@latest"], + "enabled": true +} +``` + +After configuring your client, use the `discourse_select_site` tool with `https://community.cloudflare.com`. + +### Available tools + +| Tool | Description | +| --------------------------- | ------------------------------------------ | +| `discourse_select_site` | Connect to `community.cloudflare.com` | +| `discourse_search` | Full-text search across topics and posts | +| `discourse_filter_topics` | Filter by category, tags, status, or dates | +| `discourse_read_topic` | Read a topic's posts and metadata | +| `discourse_read_post` | Read a specific post | +| `discourse_get_user` | Look up a user's profile | +| `discourse_list_user_posts` | List posts by a user | + +### Example prompts + +- Search the Cloudflare Community for topics about Error 522. +- Find unanswered topics in the SSL category from the last three days. +- Read topic 42325 and summarize the issue. +- Show recent replies from a specific user. + +### Machine-readable discovery + +Agents can discover the Community MCP server through these endpoints on `community.cloudflare.com`: + +- [`/.well-known/mcp.json`](https://community.cloudflare.com/.well-known/mcp.json) — MCP Server Card +- [`/llms.txt`](https://community.cloudflare.com/llms.txt) — `llms.txt` with server information and install instructions +- [`/.well-known/agent.json`](https://community.cloudflare.com/.well-known/agent.json) — A2A Agent Card diff --git a/src/content/docs/agents/guides/build-mcp-client.mdx b/src/content/docs/agents/mcp/guides/build-mcp-client.mdx similarity index 54% rename from src/content/docs/agents/guides/build-mcp-client.mdx rename to src/content/docs/agents/mcp/guides/build-mcp-client.mdx index 4e1bc6fea9341cc..783a1ad0fd13ba6 100644 --- a/src/content/docs/agents/guides/build-mcp-client.mdx +++ b/src/content/docs/agents/mcp/guides/build-mcp-client.mdx @@ -1,9 +1,9 @@ --- +title: Build MCP client pcx_content_type: navigation -title: Build a Remote MCP Client external_link: https://github.com/cloudflare/ai/tree/main/demos/mcp-client sidebar: - order: 11 + order: 1 head: [] -description: Build an AI Agent that acts as a remote MCP client. +description: Build an MCP client with Cloudflare AI. --- diff --git a/src/content/docs/agents/guides/connect-mcp-client.mdx b/src/content/docs/agents/mcp/guides/connect-mcp-client.mdx similarity index 96% rename from src/content/docs/agents/guides/connect-mcp-client.mdx rename to src/content/docs/agents/mcp/guides/connect-mcp-client.mdx index 41004096a2e6200..8dba22517eecf18 100644 --- a/src/content/docs/agents/guides/connect-mcp-client.mdx +++ b/src/content/docs/agents/mcp/guides/connect-mcp-client.mdx @@ -226,18 +226,18 @@ You created an Agent that can: - List all available tools from connected servers - Monitor connection status -Connections persist in the Agent's [SQL storage](/agents/api-reference/store-and-sync-state/), so they remain active across requests. +Connections persist in the Agent's [SQL storage](/agents/runtime/lifecycle/state/), so they remain active across requests. ## Next steps diff --git a/src/content/docs/agents/guides/index.mdx b/src/content/docs/agents/mcp/guides/index.mdx similarity index 93% rename from src/content/docs/agents/guides/index.mdx rename to src/content/docs/agents/mcp/guides/index.mdx index 9660fffdb0c404c..3a993b27a6fba07 100644 --- a/src/content/docs/agents/guides/index.mdx +++ b/src/content/docs/agents/mcp/guides/index.mdx @@ -2,7 +2,7 @@ title: Guides pcx_content_type: navigation sidebar: - order: 4 + order: 3 group: hideIndex: true --- diff --git a/src/content/docs/agents/guides/oauth-mcp-client.mdx b/src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx similarity index 99% rename from src/content/docs/agents/guides/oauth-mcp-client.mdx rename to src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx index dc6138c6199666b..0124bb3663f30bb 100644 --- a/src/content/docs/agents/guides/oauth-mcp-client.mdx +++ b/src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx @@ -379,12 +379,12 @@ export default { diff --git a/src/content/docs/agents/guides/remote-mcp-server.mdx b/src/content/docs/agents/mcp/guides/remote-mcp-server.mdx similarity index 89% rename from src/content/docs/agents/guides/remote-mcp-server.mdx rename to src/content/docs/agents/mcp/guides/remote-mcp-server.mdx index 2d152560c4be5ee..f197e4c0d07e451 100644 --- a/src/content/docs/agents/guides/remote-mcp-server.mdx +++ b/src/content/docs/agents/mcp/guides/remote-mcp-server.mdx @@ -9,10 +9,10 @@ sidebar: import { Details, Render, PackageManagers, LinkCard } from "~/components"; -This guide will show you how to deploy your own remote MCP server on Cloudflare using [Streamable HTTP transport](/agents/model-context-protocol/transport/), the current MCP specification standard. You have two options: +This guide will show you how to deploy your own remote MCP server on Cloudflare using [Streamable HTTP transport](/agents/mcp/protocol/transport/), the current MCP specification standard. You have two options: - **Without authentication** — anyone can connect and use the server (no login required). -- **With [authentication and authorization](/agents/guides/remote-mcp-server/#add-authentication)** — users sign in before accessing tools, and you can control which tools an agent can call based on the user's permissions. +- **With [authentication and authorization](/agents/mcp/guides/remote-mcp-server/#add-authentication)** — users sign in before accessing tools, and you can control which tools an agent can call based on the user's permissions. ## Choosing an approach @@ -20,8 +20,8 @@ The Agents SDK provides multiple ways to create MCP servers. Choose the approach | Approach | Stateful? | Requires Durable Objects? | Best for | | -------------------------------------------------------------- | --------- | ------------------------- | ---------------------------------------------- | -| [`createMcpHandler()`](/agents/api-reference/mcp-handler-api/) | No | No | Stateless tools, simplest setup | -| [`McpAgent`](/agents/api-reference/mcp-agent-api/) | Yes | Yes | Stateful tools, per-session state, elicitation | +| [`createMcpHandler()`](/agents/mcp/apis/handler-api/) | No | No | Stateless tools, simplest setup | +| [`McpAgent`](/agents/mcp/apis/agent-api/) | Yes | Yes | Stateful tools, per-session state, elicitation | | Raw `WebStandardStreamableHTTPServerTransport` | No | No | Full control, no SDK dependency | - **`createMcpHandler()`** is the fastest way to get a stateless MCP server running. Use it when your tools do not need per-session state. @@ -30,7 +30,7 @@ The Agents SDK provides multiple ways to create MCP servers. Choose the approach ## Deploy your first MCP server -You can start by deploying a [public MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) without authentication, then add user authentication and scoped authorization later. If you already know your server will require authentication, you can skip ahead to the [next section](/agents/guides/remote-mcp-server/#add-authentication). +You can start by deploying a [public MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) without authentication, then add user authentication and scoped authorization later. If you already know your server will require authentication, you can skip ahead to the [next section](/agents/mcp/guides/remote-mcp-server/#add-authentication). ### Via the dashboard @@ -38,9 +38,9 @@ The button below will guide you through everything you need to do to deploy an [ [![Deploy to Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) -Once deployed, this server will be live at your `workers.dev` subdomain (for example, `remote-mcp-server-authless.your-account.workers.dev/mcp`). You can connect to it immediately using the [AI Playground](https://playground.ai.cloudflare.com/) (a remote MCP client), [MCP inspector](https://github.com/modelcontextprotocol/inspector) or [other MCP clients](/agents/guides/remote-mcp-server/#connect-from-an-mcp-client-via-a-local-proxy). +Once deployed, this server will be live at your `workers.dev` subdomain (for example, `remote-mcp-server-authless.your-account.workers.dev/mcp`). You can connect to it immediately using the [AI Playground](https://playground.ai.cloudflare.com/) (a remote MCP client), [MCP inspector](https://github.com/modelcontextprotocol/inspector) or [other MCP clients](/agents/mcp/guides/remote-mcp-server/#connect-from-an-mcp-client-via-a-local-proxy). -A new git repository will be set up on your GitHub or GitLab account for your MCP server, configured to automatically deploy to Cloudflare each time you push a change or merge a pull request to the main branch of the repository. You can clone this repository, [develop locally](/agents/guides/remote-mcp-server/#via-the-cli), and start customizing the MCP server with your own [tools](/agents/model-context-protocol/tools/). +A new git repository will be set up on your GitHub or GitLab account for your MCP server, configured to automatically deploy to Cloudflare each time you push a change or merge a pull request to the main branch of the repository. You can clone this repository, [develop locally](/agents/mcp/guides/remote-mcp-server/#via-the-cli), and start customizing the MCP server with your own [tools](/agents/mcp/protocol/tools/). ### Via the CLI @@ -147,7 +147,7 @@ For example, to connect from Claude Desktop: Claude should invoke the tool and show the result generated by the remote MCP server. -To learn how to use remote MCP servers with other MCP clients, refer to [Test a Remote MCP Server](/agents/guides/test-remote-mcp-server). +To learn how to use remote MCP servers with other MCP clients, refer to [Test a Remote MCP Server](/agents/mcp/guides/test-remote-mcp-server/). ## Add Authentication @@ -161,7 +161,7 @@ For a step-by-step deployment guide, refer to [Secure MCP servers with Access fo ### Third-party OAuth -You can connect your MCP server with any [OAuth provider](/agents/model-context-protocol/authorization/#2-third-party-oauth-provider) that supports the OAuth 2.0 specification, including GitHub, Google, Slack, [Stytch](/agents/model-context-protocol/authorization/#stytch), [Auth0](/agents/model-context-protocol/authorization/#auth0), [WorkOS](/agents/model-context-protocol/authorization/#workos), and more. +You can connect your MCP server with any [OAuth provider](/agents/mcp/protocol/authorization/#2-third-party-oauth-provider) that supports the OAuth 2.0 specification, including GitHub, Google, Slack, [Stytch](/agents/mcp/protocol/authorization/#stytch), [Auth0](/agents/mcp/protocol/authorization/#auth0), [WorkOS](/agents/mcp/protocol/authorization/#workos), and more. The following example demonstrates how to use GitHub as an OAuth provider. @@ -303,18 +303,18 @@ npx wrangler secret put GITHUB_CLIENT_SECRET npm run deploy ``` -5. Connect to your server running at `worker-name.account-name.workers.dev/mcp` using the [AI Playground](https://playground.ai.cloudflare.com/), MCP Inspector, or [other MCP clients](/agents/guides/test-remote-mcp-server/), and authenticate with GitHub. +5. Connect to your server running at `worker-name.account-name.workers.dev/mcp` using the [AI Playground](https://playground.ai.cloudflare.com/), MCP Inspector, or [other MCP clients](/agents/mcp/guides/test-remote-mcp-server/), and authenticate with GitHub. ## Next steps diff --git a/src/content/docs/agents/guides/securing-mcp-server.mdx b/src/content/docs/agents/mcp/guides/securing-mcp-server.mdx similarity index 98% rename from src/content/docs/agents/guides/securing-mcp-server.mdx rename to src/content/docs/agents/mcp/guides/securing-mcp-server.mdx index 2f365f57b27b463..ba61fad159ec66d 100644 --- a/src/content/docs/agents/guides/securing-mcp-server.mdx +++ b/src/content/docs/agents/mcp/guides/securing-mcp-server.mdx @@ -273,13 +273,13 @@ When reading the cookie, verify the HMAC signature before trusting the data. If diff --git a/src/content/docs/agents/guides/test-remote-mcp-server.mdx b/src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx similarity index 97% rename from src/content/docs/agents/guides/test-remote-mcp-server.mdx rename to src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx index d7bb4149935c148..d1ec14276747eee 100644 --- a/src/content/docs/agents/guides/test-remote-mcp-server.mdx +++ b/src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx @@ -11,7 +11,7 @@ import { Render } from "~/components"; Remote, authorized connections are an evolving part of the [Model Context Protocol (MCP) specification](https://spec.modelcontextprotocol.io/specification/draft/basic/authorization/). Not all MCP clients support remote connections yet. -This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/guides/remote-mcp-server/) guide first. +This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/mcp/guides/remote-mcp-server/) guide first. ## The Model Context Protocol (MCP) inspector diff --git a/src/content/docs/agents/mcp/index.mdx b/src/content/docs/agents/mcp/index.mdx new file mode 100644 index 000000000000000..46dd480332415b9 --- /dev/null +++ b/src/content/docs/agents/mcp/index.mdx @@ -0,0 +1,14 @@ +--- +title: MCP +pcx_content_type: navigation +sidebar: + order: 7 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + +Model Context Protocol (MCP) integration for agents. + + diff --git a/src/content/docs/agents/model-context-protocol/authorization.mdx b/src/content/docs/agents/mcp/protocol/authorization.mdx similarity index 96% rename from src/content/docs/agents/model-context-protocol/authorization.mdx rename to src/content/docs/agents/mcp/protocol/authorization.mdx index 4bb3392c46fb7b4..a788a1d93265050 100644 --- a/src/content/docs/agents/model-context-protocol/authorization.mdx +++ b/src/content/docs/agents/mcp/protocol/authorization.mdx @@ -34,7 +34,7 @@ To deploy an [example MCP server](https://github.com/cloudflare/ai/tree/main/dem ### (2) Third-party OAuth Provider -The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/guides/remote-mcp-server/#add-authentication). +The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/mcp/guides/remote-mcp-server/#add-authentication). When you use a third-party OAuth provider, you must provide a handler to the `OAuthProvider` that implements the OAuth flow for the third-party provider. @@ -145,7 +145,7 @@ export default new OAuthProvider({ }); ``` -Refer to the [getting started example](/agents/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. +Refer to the [getting started example](/agents/mcp/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. The authorization flow in this case works like this: @@ -169,7 +169,7 @@ sequenceDiagram Note over C,M: Begin standard MCP message exchange ``` -Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/guides/remote-mcp-server) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. +Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/mcp/guides/remote-mcp-server/) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. ## Using authentication context in tools diff --git a/src/content/docs/agents/api-reference/codemode.mdx b/src/content/docs/agents/mcp/protocol/codemode.mdx similarity index 99% rename from src/content/docs/agents/api-reference/codemode.mdx rename to src/content/docs/agents/mcp/protocol/codemode.mdx index 28177685bcd6119..57dc879541d1641 100644 --- a/src/content/docs/agents/api-reference/codemode.mdx +++ b/src/content/docs/agents/mcp/protocol/codemode.mdx @@ -4,7 +4,7 @@ title: Codemode tags: - AI sidebar: - order: 19 + order: 5 --- import { @@ -401,12 +401,12 @@ sanitizeToolName("delete"); // "delete_" diff --git a/src/content/docs/agents/model-context-protocol/governance.mdx b/src/content/docs/agents/mcp/protocol/governance.mdx similarity index 64% rename from src/content/docs/agents/model-context-protocol/governance.mdx rename to src/content/docs/agents/mcp/protocol/governance.mdx index cdb44449c8d243f..8be81477a79c1c0 100644 --- a/src/content/docs/agents/model-context-protocol/governance.mdx +++ b/src/content/docs/agents/mcp/protocol/governance.mdx @@ -25,6 +25,6 @@ Cloudflare Access logs MCP server requests and tool executions made through the ## Remote MCP servers -To maintain a modern security posture, Cloudflare recommends the use of [remote MCP servers](/agents/guides/remote-mcp-server/) over local installations. Running MCP servers locally introduces risks similar to unmanaged [shadow IT](https://www.cloudflare.com/learning/access-management/what-is-shadow-it/), making it difficult to audit data flow or verify the integrity of the server code. Remote MCP servers give administrators visibility into what servers are being used, along with the ability to control who access them and what tools are authorized for employee use. +To maintain a modern security posture, Cloudflare recommends the use of [remote MCP servers](/agents/mcp/guides/remote-mcp-server/) over local installations. Running MCP servers locally introduces risks similar to unmanaged [shadow IT](https://www.cloudflare.com/learning/access-management/what-is-shadow-it/), making it difficult to audit data flow or verify the integrity of the server code. Remote MCP servers give administrators visibility into what servers are being used, along with the ability to control who access them and what tools are authorized for employee use. -You can [build your remote MCP servers](/agents/guides/remote-mcp-server/) directly on Cloudflare Workers. When both your [MCP server portal](#mcp-server-portals) and remote MCP servers run on Cloudflare's network, requests stay on the same infrastructure, minimizing latency and maximizing performance. +You can [build your remote MCP servers](/agents/mcp/guides/remote-mcp-server/) directly on Cloudflare Workers. When both your [MCP server portal](#mcp-server-portals) and remote MCP servers run on Cloudflare's network, requests stay on the same infrastructure, minimizing latency and maximizing performance. diff --git a/src/content/docs/agents/mcp/protocol/index.mdx b/src/content/docs/agents/mcp/protocol/index.mdx new file mode 100644 index 000000000000000..891142f62a2ae24 --- /dev/null +++ b/src/content/docs/agents/mcp/protocol/index.mdx @@ -0,0 +1,12 @@ +--- +title: Protocol +pcx_content_type: navigation +sidebar: + order: 2 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/model-context-protocol/tools.mdx b/src/content/docs/agents/mcp/protocol/tools.mdx similarity index 86% rename from src/content/docs/agents/model-context-protocol/tools.mdx rename to src/content/docs/agents/mcp/protocol/tools.mdx index 5b3eac171ec04a5..8b1136d1f68cbc4 100644 --- a/src/content/docs/agents/model-context-protocol/tools.mdx +++ b/src/content/docs/agents/mcp/protocol/tools.mdx @@ -9,9 +9,9 @@ sidebar: import { TypeScriptExample, LinkCard } from "~/components"; -MCP tools are functions that an [MCP server](/agents/model-context-protocol/) exposes for clients to call. When an LLM decides it needs to take an action — look up data, run a calculation, call an API — it invokes a tool. The MCP server executes the tool and returns the result. +MCP tools are functions that an [MCP server](/agents/mcp/) exposes for clients to call. When an LLM decides it needs to take an action — look up data, run a calculation, call an API — it invokes a tool. The MCP server executes the tool and returns the result. -Tools are defined using the `@modelcontextprotocol/sdk` package. The Agents SDK handles transport and lifecycle; the tool definitions are the same regardless of whether you use [`createMcpHandler`](/agents/api-reference/mcp-handler-api/) or [`McpAgent`](/agents/api-reference/mcp-agent-api/). +Tools are defined using the `@modelcontextprotocol/sdk` package. The Agents SDK handles transport and lifecycle; the tool definitions are the same regardless of whether you use [`createMcpHandler`](/agents/mcp/apis/handler-api/) or [`McpAgent`](/agents/mcp/apis/agent-api/). ## Defining tools @@ -119,7 +119,7 @@ server.tool( ## Using tools with `createMcpHandler` -For stateless MCP servers, define tools inside a factory function and pass the server to [`createMcpHandler`](/agents/api-reference/mcp-handler-api/): +For stateless MCP servers, define tools inside a factory function and pass the server to [`createMcpHandler`](/agents/mcp/apis/handler-api/): @@ -150,7 +150,7 @@ export default { ## Using tools with `McpAgent` -For stateful MCP servers, define tools in the `init()` method of an [`McpAgent`](/agents/api-reference/mcp-agent-api/). Tools have access to the agent instance via `this`, which means they can read and write state. +For stateful MCP servers, define tools in the `init()` method of an [`McpAgent`](/agents/mcp/apis/agent-api/). Tools have access to the agent instance via `this`, which means they can read and write state. @@ -185,24 +185,24 @@ export class MyMCP extends McpAgent { diff --git a/src/content/docs/agents/model-context-protocol/transport.mdx b/src/content/docs/agents/mcp/protocol/transport.mdx similarity index 92% rename from src/content/docs/agents/model-context-protocol/transport.mdx rename to src/content/docs/agents/mcp/protocol/transport.mdx index 88e3ce7e080598f..4dd6efa16d14ac3 100644 --- a/src/content/docs/agents/model-context-protocol/transport.mdx +++ b/src/content/docs/agents/mcp/protocol/transport.mdx @@ -15,14 +15,14 @@ The Model Context Protocol (MCP) specification defines two standard [transport m 2. **Streamable HTTP** — The standard transport method for remote MCP connections, [introduced](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) in March 2025. It uses a single HTTP endpoint for bidirectional messaging. :::note -Server-Sent Events (SSE) was previously used for remote MCP connections but has been deprecated in favor of Streamable HTTP. If you need SSE support for legacy clients, use the [`McpAgent`](/agents/api-reference/mcp-agent-api/) class. +Server-Sent Events (SSE) was previously used for remote MCP connections but has been deprecated in favor of Streamable HTTP. If you need SSE support for legacy clients, use the [`McpAgent`](/agents/mcp/apis/agent-api/) class. ::: -MCP servers built with the [Agents SDK](/agents) use [`createMcpHandler`](/agents/api-reference/mcp-handler-api/) to handle Streamable HTTP transport. +MCP servers built with the [Agents SDK](/agents) use [`createMcpHandler`](/agents/mcp/apis/handler-api/) to handle Streamable HTTP transport. ## Implementing remote MCP transport -Use [`createMcpHandler`](/agents/api-reference/mcp-handler-api/) to create an MCP server that handles Streamable HTTP transport. This is the recommended approach for new MCP servers. +Use [`createMcpHandler`](/agents/mcp/apis/handler-api/) to create an MCP server that handles Streamable HTTP transport. This is the recommended approach for new MCP servers. #### Get started quickly @@ -100,7 +100,7 @@ export default new OAuthProvider({ If your MCP server needs to maintain state across requests, use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. This allows you to persist session state in Durable Object storage and use advanced MCP features like [elicitation](https://modelcontextprotocol.io/specification/draft/client/elicitation) and [sampling](https://modelcontextprotocol.io/specification/draft/client/sampling). -See [Stateful MCP Servers](/agents/api-reference/mcp-handler-api#stateful-mcp-servers) for implementation details. +See [Stateful MCP Servers](/agents/mcp/apis/handler-api/#stateful-mcp-servers) for implementation details. ## RPC transport @@ -187,7 +187,7 @@ export class Chat extends AIChatAgent { RPC connections are automatically restored after Durable Object hibernation, just like HTTP connections. The binding name and props are persisted to storage so the connection can be re-established without any extra code. -For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (refer to [MCP Client API](/agents/api-reference/mcp-client-api/) for details). This makes it safe to call in `onStart()`. +For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (refer to [MCP Client API](/agents/mcp/apis/client-api/) for details). This makes it safe to call in `onStart()`. #### 3. Configure Durable Object bindings @@ -326,11 +326,11 @@ export class MyMCP extends McpAgent { If you have an existing MCP server using the `McpAgent` class: - **Not using state?** Replace your `McpAgent` class with `McpServer` from `@modelcontextprotocol/sdk` and use `createMcpHandler(server)` in a Worker `fetch` handler. -- **Using state?** Use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. See [Stateful MCP Servers](/agents/api-reference/mcp-handler-api#stateful-mcp-servers) for details. -- **Need SSE support?** Continue using `McpAgent` with `serveSSE()` for legacy client compatibility. See the [McpAgent API reference](/agents/api-reference/mcp-agent-api/). +- **Using state?** Use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. See [Stateful MCP Servers](/agents/mcp/apis/handler-api/#stateful-mcp-servers) for details. +- **Need SSE support?** Continue using `McpAgent` with `serveSSE()` for legacy client compatibility. See the [McpAgent API reference](/agents/mcp/apis/agent-api/). ### Testing with MCP clients You can test your MCP server using an MCP client that supports remote connections, or use [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), an adapter that lets MCP clients that only support local connections work with remote MCP servers. -Follow [this guide](/agents/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server to Claude Desktop, Cursor, Windsurf, and other MCP clients. +Follow [this guide](/agents/mcp/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server to Claude Desktop, Cursor, Windsurf, and other MCP clients. diff --git a/src/content/docs/agents/model-context-protocol/index.mdx b/src/content/docs/agents/model-context-protocol/index.mdx deleted file mode 100644 index 775a3993cb0836f..000000000000000 --- a/src/content/docs/agents/model-context-protocol/index.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Model Context Protocol (MCP) -pcx_content_type: navigation -tags: - - MCP -sidebar: - order: 6 ---- - -You can build and deploy [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers on Cloudflare. - -## What is the Model Context Protocol (MCP)? - -[Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open standard that connects AI systems with external applications. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various accessories, MCP provides a standardized way to connect AI agents to different services. - -### MCP Terminology - -- **MCP Hosts**: AI assistants (like [Claude](https://claude.ai) or [Cursor](https://cursor.com)), AI agents, or applications that need to access external capabilities. -- **MCP Clients**: Clients embedded within the MCP hosts that connect to MCP servers and invoke tools. Each MCP client instance has a single connection to an MCP server. -- **MCP Servers**: Applications that expose [tools](/agents/model-context-protocol/tools/), [prompts](https://modelcontextprotocol.io/docs/concepts/prompts), and [resources](https://modelcontextprotocol.io/docs/concepts/resources) that MCP clients can use. - -### Remote vs. local MCP connections - -The MCP standard supports two modes of operation: - -- **Remote MCP connections**: MCP clients connect to MCP servers over the Internet, establishing a connection using [Streamable HTTP](/agents/model-context-protocol/transport/), and authorizing the MCP client access to resources on the user's account using [OAuth](/agents/model-context-protocol/authorization/). -- **Local MCP connections**: MCP clients connect to MCP servers on the same machine, using [stdio](https://spec.modelcontextprotocol.io/specification/draft/basic/transports/#stdio) as a local transport method. - -### Best Practices - -- **Tool design**: Do not treat your MCP server as a wrapper around your full API schema. Instead, build tools that are optimized for specific user goals and reliable outcomes. Fewer, well-designed tools often outperform many granular ones, especially for agents with small context windows or tight latency budgets. -- **Scoped permissions**: Deploying several focused MCP servers, each with narrowly scoped permissions, reduces the risk of over-privileged access and makes it easier to manage and audit what each server is allowed to do. -- **Tool descriptions**: Detailed parameter descriptions help agents understand how to use your tools correctly — including what values are expected, how they affect behavior, and any important constraints. This reduces errors and improves reliability. -- **Evaluation tests**: Use evaluation tests ('evals') to measure the agent’s ability to use your tools correctly. Run these after any updates to your server or tool descriptions to catch regressions early and track improvements over time. - -### Get Started - -Go to the [Getting Started](/agents/guides/remote-mcp-server/) guide to learn how to build and deploy your first remote MCP server to Cloudflare. diff --git a/src/content/docs/agents/platform/limits.mdx b/src/content/docs/agents/platform.mdx similarity index 93% rename from src/content/docs/agents/platform/limits.mdx rename to src/content/docs/agents/platform.mdx index aec3a744fa52d5e..ec4a6bde4bda01d 100644 --- a/src/content/docs/agents/platform/limits.mdx +++ b/src/content/docs/agents/platform.mdx @@ -1,8 +1,8 @@ --- pcx_content_type: concept -title: Limits +title: Platform limits sidebar: - order: 1 + order: 9 --- import { Render } from "~/components"; @@ -25,6 +25,6 @@ Many limits are inherited from those applied to Workers scripts and/or Durable O [^2]: You can deploy up to [500 scripts per account](/workers/platform/limits/), but each script (project) can define multiple Agents. Each deployed script can be up to 10 MB on the [Workers Paid Plan](/workers/platform/pricing/#workers) -[^3]: Compute (CPU) time per Agent is limited to 30 seconds, but this is refreshed when an Agent receives a new HTTP request, runs a [scheduled task](/agents/api-reference/schedule-tasks/), or an incoming WebSocket message. +[^3]: Compute (CPU) time per Agent is limited to 30 seconds, but this is refreshed when an Agent receives a new HTTP request, runs a [scheduled task](/agents/runtime/execution/schedule-tasks/), or an incoming WebSocket message. diff --git a/src/content/docs/agents/platform/prompt.txt.mdx b/src/content/docs/agents/platform/prompt.txt.mdx deleted file mode 100644 index a39d4719ad45f29..000000000000000 --- a/src/content/docs/agents/platform/prompt.txt.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: prompt.txt -external_link: /workers/prompt.txt -sidebar: - order: 99 -head: [] -description: Provide context to your AI models & tools when building on Cloudflare. ---- diff --git a/src/content/docs/agents/platform/prompting.mdx b/src/content/docs/agents/platform/prompting.mdx deleted file mode 100644 index aef72526d8226e4..000000000000000 --- a/src/content/docs/agents/platform/prompting.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: Prompt Engineering -external_link: /workers/get-started/prompting/ -sidebar: - order: 98 -head: [] -description: Learn how to prompt engineer your AI models & tools when building Agents & Workers on Cloudflare. ---- diff --git a/src/content/docs/agents/api-reference/agents-api.mdx b/src/content/docs/agents/runtime/agents-api.mdx similarity index 83% rename from src/content/docs/agents/api-reference/agents-api.mdx rename to src/content/docs/agents/runtime/agents-api.mdx index 4be999d9fb5c70d..1bede17c08075c8 100644 --- a/src/content/docs/agents/api-reference/agents-api.mdx +++ b/src/content/docs/agents/runtime/agents-api.mdx @@ -20,7 +20,7 @@ The Agents SDK provides two main APIs: :::note -Agents require [Cloudflare Durable Objects](/durable-objects/). Refer to [Configuration](/agents/api-reference/configuration/) to learn how to add the required bindings. +Agents require [Cloudflare Durable Objects](/durable-objects/). Refer to [Configuration](/agents/runtime/operations/configuration/) to learn how to add the required bindings. ::: @@ -55,7 +55,7 @@ flowchart TD | Method | When it runs | | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `onStart(props?)` | When the instance starts, or wakes from hibernation. Receives optional [initialization props](/agents/api-reference/routing/#props) passed via `getAgentByName` or `routeAgentRequest`. | +| `onStart(props?)` | When the instance starts, or wakes from hibernation. Receives optional [initialization props](/agents/runtime/communication/routing/#props) passed via `getAgentByName` or `routeAgentRequest`. | | `onRequest(request)` | For each HTTP request to the instance | | `onConnect(connection, ctx)` | When a WebSocket connection is established | | `onMessage(connection, message)` | For each WebSocket message received | @@ -77,23 +77,23 @@ flowchart TD | Feature | Methods | Documentation | | --------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | -| **State** | `setState()`, `onStateChanged()`, `initialState` | [Store and sync state](/agents/api-reference/store-and-sync-state/) | -| **Callable methods** | `@callable()` decorator | [Callable methods](/agents/api-reference/callable-methods/) | -| **Scheduling** | `schedule()`, `scheduleEvery()`, `getSchedules()`, `cancelSchedule()` | [Schedule tasks](/agents/api-reference/schedule-tasks/) | -| **Durable execution** | `runFiber()`, `stash()`, `onFiberRecovered()`, `keepAlive()`, `keepAliveWhile()` | [Durable execution](/agents/api-reference/durable-execution/) | -| **Queue** | `queue()`, `dequeue()`, `dequeueAll()`, `getQueue()` | [Queue tasks](/agents/api-reference/queue-tasks/) | -| **WebSockets** | `onConnect()`, `onMessage()`, `onClose()`, `broadcast()` | [WebSockets](/agents/api-reference/websockets/) | -| **HTTP/SSE** | `onRequest()` | [HTTP and SSE](/agents/api-reference/http-sse/) | -| **Email** | `onEmail()`, `replyToEmail()` | [Email routing](/agents/api-reference/email/) | -| **Workflows** | `runWorkflow()`, `waitForApproval()` | [Run Workflows](/agents/api-reference/run-workflows/) | -| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/api-reference/mcp-client-api/) | -| **AI Models** | Workers AI, OpenAI, Anthropic bindings | [Using AI models](/agents/api-reference/using-ai-models/) | -| **Protocol messages** | `shouldSendProtocolMessages()`, `isConnectionProtocolEnabled()` | [Protocol messages](/agents/api-reference/protocol-messages/) | -| **Context** | `getCurrentAgent()` | [getCurrentAgent()](/agents/api-reference/get-current-agent/) | -| **Observability** | `subscribe()`, diagnostics channels, Tail Workers | [Observability](/agents/api-reference/observability/) | -| **Sub-agents** | `subAgent()`, `abortSubAgent()`, `deleteSubAgent()` | [Sub-agents](/agents/api-reference/sub-agents/) | -| **Sessions** | `Session.create()`, context blocks, compaction, search | [Sessions](/agents/api-reference/sessions/) | -| **Think** | `Think` base class, workspace tools, lifecycle hooks, extensions | [Think](/agents/api-reference/think/) | +| **State** | `setState()`, `onStateChanged()`, `initialState` | [Store and sync state](/agents/runtime/lifecycle/state/) | +| **Callable methods** | `@callable()` decorator | [Callable methods](/agents/runtime/lifecycle/callable-methods/) | +| **Scheduling** | `schedule()`, `scheduleEvery()`, `getSchedules()`, `cancelSchedule()` | [Schedule tasks](/agents/runtime/execution/schedule-tasks/) | +| **Durable execution** | `runFiber()`, `stash()`, `onFiberRecovered()`, `keepAlive()`, `keepAliveWhile()` | [Durable execution](/agents/runtime/execution/durable-execution/) | +| **Queue** | `queue()`, `dequeue()`, `dequeueAll()`, `getQueue()` | [Queue tasks](/agents/runtime/execution/queue-tasks/) | +| **WebSockets** | `onConnect()`, `onMessage()`, `onClose()`, `broadcast()` | [WebSockets](/agents/runtime/communication/websockets/) | +| **HTTP/SSE** | `onRequest()` | [HTTP and SSE](/agents/runtime/communication/http-sse/) | +| **Email** | `onEmail()`, `replyToEmail()` | [Email routing](/agents/communication-channels/email/) | +| **Workflows** | `runWorkflow()`, `waitForApproval()` | [Run Workflows](/agents/runtime/execution/run-workflows/) | +| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/mcp/apis/client-api/) | +| **AI Models** | Workers AI, OpenAI, Anthropic bindings | [Using AI models](/agents/runtime/operations/using-ai-models/) | +| **Protocol messages** | `shouldSendProtocolMessages()`, `isConnectionProtocolEnabled()` | [Protocol messages](/agents/runtime/communication/protocol-messages/) | +| **Context** | `getCurrentAgent()` | [getCurrentAgent()](/agents/runtime/lifecycle/get-current-agent/) | +| **Observability** | `subscribe()`, diagnostics channels, Tail Workers | [Observability](/agents/runtime/operations/observability/) | +| **Sub-agents** | `subAgent()`, `abortSubAgent()`, `deleteSubAgent()` | [Sub-agents](/agents/runtime/execution/sub-agents/) | +| **Sessions** | `Session.create()`, context blocks, compaction, search | [Sessions](/agents/runtime/lifecycle/sessions/) | +| **Think** | `Think` base class, workspace tools, lifecycle hooks, extensions | [Think](/agents/harnesses/think/) | ## SQL API @@ -110,16 +110,16 @@ this.sql`INSERT INTO users (id, name) VALUES (${id}, ${name})`; const users = this.sql`SELECT * FROM users WHERE id = ${id}`; ``` -For state that needs to sync with clients, use the [State API](/agents/api-reference/store-and-sync-state/) instead. +For state that needs to sync with clients, use the [State API](/agents/runtime/lifecycle/state/) instead. ## Client-side API reference | Feature | Methods | Documentation | | -------------------- | ---------------- | ----------------------------------------------------------------------------- | -| **WebSocket client** | `AgentClient` | [Client SDK](/agents/api-reference/client-sdk/) | -| **HTTP client** | `agentFetch()` | [Client SDK](/agents/api-reference/client-sdk/#http-requests-with-agentfetch) | -| **React hook** | `useAgent()` | [Client SDK](/agents/api-reference/client-sdk/#react) | -| **Chat hook** | `useAgentChat()` | [Client SDK](/agents/api-reference/client-sdk/) | +| **WebSocket client** | `AgentClient` | [Client SDK](/agents/communication-channels/chat/client-sdk/) | +| **HTTP client** | `agentFetch()` | [Client SDK](/agents/communication-channels/chat/client-sdk/#http-requests-with-agentfetch) | +| **React hook** | `useAgent()` | [Client SDK](/agents/communication-channels/chat/client-sdk/#react) | +| **Chat hook** | `useAgentChat()` | [Client SDK](/agents/communication-channels/chat/client-sdk/) | ### Quick example @@ -162,7 +162,7 @@ Features include: - Automatic resumable streaming (reconnect mid-stream) - Works with `useAgentChat` React hook -Refer to [Build a chat agent](/agents/getting-started/build-a-chat-agent/) for a complete tutorial. +Refer to [Build a chat agent](/agents/examples/chat-agent/) for a complete tutorial. ## Routing @@ -187,7 +187,7 @@ export default { } satisfies ExportedHandler; ``` -Refer to [Routing](/agents/api-reference/routing/) for custom paths, CORS, and instance naming patterns. +Refer to [Routing](/agents/runtime/communication/routing/) for custom paths, CORS, and instance naming patterns. ## Next steps @@ -199,18 +199,18 @@ Refer to [Routing](/agents/api-reference/routing/) for custom paths, CORS, and i diff --git a/src/content/docs/agents/api-reference/http-sse.mdx b/src/content/docs/agents/runtime/communication/http-sse.mdx similarity index 92% rename from src/content/docs/agents/api-reference/http-sse.mdx rename to src/content/docs/agents/runtime/communication/http-sse.mdx index 8d9c0e88ef8144e..262bca949970429 100644 --- a/src/content/docs/agents/api-reference/http-sse.mdx +++ b/src/content/docs/agents/runtime/communication/http-sse.mdx @@ -143,8 +143,8 @@ export class ChatAgent extends Agent { SSE connections can be long-lived. Handle client disconnects gracefully: -- **Persist progress** — Write to [agent state](/agents/api-reference/store-and-sync-state/) so clients can resume -- **Use agent routing** — Clients can [reconnect to the same agent instance](/agents/api-reference/routing/) without session stores +- **Persist progress** — Write to [agent state](/agents/runtime/lifecycle/state/) so clients can resume +- **Use agent routing** — Clients can [reconnect to the same agent instance](/agents/runtime/communication/routing/) without session stores - **No timeout limits** — Cloudflare Workers have no effective limit on SSE response duration @@ -187,24 +187,24 @@ export class ResumeAgent extends Agent { **Recommendation:** Use WebSockets for interactive applications. Use SSE for streaming AI responses or server-push notifications. -Refer to [WebSockets](/agents/api-reference/websockets/) for WebSocket documentation. +Refer to [WebSockets](/agents/runtime/communication/websockets/) for WebSocket documentation. ## Next steps diff --git a/src/content/docs/agents/runtime/communication/index.mdx b/src/content/docs/agents/runtime/communication/index.mdx new file mode 100644 index 000000000000000..afc1b7250170575 --- /dev/null +++ b/src/content/docs/agents/runtime/communication/index.mdx @@ -0,0 +1,12 @@ +--- +title: Communication +pcx_content_type: navigation +sidebar: + order: 2 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/api-reference/protocol-messages.mdx b/src/content/docs/agents/runtime/communication/protocol-messages.mdx similarity index 88% rename from src/content/docs/agents/api-reference/protocol-messages.mdx rename to src/content/docs/agents/runtime/communication/protocol-messages.mdx index 07f2436d6eaa5f3..db8fe71593607ae 100644 --- a/src/content/docs/agents/api-reference/protocol-messages.mdx +++ b/src/content/docs/agents/runtime/communication/protocol-messages.mdx @@ -21,7 +21,7 @@ On every new connection, the Agent sends three protocol messages: State and MCP messages are also broadcast to all connections whenever they change. -For most web clients this is fine — the [Client SDK](/agents/api-reference/client-sdk/) and `useAgent` hook consume these messages automatically. However, some clients cannot handle JSON text frames: +For most web clients this is fine — the [Client SDK](/agents/communication-channels/chat/client-sdk/) and `useAgent` hook consume these messages automatically. However, some clients cannot handle JSON text frames: - **Binary-only clients** — MQTT devices, IoT sensors, custom binary protocols - **Lightweight clients** — Embedded systems with minimal WebSocket stacks @@ -170,7 +170,7 @@ An overridable hook that determines if a connection should receive protocol mess Default: returns `true` (all connections receive protocol messages). -This hook is evaluated once on connect. The result is persisted in the connection's WebSocket attachment and survives [hibernation](/agents/api-reference/websockets/#hibernation). +This hook is evaluated once on connect. The result is persisted in the connection's WebSocket attachment and survives [hibernation](/agents/runtime/communication/websockets/#hibernation). ### `isConnectionProtocolEnabled` @@ -185,18 +185,18 @@ Safe to call at any time, including after the agent wakes from hibernation. ## How it works -Protocol status is stored as an internal flag in the connection's WebSocket attachment — the same mechanism used by [readonly connections](/agents/api-reference/readonly-connections/). This means: +Protocol status is stored as an internal flag in the connection's WebSocket attachment — the same mechanism used by [readonly connections](/agents/runtime/communication/readonly-connections/). This means: - **Survives hibernation** — the flag is serialized and restored when the agent wakes up - **No cleanup needed** — connection state is automatically discarded when the connection closes - **Zero overhead** — no database tables or queries, just the connection's built-in attachment - **Safe from user code** — `connection.state` and `connection.setState()` never expose or overwrite the flag -Unlike [readonly](/agents/api-reference/readonly-connections/) which can be toggled dynamically with `setConnectionReadonly()`, protocol status is set once on connect and cannot be changed afterward. To change a connection's protocol status, the client must disconnect and reconnect. +Unlike [readonly](/agents/runtime/communication/readonly-connections/) which can be toggled dynamically with `setConnectionReadonly()`, protocol status is set once on connect and cannot be changed afterward. To change a connection's protocol status, the client must disconnect and reconnect. ## Related resources -- [Readonly connections](/agents/api-reference/readonly-connections/) -- [WebSockets](/agents/api-reference/websockets/) -- [Store and sync state](/agents/api-reference/store-and-sync-state/) -- [MCP Client API](/agents/api-reference/mcp-client-api/) +- [Readonly connections](/agents/runtime/communication/readonly-connections/) +- [WebSockets](/agents/runtime/communication/websockets/) +- [Store and sync state](/agents/runtime/lifecycle/state/) +- [MCP Client API](/agents/mcp/apis/client-api/) diff --git a/src/content/docs/agents/api-reference/readonly-connections.mdx b/src/content/docs/agents/runtime/communication/readonly-connections.mdx similarity index 97% rename from src/content/docs/agents/api-reference/readonly-connections.mdx rename to src/content/docs/agents/runtime/communication/readonly-connections.mdx index 0a11e525baf0859..2bcd29caefc339d 100644 --- a/src/content/docs/agents/api-reference/readonly-connections.mdx +++ b/src/content/docs/agents/runtime/communication/readonly-connections.mdx @@ -452,7 +452,7 @@ function GameComponent() { ## How it works -Readonly status is stored in the connection's WebSocket attachment, which persists through the WebSocket Hibernation API. The flag is namespaced internally so it cannot be accidentally overwritten by `connection.setState()`. The same mechanism is used by [protocol message control](/agents/api-reference/protocol-messages/) — both flag coexist safely in the attachment. This means: +Readonly status is stored in the connection's WebSocket attachment, which persists through the WebSocket Hibernation API. The flag is namespaced internally so it cannot be accidentally overwritten by `connection.setState()`. The same mechanism is used by [protocol message control](/agents/runtime/communication/protocol-messages/) — both flag coexist safely in the attachment. This means: - **Survives hibernation** — the flag is serialized and restored when the agent wakes up - **No cleanup needed** — connection state is automatically discarded when the connection closes @@ -624,7 +624,7 @@ export class AuditedAgent extends Agent { ## Related resources -- [Store and sync state](/agents/api-reference/store-and-sync-state/) -- [Protocol messages](/agents/api-reference/protocol-messages/) — suppress JSON protocol frames for binary-only clients (can be combined with readonly) -- [WebSockets](/agents/api-reference/websockets/) -- [Callable methods](/agents/api-reference/callable-methods/) +- [Store and sync state](/agents/runtime/lifecycle/state/) +- [Protocol messages](/agents/runtime/communication/protocol-messages/) — suppress JSON protocol frames for binary-only clients (can be combined with readonly) +- [WebSockets](/agents/runtime/communication/websockets/) +- [Callable methods](/agents/runtime/lifecycle/callable-methods/) diff --git a/src/content/docs/agents/api-reference/routing.mdx b/src/content/docs/agents/runtime/communication/routing.mdx similarity index 97% rename from src/content/docs/agents/api-reference/routing.mdx rename to src/content/docs/agents/runtime/communication/routing.mdx index 1d9c62f2c766e81..446b42f95af9886 100644 --- a/src/content/docs/agents/api-reference/routing.mdx +++ b/src/content/docs/agents/runtime/communication/routing.mdx @@ -469,7 +469,7 @@ export default { For agent-specific initialization, use `getAgentByName` instead where you control exactly which agent receives the props. :::note -For `McpAgent`, props are automatically stored and accessible via `this.props`. Refer to [MCP servers](/agents/api-reference/mcp-agent-api/) for details. +For `McpAgent`, props are automatically stored and accessible via `this.props`. Refer to [MCP servers](/agents/mcp/apis/agent-api/) for details. ::: ### Hooks @@ -493,7 +493,7 @@ const response = await routeAgentRequest(request, env, { -These hooks are useful for authentication and validation. Refer to [Cross-domain authentication](/agents/guides/cross-domain-authentication/) for detailed examples. +These hooks are useful for authentication and validation. Refer to [Cross-domain authentication](/agents/runtime/operations/cross-domain-authentication/) for detailed examples. ## Server-side agent access @@ -746,7 +746,7 @@ export default app; -For WebSocket authentication patterns (tokens in URLs, JWT refresh), refer to [Cross-domain authentication](/agents/guides/cross-domain-authentication/). +For WebSocket authentication patterns (tokens in URLs, JWT refresh), refer to [Cross-domain authentication](/agents/runtime/operations/cross-domain-authentication/). ## Troubleshooting @@ -856,24 +856,24 @@ class SecureAgent extends Agent { diff --git a/src/content/docs/agents/api-reference/websockets.mdx b/src/content/docs/agents/runtime/communication/websockets.mdx similarity index 97% rename from src/content/docs/agents/api-reference/websockets.mdx rename to src/content/docs/agents/runtime/communication/websockets.mdx index 835070790cd7ad6..90a1686a492cd07 100644 --- a/src/content/docs/agents/api-reference/websockets.mdx +++ b/src/content/docs/agents/runtime/communication/websockets.mdx @@ -7,7 +7,7 @@ sidebar: import { TypeScriptExample, LinkCard } from "~/components"; -Agents support WebSocket connections for real-time, bi-directional communication. This page covers server-side WebSocket handling. For client-side connection, refer to the [Client SDK](/agents/api-reference/client-sdk/). +Agents support WebSocket connections for real-time, bi-directional communication. This page covers server-side WebSocket handling. For client-side connection, refer to the [Client SDK](/agents/communication-channels/chat/client-sdk/). ## Lifecycle hooks @@ -221,7 +221,7 @@ export class ChatAgent extends Agent { | `getConnection` | `(id: string) => Connection \| undefined` | Get connection by ID | | `getConnectionTags` | `(connection, ctx) => string[]` | Override to tag connections | | `broadcast` | `(message, without?: string[]) => void` | Send to all connections | -| `isConnectionReadonly` | `(connection) => boolean` | Check if a connection is [readonly](/agents/api-reference/readonly-connections/) | +| `isConnectionReadonly` | `(connection) => boolean` | Check if a connection is [readonly](/agents/runtime/communication/readonly-connections/) | | `isConnectionProtocolEnabled` | `(connection) => boolean` | Check if protocol messages are enabled for this connection | ## Handling binary data @@ -252,7 +252,7 @@ export class FileAgent extends Agent { :::note -Agents automatically send JSON text frames (identity, state, MCP servers) to every connection. If your client only handles binary data and cannot process these frames, use [`shouldSendProtocolMessages`](/agents/api-reference/protocol-messages/) to suppress them. +Agents automatically send JSON text frames (identity, state, MCP servers) to every connection. If your client only handles binary data and cannot process these frames, use [`shouldSendProtocolMessages`](/agents/runtime/communication/protocol-messages/) to suppress them. ::: ## Error and close handling @@ -551,24 +551,24 @@ For browser connections, use the Agents client SDK: - **Vanilla JS**: `AgentClient` from `agents/client` - **React**: `useAgent` hook from `agents/react` -Refer to [Client SDK](/agents/api-reference/client-sdk/) for full documentation. +Refer to [Client SDK](/agents/communication-channels/chat/client-sdk/) for full documentation. ## Next steps diff --git a/src/content/docs/agents/api-reference/durable-execution.mdx b/src/content/docs/agents/runtime/execution/durable-execution.mdx similarity index 97% rename from src/content/docs/agents/api-reference/durable-execution.mdx rename to src/content/docs/agents/runtime/execution/durable-execution.mdx index 26a433ef3e1c51c..539eabb5ea5235b 100644 --- a/src/content/docs/agents/api-reference/durable-execution.mdx +++ b/src/content/docs/agents/runtime/execution/durable-execution.mdx @@ -1,7 +1,7 @@ --- -title: Durable execution +title: Durable execution with fibers pcx_content_type: reference -description: Run work that survives Durable Object eviction with runFiber(), keepAlive(), and crash recovery. +description: Run work that survives Durable Object eviction with fibers, runFiber(), keepAlive(), and crash recovery. tags: - AI sidebar: @@ -342,6 +342,6 @@ Run an async function while keeping the DO alive. Heartbeat starts before `fn` a ## Related - [Long-running agents](/agents/concepts/long-running-agents/) — how fibers compose with schedules, plans, and async operations -- [Schedule tasks](/agents/api-reference/schedule-tasks/) — `keepAlive` details and the alarm system +- [Schedule tasks](/agents/runtime/execution/schedule-tasks/) — `keepAlive` details and the alarm system - [Workflows](/agents/concepts/workflows/) — durable multi-step execution outside the agent -- [Chat agents](/agents/api-reference/chat-agents/) — `chatRecovery` and `onChatRecovery` +- [Chat agents](/agents/communication-channels/chat/chat-agents/) — `chatRecovery` and `onChatRecovery` diff --git a/src/content/docs/agents/runtime/execution/index.mdx b/src/content/docs/agents/runtime/execution/index.mdx new file mode 100644 index 000000000000000..6014c2a070bd27a --- /dev/null +++ b/src/content/docs/agents/runtime/execution/index.mdx @@ -0,0 +1,12 @@ +--- +title: Execution +pcx_content_type: navigation +sidebar: + order: 3 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/api-reference/queue-tasks.mdx b/src/content/docs/agents/runtime/execution/queue-tasks.mdx similarity index 94% rename from src/content/docs/agents/api-reference/queue-tasks.mdx rename to src/content/docs/agents/runtime/execution/queue-tasks.mdx index c77f9f7edffc353..32ca6e2fffdf611 100644 --- a/src/content/docs/agents/api-reference/queue-tasks.mdx +++ b/src/content/docs/agents/runtime/execution/queue-tasks.mdx @@ -44,7 +44,7 @@ async queue( - `callback` - The name of the method to call when processing the task - `payload` - Data to pass to the callback method - `options` - Optional configuration: - - `retry` - Retry options for the callback execution. If the callback throws, it is retried with exponential backoff. Refer to [Retries](/agents/api-reference/retries/) for details on `RetryOptions` + - `retry` - Retry options for the callback execution. If the callback throws, it is retried with exponential backoff. Refer to [Retries](/agents/runtime/execution/retries/) for details on `RetryOptions` **Returns:** The unique ID of the queued task @@ -335,7 +335,7 @@ class RobustAgent extends Agent { -If no `retry` option is provided, the class-level defaults from `static options.retry` are used (3 attempts, 100ms base delay, 3s max delay). Refer to [Retries](/agents/api-reference/retries/) for full details. +If no `retry` option is provided, the class-level defaults from `static options.retry` are used (3 attempts, 100ms base delay, 3s max delay). Refer to [Retries](/agents/runtime/execution/retries/) for full details. ## Best practices @@ -350,7 +350,7 @@ If no `retry` option is provided, the class-level defaults from `static options. The queue system works with other Agent SDK features: - **State management**: Access agent state within queued callbacks. -- **Scheduling**: Combine with [`schedule()`](/agents/api-reference/schedule-tasks/) for time-based queue processing. +- **Scheduling**: Combine with [`schedule()`](/agents/runtime/execution/schedule-tasks/) for time-based queue processing. - **Context**: Queued tasks maintain the original request context. - **Database**: Uses the same database as other agent data. @@ -363,7 +363,7 @@ The queue system works with other Agent SDK features: ## Queue vs Schedule -Use **queue** when you want tasks to execute as soon as possible in order. Use [**schedule**](/agents/api-reference/schedule-tasks/) when you need tasks to run at specific times or on a recurring basis. +Use **queue** when you want tasks to execute as soon as possible in order. Use [**schedule**](/agents/runtime/execution/schedule-tasks/) when you need tasks to run at specific times or on a recurring basis. | Feature | Queue | Schedule | | ---------------- | ------------------------ | --------------------------- | @@ -375,18 +375,18 @@ Use **queue** when you want tasks to execute as soon as possible in order. Use [ diff --git a/src/content/docs/agents/api-reference/retries.mdx b/src/content/docs/agents/runtime/execution/retries.mdx similarity index 98% rename from src/content/docs/agents/api-reference/retries.mdx rename to src/content/docs/agents/runtime/execution/retries.mdx index 5fa57173fb287e1..4dd2ed32de9e626 100644 --- a/src/content/docs/agents/api-reference/retries.mdx +++ b/src/content/docs/agents/runtime/execution/retries.mdx @@ -504,18 +504,18 @@ class MyAgent extends Agent { diff --git a/src/content/docs/agents/api-reference/run-workflows.mdx b/src/content/docs/agents/runtime/execution/run-workflows.mdx similarity index 99% rename from src/content/docs/agents/api-reference/run-workflows.mdx rename to src/content/docs/agents/runtime/execution/run-workflows.mdx index 669935e39363816..c1db1e2169964df 100644 --- a/src/content/docs/agents/api-reference/run-workflows.mdx +++ b/src/content/docs/agents/runtime/execution/run-workflows.mdx @@ -844,13 +844,13 @@ Workflows cannot open WebSocket connections directly. Use `broadcastToClients()` diff --git a/src/content/docs/agents/api-reference/schedule-tasks.mdx b/src/content/docs/agents/runtime/execution/schedule-tasks.mdx similarity index 98% rename from src/content/docs/agents/api-reference/schedule-tasks.mdx rename to src/content/docs/agents/runtime/execution/schedule-tasks.mdx index 4e8ca177991a8db..6249019c4805bc4 100644 --- a/src/content/docs/agents/api-reference/schedule-tasks.mdx +++ b/src/content/docs/agents/runtime/execution/schedule-tasks.mdx @@ -701,7 +701,7 @@ Schedule a task for future execution. - `when` - When to execute: `number` (seconds delay), `Date` (specific time), or `string` (cron expression) - `callback` - Name of the method to call - `payload` - Data to pass to the callback (must be JSON-serializable) -- `options.retry` - Optional retry configuration. Refer to [Retries](/agents/api-reference/retries/) for details +- `options.retry` - Optional retry configuration. Refer to [Retries](/agents/runtime/execution/retries/) for details - `options.idempotent` - Deduplicate by callback + payload. Defaults to `true` for cron schedules, `false` for delayed and Date-based schedules **Returns:** A `Schedule` object with the task details @@ -749,7 +749,7 @@ Schedule a task to run repeatedly at a fixed interval. - `intervalSeconds` - Number of seconds between executions (must be greater than 0) - `callback` - Name of the method to call - `payload` - Data to pass to the callback (must be JSON-serializable) -- `options.retry` - Optional retry configuration. Refer to [Retries](/agents/api-reference/retries/) for details. +- `options.retry` - Optional retry configuration. Refer to [Retries](/agents/runtime/execution/retries/) for details. **Returns:** A `Schedule` object with `type: "interval"` @@ -898,24 +898,24 @@ dispose2(); // Now the agent can go idle diff --git a/src/content/docs/agents/api-reference/sub-agents.mdx b/src/content/docs/agents/runtime/execution/sub-agents.mdx similarity index 96% rename from src/content/docs/agents/api-reference/sub-agents.mdx rename to src/content/docs/agents/runtime/execution/sub-agents.mdx index 71c8d8db733f120..e5f7733ecc59bad 100644 --- a/src/content/docs/agents/api-reference/sub-agents.mdx +++ b/src/content/docs/agents/runtime/execution/sub-agents.mdx @@ -331,7 +331,7 @@ For scheduled work, have the parent schedule the task and delegate to the sub-ag ## Related -- [Think](/agents/api-reference/think/) — `chat()` method for streaming AI turns through sub-agents +- [Think](/agents/harnesses/think/) — `chat()` method for streaming AI turns through sub-agents - [Long-running agents](/agents/concepts/long-running-agents/) — sub-agent delegation in the context of multi-week agent lifetimes -- [Callable methods](/agents/api-reference/callable-methods/) — RPC via `@callable` and service bindings -- [Chat agents](/agents/api-reference/chat-agents/) — `ToolLoopAgent` for in-process AI SDK sub-calls +- [Callable methods](/agents/runtime/lifecycle/callable-methods/) — RPC via `@callable` and service bindings +- [Chat agents](/agents/communication-channels/chat/chat-agents/) — `ToolLoopAgent` for in-process AI SDK sub-calls diff --git a/src/content/docs/agents/runtime/index.mdx b/src/content/docs/agents/runtime/index.mdx new file mode 100644 index 000000000000000..af883fedb8318a2 --- /dev/null +++ b/src/content/docs/agents/runtime/index.mdx @@ -0,0 +1,14 @@ +--- +title: Runtime +pcx_content_type: navigation +sidebar: + order: 6 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + +The runtime powers your agent — state, communication, execution, and operations. + + diff --git a/src/content/docs/agents/concepts/agent-class.mdx b/src/content/docs/agents/runtime/lifecycle/agent-class.mdx similarity index 96% rename from src/content/docs/agents/concepts/agent-class.mdx rename to src/content/docs/agents/runtime/lifecycle/agent-class.mdx index 272379ecf20bcb4..fd5f96c7d1f593e 100644 --- a/src/content/docs/agents/concepts/agent-class.mdx +++ b/src/content/docs/agents/runtime/lifecycle/agent-class.mdx @@ -7,7 +7,7 @@ sidebar: The core of the `agents` library is the `Agent` class. You extend it, override a few methods, and get state management, WebSockets, scheduling, RPC, and more for free. This page explains how `Agent` is built, layer by layer, so you understand what is happening under the hood. -The snippets shown here are illustrative and do not necessarily represent best practices. For the full API, refer to the [API reference](/agents/api-reference/) and the [source code](https://github.com/cloudflare/agents/blob/main/packages/agents/src/index.ts). +The snippets shown here are illustrative and do not necessarily represent best practices. For the full API, refer to the [API reference](/agents/runtime/) and the [source code](https://github.com/cloudflare/agents/blob/main/packages/agents/src/index.ts). ## What is the Agent? @@ -207,7 +207,7 @@ class MyAgent extends Agent { } ``` -State is stored in the `cf_agents_state` SQL table. State messages are sent with `type: "cf_agent_state"` (both from the client and the server). Since `agents` provides [JS and React clients](/agents/api-reference/store-and-sync-state/#synchronizing-state), real-time state updates are available out of the box. +State is stored in the `cf_agents_state` SQL table. State messages are sent with `type: "cf_agent_state"` (both from the client and the server). Since `agents` provides [JS and React clients](/agents/runtime/lifecycle/state/#synchronizing-state), real-time state updates are available out of the box. ### `this.sql` @@ -325,7 +325,7 @@ Schedules are stored in the `cf_agents_schedules` SQL table. Cron schedules auto ### `this.mcp` and friends -`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is properly documented in [MCP client API](/agents/api-reference/mcp-client-api/). +`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is properly documented in [MCP client API](/agents/mcp/apis/client-api/). ```ts class MyAgent extends Agent { @@ -504,7 +504,7 @@ class MyAgent extends Agent { } ``` -`AIChatAgent` uses `keepAliveWhile` internally to keep the agent alive during streaming LLM responses. For more details, refer to [Schedule tasks — Keeping the agent alive](/agents/api-reference/schedule-tasks/#keeping-the-agent-alive). +`AIChatAgent` uses `keepAliveWhile` internally to keep the agent alive during streaming LLM responses. For more details, refer to [Schedule tasks — Keeping the agent alive](/agents/runtime/execution/schedule-tasks/#keeping-the-agent-alive). ### Routing @@ -522,7 +522,7 @@ return new Response("Not found", { status: 404 }); ## Layer 3: `AIChatAgent` -The [`AIChatAgent`](/agents/api-reference/chat-agents/) class from `@cloudflare/ai-chat` extends `Agent` with an opinionated layer for AI chat. It adds automatic message persistence to SQLite, resumable streaming, tool support (server-side, client-side, and human-in-the-loop), and a React hook (`useAgentChat`) for building chat UIs. +The [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/) class from `@cloudflare/ai-chat` extends `Agent` with an opinionated layer for AI chat. It adds automatic message persistence to SQLite, resumable streaming, tool support (server-side, client-side, and human-in-the-loop), and a React hook (`useAgentChat`) for building chat UIs. The full hierarchy is: **DurableObject** > **Server** > **Agent** > **AIChatAgent**. diff --git a/src/content/docs/agents/api-reference/callable-methods.mdx b/src/content/docs/agents/runtime/lifecycle/callable-methods.mdx similarity index 99% rename from src/content/docs/agents/api-reference/callable-methods.mdx rename to src/content/docs/agents/runtime/lifecycle/callable-methods.mdx index 4ace7093dba8089..bd5a8930ace5f2d 100644 --- a/src/content/docs/agents/api-reference/callable-methods.mdx +++ b/src/content/docs/agents/runtime/lifecycle/callable-methods.mdx @@ -740,18 +740,18 @@ Do not set `"experimentalDecorators": true` in your `tsconfig.json`. The Agents diff --git a/src/content/docs/agents/api-reference/get-current-agent.mdx b/src/content/docs/agents/runtime/lifecycle/get-current-agent.mdx similarity index 98% rename from src/content/docs/agents/api-reference/get-current-agent.mdx rename to src/content/docs/agents/runtime/lifecycle/get-current-agent.mdx index b4d2b6f3faed2e4..09d668ae9d2525f 100644 --- a/src/content/docs/agents/api-reference/get-current-agent.mdx +++ b/src/content/docs/agents/runtime/lifecycle/get-current-agent.mdx @@ -274,18 +274,18 @@ The context available depends on how the method was invoked: diff --git a/src/content/docs/agents/runtime/lifecycle/index.mdx b/src/content/docs/agents/runtime/lifecycle/index.mdx new file mode 100644 index 000000000000000..cc12db0abd28000 --- /dev/null +++ b/src/content/docs/agents/runtime/lifecycle/index.mdx @@ -0,0 +1,12 @@ +--- +title: Lifecycle +pcx_content_type: navigation +sidebar: + order: 1 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/api-reference/sessions.mdx b/src/content/docs/agents/runtime/lifecycle/sessions.mdx similarity index 98% rename from src/content/docs/agents/api-reference/sessions.mdx rename to src/content/docs/agents/runtime/lifecycle/sessions.mdx index f18c2b5d6d785be..10241c1f0a19f58 100644 --- a/src/content/docs/agents/api-reference/sessions.mdx +++ b/src/content/docs/agents/runtime/lifecycle/sessions.mdx @@ -648,6 +648,6 @@ All storage is in Durable Object SQLite. Tables are created lazily on first use. ## Related -- [Think](/agents/api-reference/think/) — opinionated chat agent that uses Session for conversation storage via `configureSession()` -- [Chat agents](/agents/api-reference/chat-agents/) — `AIChatAgent` with its own message persistence layer -- [Store and sync state](/agents/api-reference/store-and-sync-state/) — `setState()` for simpler key-value persistence +- [Think](/agents/harnesses/think/) — opinionated chat agent that uses Session for conversation storage via `configureSession()` +- [Chat agents](/agents/communication-channels/chat/chat-agents/) — `AIChatAgent` with its own message persistence layer +- [Store and sync state](/agents/runtime/lifecycle/state/) — `setState()` for simpler key-value persistence diff --git a/src/content/docs/agents/api-reference/store-and-sync-state.mdx b/src/content/docs/agents/runtime/lifecycle/state.mdx similarity index 95% rename from src/content/docs/agents/api-reference/store-and-sync-state.mdx rename to src/content/docs/agents/runtime/lifecycle/state.mdx index e7977acc6e6b8a3..5d186c3b02595ce 100644 --- a/src/content/docs/agents/api-reference/store-and-sync-state.mdx +++ b/src/content/docs/agents/runtime/lifecycle/state.mdx @@ -24,7 +24,7 @@ State within an Agent is: Agent state is stored in a SQL database embedded within each individual Agent instance. You can interact with it using the higher-level `this.setState` API (recommended), which allows you to sync state and trigger events on state changes, or by directly querying the database with `this.sql`. :::note[State vs Props] -**State** is persistent data that survives restarts and syncs across clients. **[Props](/agents/api-reference/routing/#props)** are one-time initialization arguments passed when an agent is instantiated - use props for configuration that does not need to persist. +**State** is persistent data that survives restarts and syncs across clients. **[Props](/agents/runtime/communication/routing/#props)** are one-time initialization arguments passed when an agent is instantiated - use props for configuration that does not need to persist. ::: @@ -183,7 +183,7 @@ export class MinimalAgent extends Agent { Use `setState()` to update state. This: 1. Saves to SQLite (persistent) -2. Broadcasts to all connected clients (excluding connections where [`shouldSendProtocolMessages`](/agents/api-reference/protocol-messages/) returned `false`) +2. Broadcasts to all connected clients (excluding connections where [`shouldSendProtocolMessages`](/agents/runtime/communication/protocol-messages/) returned `false`) 3. Triggers `onStateChanged()` (after broadcast; best-effort) @@ -423,7 +423,7 @@ flowchart TD ## State from Workflows -When using [Workflows](/agents/api-reference/run-workflows/), you can update agent state from workflow steps: +When using [Workflows](/agents/runtime/execution/run-workflows/), you can update agent state from workflow steps: @@ -639,7 +639,7 @@ onStateChanged(state: State, source: Connection | "server") { ## Use Agent state as model context -You can combine the state and SQL APIs in your Agent with its ability to [call AI models](/agents/api-reference/using-ai-models/) to include historical context within your prompts to a model. Modern Large Language Models (LLMs) often have very large context windows (up to millions of tokens), which allows you to pull relevant context into your prompt directly. +You can combine the state and SQL APIs in your Agent with its ability to [call AI models](/agents/runtime/operations/using-ai-models/) to include historical context within your prompts to a model. Modern Large Language Models (LLMs) often have very large context windows (up to millions of tokens), which allows you to pull relevant context into your prompt directly. For example, you can use an Agent's built-in SQL database to pull history, query a model with it, and append to that history ahead of the next call to the model: @@ -716,24 +716,24 @@ This works because each instance of an Agent has its own database, and the state diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/runtime/operations/configuration.mdx similarity index 98% rename from src/content/docs/agents/api-reference/configuration.mdx rename to src/content/docs/agents/runtime/operations/configuration.mdx index 6b10f6d597689bb..2ed1b5e1a033b29 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/runtime/operations/configuration.mdx @@ -322,7 +322,7 @@ export default defineConfig({ The `agents()` plugin is safe to include even if your project does not use decorators. It only runs the transform on files that contain `@` syntax. -The starter template and all examples include this plugin by default. If you encounter `SyntaxError: Invalid or unexpected token` with decorators, refer to [Callable methods — Troubleshooting](/agents/api-reference/callable-methods/#troubleshooting). +The starter template and all examples include this plugin by default. If you encounter `SyntaxError: Invalid or unexpected token` with decorators, refer to [Callable methods — Troubleshooting](/agents/runtime/lifecycle/callable-methods/#troubleshooting). ## Generating types @@ -941,18 +941,18 @@ Migration tags must be unique. If you see conflicts: diff --git a/src/content/docs/agents/guides/cross-domain-authentication.mdx b/src/content/docs/agents/runtime/operations/cross-domain-authentication.mdx similarity index 98% rename from src/content/docs/agents/guides/cross-domain-authentication.mdx rename to src/content/docs/agents/runtime/operations/cross-domain-authentication.mdx index 07554aa0acc65aa..78f94544d3a4371 100644 --- a/src/content/docs/agents/guides/cross-domain-authentication.mdx +++ b/src/content/docs/agents/runtime/operations/cross-domain-authentication.mdx @@ -283,18 +283,18 @@ export class SecureAgent extends Agent { diff --git a/src/content/docs/agents/runtime/operations/index.mdx b/src/content/docs/agents/runtime/operations/index.mdx new file mode 100644 index 000000000000000..a451c862df9407e --- /dev/null +++ b/src/content/docs/agents/runtime/operations/index.mdx @@ -0,0 +1,12 @@ +--- +title: Operations +pcx_content_type: navigation +sidebar: + order: 4 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + + diff --git a/src/content/docs/agents/api-reference/observability.mdx b/src/content/docs/agents/runtime/operations/observability.mdx similarity index 99% rename from src/content/docs/agents/api-reference/observability.mdx rename to src/content/docs/agents/runtime/operations/observability.mdx index 81f492b5c0571b4..43147b89c11438b 100644 --- a/src/content/docs/agents/api-reference/observability.mdx +++ b/src/content/docs/agents/runtime/operations/observability.mdx @@ -233,7 +233,7 @@ These events are emitted by `AIChatAgent` from `@cloudflare/ai-chat`. They track @@ -245,6 +245,6 @@ These events are emitted by `AIChatAgent` from `@cloudflare/ai-chat`. They track diff --git a/src/content/docs/agents/api-reference/using-ai-models.mdx b/src/content/docs/agents/runtime/operations/using-ai-models.mdx similarity index 92% rename from src/content/docs/agents/api-reference/using-ai-models.mdx rename to src/content/docs/agents/runtime/operations/using-ai-models.mdx index b83fb56ea10d3c9..5472833a4a77ba0 100644 --- a/src/content/docs/agents/api-reference/using-ai-models.mdx +++ b/src/content/docs/agents/runtime/operations/using-ai-models.mdx @@ -23,13 +23,13 @@ The [AI SDK](https://sdk.vercel.ai/docs/introduction) provides a unified interfa ## Calling AI Models -You can call models from any method within an Agent, including from HTTP requests using the [`onRequest`](/agents/api-reference/agents-api/) handler, when a [scheduled task](/agents/api-reference/schedule-tasks/) runs, when handling a WebSocket message in the [`onMessage`](/agents/api-reference/websockets/) handler, or from any of your own methods. +You can call models from any method within an Agent, including from HTTP requests using the [`onRequest`](/agents/runtime/agents-api/) handler, when a [scheduled task](/agents/runtime/execution/schedule-tasks/) runs, when handling a WebSocket message in the [`onMessage`](/agents/runtime/communication/websockets/) handler, or from any of your own methods. Agents can call AI models on their own — autonomously — and can handle long-running responses that take minutes (or longer) to respond in full. If a client disconnects mid-stream, the Agent keeps running and can catch the client up when it reconnects. ### Streaming over WebSockets {/* long-running-model-requests */} -Modern reasoning models can take some time to both generate a response _and_ stream the response back to the client. Instead of buffering the entire response, you can stream it back over [WebSockets](/agents/api-reference/websockets/). +Modern reasoning models can take some time to both generate a response _and_ stream the response back to the client. Instead of buffering the entire response, you can stream it back over [WebSockets](/agents/runtime/communication/websockets/). @@ -76,7 +76,7 @@ export class MyAgent extends Agent { -You can also persist AI model responses back to [Agent state](/agents/api-reference/store-and-sync-state/) using `this.setState`. If a user disconnects, read the message history back and send it to the user when they reconnect. +You can also persist AI model responses back to [Agent state](/agents/runtime/lifecycle/state/) using `this.setState`. If a user disconnects, read the message history back and send it to the user when they reconnect. ## Workers AI @@ -239,7 +239,7 @@ export class MyAgent extends Agent { Agents can call models across any service that supports the OpenAI API. For example, you can use the OpenAI SDK to call one of [Google's Gemini models](https://ai.google.dev/gemini-api/docs/openai#node.js) directly from your Agent. -Agents can stream responses back over HTTP using Server-Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSocket API](/agents/api-reference/websockets/) to stream responses back to a client. +Agents can stream responses back over HTTP using Server-Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSocket API](/agents/runtime/communication/websockets/) to stream responses back to a client. diff --git a/src/content/docs/agents/api-reference/browse-the-web.mdx b/src/content/docs/agents/tools/browser.mdx similarity index 97% rename from src/content/docs/agents/api-reference/browse-the-web.mdx rename to src/content/docs/agents/tools/browser.mdx index cbee6db82aa509e..a55420a05a5ec11 100644 --- a/src/content/docs/agents/api-reference/browse-the-web.mdx +++ b/src/content/docs/agents/tools/browser.mdx @@ -1,8 +1,8 @@ --- -title: Browse the web +title: Browser pcx_content_type: reference sidebar: - order: 15 + order: 1 --- import { @@ -12,7 +12,7 @@ import { PackageManagers, } from "~/components"; -Give your agents full access to the [Chrome DevTools Protocol (CDP)](/browser-run/cdp/) with [Browser Run](/browser-run/) tools. +Give your agents full access to [Browser Run](/browser-run/) tools to inspect pages, capture screenshots, scrape rendered content, and debug frontend issues. Instead of a fixed set of browser actions (click, screenshot, navigate), the LLM writes JavaScript code that runs CDP commands against a live browser session — accessing all domains, commands, events, and types in the protocol. @@ -143,7 +143,7 @@ async () => { ## Use with an Agent -The typical pattern is to create browser tools inside an [`AIChatAgent`](/agents/api-reference/chat-agents/) message handler, which gives you message persistence and streaming: +The typical pattern is to create browser tools inside an [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/) message handler, which gives you message persistence and streaming: diff --git a/src/content/docs/agents/tools/index.mdx b/src/content/docs/agents/tools/index.mdx new file mode 100644 index 000000000000000..46dcf1412aab494 --- /dev/null +++ b/src/content/docs/agents/tools/index.mdx @@ -0,0 +1,14 @@ +--- +title: Tools +pcx_content_type: navigation +sidebar: + order: 4 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + +Tools extend what agents can do — browse the web, process payments, run code, and more. + + diff --git a/src/content/docs/agents/agentic-payments/index.mdx b/src/content/docs/agents/tools/payments/index.mdx similarity index 96% rename from src/content/docs/agents/agentic-payments/index.mdx rename to src/content/docs/agents/tools/payments/index.mdx index 40c02740d2d2b5e..2bf8aa391c41a73 100644 --- a/src/content/docs/agents/agentic-payments/index.mdx +++ b/src/content/docs/agents/tools/payments/index.mdx @@ -44,12 +44,12 @@ MPP supports multiple payment methods beyond blockchain — including cards (via diff --git a/src/content/docs/agents/agentic-payments/mpp/charge-for-http-content.mdx b/src/content/docs/agents/tools/payments/mpp-charge-for-http-content.mdx similarity index 100% rename from src/content/docs/agents/agentic-payments/mpp/charge-for-http-content.mdx rename to src/content/docs/agents/tools/payments/mpp-charge-for-http-content.mdx diff --git a/src/content/docs/agents/agentic-payments/mpp/index.mdx b/src/content/docs/agents/tools/payments/mpp.mdx similarity index 93% rename from src/content/docs/agents/agentic-payments/mpp/index.mdx rename to src/content/docs/agents/tools/payments/mpp.mdx index dcea8835d662dfa..2a6cfaea27709ca 100644 --- a/src/content/docs/agents/agentic-payments/mpp/index.mdx +++ b/src/content/docs/agents/tools/payments/mpp.mdx @@ -45,7 +45,7 @@ MPP defines two payment intents: ## Compatibility with x402 -MPP is backwards-compatible with [x402](/agents/agentic-payments/x402/). The core x402 `exact` payment flows map directly onto MPP's `charge` intent, so MPP clients can consume existing x402 services without modification. +MPP is backwards-compatible with [x402](/agents/tools/payments/x402/). The core x402 `exact` payment flows map directly onto MPP's `charge` intent, so MPP clients can consume existing x402 services without modification. ## Charge for resources @@ -53,7 +53,7 @@ MPP is backwards-compatible with [x402](/agents/agentic-payments/x402/). The cor diff --git a/src/content/docs/agents/agentic-payments/x402/charge-for-http-content.mdx b/src/content/docs/agents/tools/payments/x402/charge-for-http-content.mdx similarity index 95% rename from src/content/docs/agents/agentic-payments/x402/charge-for-http-content.mdx rename to src/content/docs/agents/tools/payments/x402/charge-for-http-content.mdx index be35f9d12da5148..9f1232522d9a5b7 100644 --- a/src/content/docs/agents/agentic-payments/x402/charge-for-http-content.mdx +++ b/src/content/docs/agents/tools/payments/x402/charge-for-http-content.mdx @@ -105,5 +105,5 @@ Refer to the [x402 Workers example](https://github.com/cloudflare/agents/tree/ma ## Related - [Pay Per Crawl](/ai-crawl-control/features/pay-per-crawl/) — Native Cloudflare monetization without custom code -- [Charge for MCP tools](/agents/agentic-payments/x402/charge-for-mcp-tools/) — Charge per tool call instead of per request +- [Charge for MCP tools](/agents/tools/payments/x402/charge-for-mcp-tools/) — Charge per tool call instead of per request - [x402.org](https://x402.org) — Protocol specification diff --git a/src/content/docs/agents/agentic-payments/x402/charge-for-mcp-tools.mdx b/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx similarity index 89% rename from src/content/docs/agents/agentic-payments/x402/charge-for-mcp-tools.mdx rename to src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx index 06a78134f33c941..16bf8e81804d657 100644 --- a/src/content/docs/agents/agentic-payments/x402/charge-for-mcp-tools.mdx +++ b/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx @@ -88,6 +88,6 @@ For a complete working example, refer to [x402-mcp on GitHub](https://github.com ## Related -- [Pay from Agents SDK](/agents/agentic-payments/x402/pay-from-agents-sdk/) — Build clients that pay for tools -- [Charge for HTTP content](/agents/agentic-payments/x402/charge-for-http-content/) — Gate HTTP endpoints -- [MCP server guide](/agents/guides/remote-mcp-server/) — Build your first MCP server +- [Pay from Agents SDK](/agents/tools/payments/x402/pay-from-agents-sdk/) — Build clients that pay for tools +- [Charge for HTTP content](/agents/tools/payments/x402/charge-for-http-content/) — Gate HTTP endpoints +- [MCP server guide](/agents/mcp/guides/remote-mcp-server/) — Build your first MCP server diff --git a/src/content/docs/agents/agentic-payments/x402/index.mdx b/src/content/docs/agents/tools/payments/x402/index.mdx similarity index 95% rename from src/content/docs/agents/agentic-payments/x402/index.mdx rename to src/content/docs/agents/tools/payments/x402/index.mdx index 0f47d51ed47b651..8a08975d7096b9f 100644 --- a/src/content/docs/agents/agentic-payments/x402/index.mdx +++ b/src/content/docs/agents/tools/payments/x402/index.mdx @@ -56,12 +56,12 @@ Supported networks include Base, Ethereum, Polygon, Optimism, Arbitrum, Avalanch @@ -71,12 +71,12 @@ Supported networks include Base, Ethereum, Polygon, Optimism, Arbitrum, Avalanch diff --git a/src/content/docs/agents/agentic-payments/x402/pay-from-agents-sdk.mdx b/src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx similarity index 82% rename from src/content/docs/agents/agentic-payments/x402/pay-from-agents-sdk.mdx rename to src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx index 92742ef4752838f..354911805f3ae0a 100644 --- a/src/content/docs/agents/agentic-payments/x402/pay-from-agents-sdk.mdx +++ b/src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx @@ -59,6 +59,6 @@ Use `base-sepolia` for testing. Get test USDC from the [Circle faucet](https://f ## Related -- [Charge for MCP tools](/agents/agentic-payments/x402/charge-for-mcp-tools/) — Build servers that charge for tools -- [Pay from coding tools](/agents/agentic-payments/x402/pay-with-tool-plugins/) — Add payments to OpenCode or Claude Code -- [Human-in-the-loop guide](/agents/guides/human-in-the-loop/) — Implement approval workflows +- [Charge for MCP tools](/agents/tools/payments/x402/charge-for-mcp-tools/) — Build servers that charge for tools +- [Pay from coding tools](/agents/tools/payments/x402/pay-with-tool-plugins/) — Add payments to OpenCode or Claude Code +- [Human-in-the-loop guide](/agents/concepts/human-in-the-loop/) — Implement approval workflows diff --git a/src/content/docs/agents/agentic-payments/x402/pay-with-tool-plugins.mdx b/src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx similarity index 93% rename from src/content/docs/agents/agentic-payments/x402/pay-with-tool-plugins.mdx rename to src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx index 355241aa13245d8..9e8a67fac2a9905 100644 --- a/src/content/docs/agents/agentic-payments/x402/pay-with-tool-plugins.mdx +++ b/src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx @@ -156,7 +156,7 @@ Register the hook in `.claude/settings.json`: ## Related -- [Pay from Agents SDK](/agents/agentic-payments/x402/pay-from-agents-sdk/) — Use the Agents SDK for more control -- [Charge for HTTP content](/agents/agentic-payments/x402/charge-for-http-content/) — Build the server side -- [Human-in-the-loop guide](/agents/guides/human-in-the-loop/) — Implement approval workflows +- [Pay from Agents SDK](/agents/tools/payments/x402/pay-from-agents-sdk/) — Use the Agents SDK for more control +- [Charge for HTTP content](/agents/tools/payments/x402/charge-for-http-content/) — Build the server side +- [Human-in-the-loop guide](/agents/concepts/human-in-the-loop/) — Implement approval workflows - [x402.org](https://x402.org) — Protocol specification diff --git a/src/content/docs/agents/api-reference/rag.mdx b/src/content/docs/agents/tools/rag.mdx similarity index 78% rename from src/content/docs/agents/api-reference/rag.mdx rename to src/content/docs/agents/tools/rag.mdx index 85b6510ea09ff33..031c90c0dc4bf77 100644 --- a/src/content/docs/agents/api-reference/rag.mdx +++ b/src/content/docs/agents/tools/rag.mdx @@ -1,8 +1,8 @@ --- -title: Retrieval Augmented Generation +title: RAG pcx_content_type: concept sidebar: - order: 14 + order: 2 --- import { @@ -13,9 +13,9 @@ import { WranglerConfig, } from "~/components"; -Agents can use Retrieval Augmented Generation (RAG) to retrieve relevant information and use it augment [calls to AI models](/agents/api-reference/using-ai-models/). Store a user's chat history to use as context for future conversations, summarize documents to bootstrap an Agent's knowledge base, and/or use data from your Agent's [web browsing](/agents/api-reference/browse-the-web/) tasks to enhance your Agent's capabilities. +Agents can use Retrieval Augmented Generation (RAG) to retrieve relevant information and augment [calls to AI models](/agents/runtime/operations/using-ai-models/). Store a user's chat history to use as context for future conversations, summarize documents to bootstrap an Agent's knowledge base, and/or use data from your Agent's [browser](/agents/tools/browser/) tasks to enhance your Agent's capabilities. -You can use the Agent's own [SQL database](/agents/api-reference/store-and-sync-state) as the source of truth for your data and store embeddings in [Vectorize](/vectorize/) (or any other vector-enabled database) to allow your Agent to retrieve relevant information. +You can use the Agent's own [SQL database](/agents/runtime/lifecycle/state/) as the source of truth for your data and store embeddings in [Vectorize](/vectorize/) (or any other vector-enabled database) to allow your Agent to retrieve relevant information. ### Vector search diff --git a/src/content/docs/agents/tools/sandbox.mdx b/src/content/docs/agents/tools/sandbox.mdx new file mode 100644 index 000000000000000..f7e171e43c205ab --- /dev/null +++ b/src/content/docs/agents/tools/sandbox.mdx @@ -0,0 +1,125 @@ +--- +title: Sandbox +pcx_content_type: concept +sidebar: + order: 3 +description: Give agents isolated Linux environments for running code, managing files, and executing commands. +--- + +import { LinkCard, TypeScriptExample, WranglerConfig } from "~/components"; + +Agents can use [Sandbox](/sandbox/) to run code in isolated container environments. Use Sandbox when an agent needs a real filesystem, shell commands, language runtimes, package installation, or long-lived project state that should not run inside the agent's own Worker isolate. + +Sandbox is built on [Cloudflare Containers](/containers/) and exposes a TypeScript API for command execution, file operations, background processes, and service previews. + +## When to use Sandbox + +Use Sandbox for agents that need to: + +- Run untrusted or model-generated code in isolation. +- Execute Python, Node.js, shell commands, or package managers. +- Read, write, and manage project files. +- Run tests, linters, build tools, or data analysis scripts. +- Maintain a workspace across multiple agent turns. + +For lightweight JavaScript orchestration of MCP tools, use [Codemode](/agents/mcp/protocol/codemode/). Codemode runs generated JavaScript in an isolated Worker sandbox and is optimized for typed tool composition. Sandbox is for full Linux execution environments. + +## Basic pattern + +Bind the Sandbox Durable Object to your Worker, then access a sandbox from your agent methods with `getSandbox()`. + + + +```ts +import { Agent, callable } from "agents"; +import { getSandbox } from "@cloudflare/sandbox"; +import type { Sandbox } from "@cloudflare/sandbox"; + +export { Sandbox } from "@cloudflare/sandbox"; + +type Env = { + Sandbox: DurableObjectNamespace; +}; + +export class CodeAgent extends Agent { + @callable() + async runPython(code: string) { + const sandbox = getSandbox(this.env.Sandbox, this.name); + + await sandbox.writeFile("/workspace/script.py", code); + const result = await sandbox.exec("python3 /workspace/script.py"); + + this.setState({ lastOutput: result.stdout }); + + return { + success: result.success, + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.exitCode, + }; + } +} +``` + + + +## Configuration + +Configure the Sandbox container, Durable Object binding, and migration in `wrangler.jsonc`. + + + +```jsonc +{ + "containers": [ + { + "class_name": "Sandbox", + "image": "./Dockerfile", + "instance_type": "lite", + "max_instances": 1 + } + ], + "durable_objects": { + "bindings": [ + { + "name": "Sandbox", + "class_name": "Sandbox" + } + ] + }, + "migrations": [ + { + "tag": "v1", + "new_sqlite_classes": ["Sandbox"] + } + ] +} +``` + + + +## Sandbox and agent state + +Use agent state for user-visible progress and small metadata. Use the sandbox filesystem for workspace files, generated code, package installs, logs, and artifacts. + +For long-running sandbox work, pair Sandbox with [durable execution with fibers](/agents/runtime/execution/durable-execution/) or [Workflows](/agents/runtime/execution/run-workflows/) so the agent can recover or report progress if work outlives a single request. + +## Related resources + + + + + + diff --git a/src/content/docs/agents/guides/chatgpt-app.mdx b/src/content/docs/workers/demos/chatgpt-app.mdx similarity index 99% rename from src/content/docs/agents/guides/chatgpt-app.mdx rename to src/content/docs/workers/demos/chatgpt-app.mdx index 4a7378b79421556..d2ffa81d2276479 100644 --- a/src/content/docs/agents/guides/chatgpt-app.mdx +++ b/src/content/docs/workers/demos/chatgpt-app.mdx @@ -1,8 +1,8 @@ --- -pcx_content_type: tutorial -title: Build an Interactive ChatGPT App +pcx_content_type: example +title: Build an interactive ChatGPT app sidebar: - order: 6 + order: 1 reviewed: 2025-11-07 --- From e3baf35d99fb2eaa8408e06cd550322b18936598 Mon Sep 17 00:00:00 2001 From: Thomas Gauvin Date: Wed, 27 May 2026 18:08:16 -0400 Subject: [PATCH 2/5] [Agents] Refine overview page --- src/components/AgentsPlatformDiagram.astro | 16 +-- src/content/docs/agents/index.mdx | 135 +++++---------------- 2 files changed, 39 insertions(+), 112 deletions(-) diff --git a/src/components/AgentsPlatformDiagram.astro b/src/components/AgentsPlatformDiagram.astro index 01a174313f40276..d51e8c1dac55f0c 100644 --- a/src/components/AgentsPlatformDiagram.astro +++ b/src/components/AgentsPlatformDiagram.astro @@ -33,9 +33,9 @@ const tools = [ -
+
-

Communication channels

+
Communication channels
{channels.length}
@@ -48,11 +48,11 @@ const tools = [
-
+
-

Agent

+
Agent
@@ -80,9 +80,9 @@ const tools = [
-
+
-

Tools

+
Tools
{tools.length}
@@ -203,7 +203,7 @@ const tools = [ ring: 1px solid var(--map-line); } - .card-header h2, + .card-title, .section-title, .observability-title { margin: 0; @@ -317,7 +317,7 @@ const tools = [ padding: 0 10px; } - .agent-header h2 { + .agent-title { min-width: 0; margin: 0; flex: 1; diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index eb3a12dc136e6fa..db2430e8e557467 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -12,28 +12,24 @@ head: --- import { - CardGrid, AgentsPlatformDiagram, - Description, - Feature, - LinkButton, - LinkTitleCard, - PackageManagers, - Plan, RelatedProduct, - Render, - TabItem, - Tabs, - TypeScriptExample, - WranglerConfig, - LinkCard, } from "~/components"; -Most AI applications today are stateless — they process a request, return a response, and forget everything. Real agents need more. They need to remember conversations, act on schedules, call tools, coordinate with other agents, and stay connected to users in real-time. The Agents SDK gives you all of this as a TypeScript class. +Build and host Agents on Cloudflare, connect chat, voice, email, Slack, and webhooks to a durable agent runtime with Browser, Sandbox, AI Search, MCP, Payments and other MCP tools. + +When you host agents on Cloudflare, each agent has a durable identity, local SQL storage, real-time connections, scheduled work, and recoverable execution. + +Deploy once and Cloudflare runs your agents across its global network, scaling to tens of millions of instances. No infrastructure to manage, no sessions to reconstruct, no state to externalize. -Each agent runs on a [Durable Object](/durable-objects/) — a stateful micro-server with its own SQL database, WebSocket connections, and scheduling. Deploy once and Cloudflare runs your agents across its global network, scaling to tens of millions of instances. No infrastructure to manage, no sessions to reconstruct, no state to externalize. +Agents on Cloudflare are composed from four parts: + +- **Communication channels** define how users and systems reach your agent, such as [chat](/agents/communication-channels/chat/), [voice](/agents/communication-channels/voice/), [email](/agents/communication-channels/email/), [Slack](/agents/communication-channels/slack/), [webhooks](/agents/communication-channels/webhooks/), and other event sources. +- **The agent harness** defines the loop: how the agent calls models, selects tools, handles tool results, streams responses, and decides whether to continue. Use [Project Think](/agents/harnesses/think/) for an opinionated harness, or build your own loop directly on the [Agents SDK runtime](/agents/runtime/agents-api/). +- **The Agents SDK runtime** provides durable infrastructure: the [`Agent` class](/agents/runtime/lifecycle/agent-class/), [state](/agents/runtime/lifecycle/state/), [sessions](/agents/runtime/lifecycle/sessions/), [routing](/agents/runtime/communication/routing/), [WebSockets](/agents/runtime/communication/websockets/), [scheduling](/agents/runtime/execution/schedule-tasks/), [fibers](/agents/runtime/execution/durable-execution/), and [observability](/agents/runtime/operations/observability/). +- **Tools** give the agent capabilities: [browser automation](/agents/tools/browser/), [sandboxed code execution](/agents/tools/sandbox/), retrieval with [AI Search and RAG](/agents/tools/rag/), [MCP tools](/agents/mcp/), and [payments](/agents/tools/payments/). ### Get started @@ -47,121 +43,52 @@ npm run dev The starter includes streaming AI chat, server-side and client-side tools, human-in-the-loop approval, and task scheduling — a foundation you can build on or tear apart. You can also swap in [OpenAI, Anthropic, Google Gemini, or any other provider](/agents/runtime/operations/using-ai-models/). - - - - -### What agents can do +### Example agents -- **Remember everything** — Every agent has a built-in [SQL database](/agents/runtime/lifecycle/state/) and key-value state that syncs to connected clients in real-time. State survives restarts, deploys, and hibernation. -- **Build AI chat** — [`AIChatAgent`](/agents/communication-channels/chat/chat-agents/) gives you streaming AI chat with automatic message persistence, resumable streams, and tool support. Pair it with the [`useAgentChat`](/agents/communication-channels/chat/chat-agents/) React hook to build chat UIs in minutes. -- **Think with any model** — Call [any AI model](/agents/runtime/operations/using-ai-models/) — Workers AI, OpenAI, Anthropic, Gemini — and stream responses over [WebSockets](/agents/runtime/communication/websockets/) or [Server-Sent Events](/agents/runtime/communication/http-sse/). Long-running reasoning models that take minutes to respond work out of the box. -- **Use and serve tools** — Define server-side tools, client-side tools that run in the browser, and [human-in-the-loop](/agents/concepts/human-in-the-loop/) approval flows. Expose your agent's tools to other agents and LLMs via [MCP](/agents/mcp/apis/agent-api/). -- **Act on their own** — [Schedule tasks](/agents/runtime/execution/schedule-tasks/) on a delay, at a specific time, or on a cron. Agents can wake themselves up, do work, and go back to sleep — without a user present. -- **Browse the web** — Give your agents [browser tools](/agents/tools/browser/) powered by the Chrome DevTools Protocol to scrape, screenshot, debug, and interact with web pages. -- **Talk to users** — Build real-time [voice agents](/agents/communication-channels/voice/) with speech-to-text, text-to-speech, and conversation persistence — audio streams over WebSocket. -- **Orchestrate work** — Run multi-step [workflows](/agents/runtime/execution/run-workflows/) with automatic retries, or coordinate across multiple agents. -- **React to events** — Handle [inbound email](/agents/communication-channels/email/), HTTP requests, WebSocket messages, and state changes — all from the same class. + -### How it works +Build a streaming AI chat agent with tools and human-in-the-loop approvals. -An agent is a TypeScript class. Methods marked with `@callable()` become typed RPC that clients can call directly over WebSocket. - - - -```ts -import { Agent, callable } from "agents"; - -export class CounterAgent extends Agent { - initialState = { count: 0 }; - - @callable() - increment() { - this.setState({ count: this.state.count + 1 }); - return this.state.count; - } -} -``` - - + -```tsx -import { useAgent } from "agents/react"; + -function Counter() { - const [count, setCount] = useState(0); - const agent = useAgent({ - agent: "CounterAgent", - onStateUpdate: (state) => setCount(state.count), - }); +Build an agent that responds to Slack messages, mentions, and commands. - return ; -} -``` - -For AI chat, extend `AIChatAgent` instead. Messages are persisted automatically, streams resume on disconnect, and the React hook handles the UI. - - - -```ts -import { AIChatAgent } from "@cloudflare/ai-chat"; -import { createWorkersAI } from "workers-ai-provider"; -import { streamText, convertToModelMessages } from "ai"; - -export class ChatAgent extends AIChatAgent { - async onChatMessage() { - const workersai = createWorkersAI({ binding: this.env.AI }); - const result = streamText({ - model: workersai("@cf/zai-org/glm-4.7-flash"), - messages: await convertToModelMessages(this.messages), - }); - return result.toUIMessageStreamResponse(); - } -} -``` - - + -Refer to the [quick start](/agents/getting-started/quick-start/) for a full walkthrough, the [chat agents guide](/agents/communication-channels/chat/chat-agents/) for the full chat API, or the [Agents API reference](/agents/runtime/agents-api/) for the complete SDK. + ---- +Build a real-time voice agent with speech-to-text and text-to-speech. -### Build on the Cloudflare Platform + - + -Run machine learning models, powered by serverless GPUs, on Cloudflare's global network. No API keys required. +Build an agent that can inspect pages, capture screenshots, and use browser tools. - + -Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale. +Build an agent that sends, receives, routes, and replies to email. - + -Observe and control your AI applications with caching, rate limiting, request retries, model fallback, and more. +Build an agent that can pay for x402-protected tools. - + -Build full-stack AI applications with Vectorize, Cloudflare's vector database for semantic search, recommendations, and providing context to LLMs. +Build a document agent with AI Search and RAG. - + -Build stateful agents that guarantee executions, including automatic retries, persistent state that runs for minutes, hours, days, or weeks. +Build an agent that reviews pull requests using Sandbox and Claude. From 61beb12363a21a38c96b87da66d98cec7d384f27 Mon Sep 17 00:00:00 2001 From: Thomas Gauvin Date: Wed, 27 May 2026 18:11:25 -0400 Subject: [PATCH 3/5] [Agents] Update diagram sandbox label --- src/components/AgentsPlatformDiagram.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AgentsPlatformDiagram.astro b/src/components/AgentsPlatformDiagram.astro index d51e8c1dac55f0c..2178cbc53b06a18 100644 --- a/src/components/AgentsPlatformDiagram.astro +++ b/src/components/AgentsPlatformDiagram.astro @@ -18,7 +18,7 @@ const runtime = [ const tools = [ { type: "Browser", name: "CDP", href: "/agents/tools/browser/" }, - { type: "Sandbox", name: "Linux", href: "/agents/tools/sandbox/" }, + { type: "Sandbox", name: "Bash/Shell", href: "/agents/tools/sandbox/" }, { type: "AI Search", name: "RAG", href: "/agents/tools/rag/" }, { type: "MCP", name: "Servers", href: "/agents/mcp/" }, { type: "Payments", name: "x402 · MPP", href: "/agents/tools/payments/" }, From ad263a0a35d0457c1f16a6c47d52caafb7fb5cc2 Mon Sep 17 00:00:00 2001 From: Thomas Gauvin Date: Wed, 27 May 2026 18:17:24 -0400 Subject: [PATCH 4/5] [Agents] Update tools IA and overview --- public/__redirects | 53 ++++++++++--------- src/components/AgentsPlatformDiagram.astro | 6 +-- .../agents/communication-channels/slack.mdx | 2 +- .../agents/concepts/human-in-the-loop.mdx | 2 +- .../docs/agents/concepts/what-are-agents.mdx | 2 +- .../docs/agents/examples/slack-agent.mdx | 2 +- .../agents/getting-started/quick-start.mdx | 2 +- src/content/docs/agents/index.mdx | 4 +- .../docs/agents/runtime/agents-api.mdx | 2 +- .../communication/protocol-messages.mdx | 2 +- .../agents/runtime/communication/routing.mdx | 2 +- .../agents/runtime/lifecycle/agent-class.mdx | 2 +- src/content/docs/agents/tools/browser.mdx | 2 +- .../agents/{ => tools}/mcp/apis/agent-api.mdx | 16 +++--- .../{ => tools}/mcp/apis/client-api.mdx | 10 ++-- .../{ => tools}/mcp/apis/handler-api.mdx | 20 +++---- .../agents/{ => tools}/mcp/apis/index.mdx | 0 .../{ => tools}/mcp/cloudflare/index.mdx | 0 .../{ => tools}/mcp/cloudflare/mcp-portal.mdx | 0 .../mcp/cloudflare/servers-for-cloudflare.mdx | 2 +- .../mcp/guides/build-mcp-client.mdx | 0 .../mcp/guides/connect-mcp-client.mdx | 4 +- .../agents/{ => tools}/mcp/guides/index.mdx | 0 .../mcp/guides/oauth-mcp-client.mdx | 4 +- .../mcp/guides/remote-mcp-server.mdx | 24 ++++----- .../mcp/guides/securing-mcp-server.mdx | 4 +- .../mcp/guides/test-remote-mcp-server.mdx | 2 +- .../docs/agents/{ => tools}/mcp/index.mdx | 2 +- .../mcp/protocol/authorization.mdx | 6 +-- .../{ => tools}/mcp/protocol/codemode.mdx | 2 +- .../{ => tools}/mcp/protocol/governance.mdx | 4 +- .../agents/{ => tools}/mcp/protocol/index.mdx | 0 .../agents/{ => tools}/mcp/protocol/tools.mdx | 16 +++--- .../{ => tools}/mcp/protocol/transport.mdx | 16 +++--- .../docs/agents/tools/payments/index.mdx | 2 +- .../payments/x402/charge-for-mcp-tools.mdx | 2 +- src/content/docs/agents/tools/rag.mdx | 4 +- src/content/docs/agents/tools/sandbox.mdx | 4 +- 38 files changed, 114 insertions(+), 113 deletions(-) rename src/content/docs/agents/{ => tools}/mcp/apis/agent-api.mdx (95%) rename src/content/docs/agents/{ => tools}/mcp/apis/client-api.mdx (98%) rename src/content/docs/agents/{ => tools}/mcp/apis/handler-api.mdx (91%) rename src/content/docs/agents/{ => tools}/mcp/apis/index.mdx (100%) rename src/content/docs/agents/{ => tools}/mcp/cloudflare/index.mdx (100%) rename src/content/docs/agents/{ => tools}/mcp/cloudflare/mcp-portal.mdx (100%) rename src/content/docs/agents/{ => tools}/mcp/cloudflare/servers-for-cloudflare.mdx (97%) rename src/content/docs/agents/{ => tools}/mcp/guides/build-mcp-client.mdx (100%) rename src/content/docs/agents/{ => tools}/mcp/guides/connect-mcp-client.mdx (98%) rename src/content/docs/agents/{ => tools}/mcp/guides/index.mdx (100%) rename src/content/docs/agents/{ => tools}/mcp/guides/oauth-mcp-client.mdx (99%) rename src/content/docs/agents/{ => tools}/mcp/guides/remote-mcp-server.mdx (89%) rename src/content/docs/agents/{ => tools}/mcp/guides/securing-mcp-server.mdx (98%) rename src/content/docs/agents/{ => tools}/mcp/guides/test-remote-mcp-server.mdx (97%) rename src/content/docs/agents/{ => tools}/mcp/index.mdx (95%) rename src/content/docs/agents/{ => tools}/mcp/protocol/authorization.mdx (96%) rename src/content/docs/agents/{ => tools}/mcp/protocol/codemode.mdx (99%) rename src/content/docs/agents/{ => tools}/mcp/protocol/governance.mdx (64%) rename src/content/docs/agents/{ => tools}/mcp/protocol/index.mdx (100%) rename src/content/docs/agents/{ => tools}/mcp/protocol/tools.mdx (86%) rename src/content/docs/agents/{ => tools}/mcp/protocol/transport.mdx (92%) diff --git a/public/__redirects b/public/__redirects index c3fea4aed54c6cf..dae5e7bc1a62daf 100644 --- a/public/__redirects +++ b/public/__redirects @@ -188,31 +188,32 @@ /agents/examples/using-ai-models/ /agents/runtime/operations/using-ai-models/ 301 /agents/examples/websockets/ /agents/runtime/communication/websockets/ 301 /agents/examples/sdk/ /agents/runtime/agents-api/ 301 -/agents/examples/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 -/agents/api-reference/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/examples/build-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 +/agents/api-reference/build-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 /agents/api-reference/sdk/ /agents/runtime/agents-api/ 301 -/agents/guides/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 -/agents/capabilities/mcp-server/ /agents/mcp/ 301 -/agents/model-context-protocol/mcp-agent-api/ /agents/mcp/apis/agent-api/ 301 -/agents/model-context-protocol/mcp-client-api/ /agents/mcp/apis/client-api/ 301 -/agents/model-context-protocol/mcp-handler-api/ /agents/mcp/apis/handler-api/ 301 +/agents/guides/build-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 +/agents/capabilities/mcp-server/ /agents/tools/mcp/ 301 +/agents/mcp/ /agents/tools/mcp/ 301 +/agents/model-context-protocol/mcp-agent-api/ /agents/tools/mcp/apis/agent-api/ 301 +/agents/model-context-protocol/mcp-client-api/ /agents/tools/mcp/apis/client-api/ 301 +/agents/model-context-protocol/mcp-handler-api/ /agents/tools/mcp/apis/handler-api/ 301 /agents/api-reference/calling-agents/ /agents/runtime/communication/routing/ 301 -/agents/community-mcp-server/ /agents/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 +/agents/community-mcp-server/ /agents/tools/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 /agents/patterns/ /agents/concepts/patterns/ 301 /agents/api-reference/agents-api/ /agents/runtime/agents-api/ 301 /agents/api-reference/browse-the-web/ /agents/tools/browser/ 301 /agents/api-reference/callable-methods/ /agents/runtime/lifecycle/callable-methods/ 301 /agents/api-reference/chat-agents/ /agents/communication-channels/chat/chat-agents/ 301 /agents/api-reference/client-sdk/ /agents/communication-channels/chat/client-sdk/ 301 -/agents/api-reference/codemode/ /agents/mcp/protocol/codemode/ 301 +/agents/api-reference/codemode/ /agents/tools/mcp/protocol/codemode/ 301 /agents/api-reference/configuration/ /agents/runtime/operations/configuration/ 301 /agents/api-reference/durable-execution/ /agents/runtime/execution/durable-execution/ 301 /agents/api-reference/email/ /agents/communication-channels/email/ 301 /agents/api-reference/get-current-agent/ /agents/runtime/lifecycle/get-current-agent/ 301 /agents/api-reference/http-sse/ /agents/runtime/communication/http-sse/ 301 -/agents/api-reference/mcp-agent-api/ /agents/mcp/apis/agent-api/ 301 -/agents/api-reference/mcp-client-api/ /agents/mcp/apis/client-api/ 301 -/agents/api-reference/mcp-handler-api/ /agents/mcp/apis/handler-api/ 301 +/agents/api-reference/mcp-agent-api/ /agents/tools/mcp/apis/agent-api/ 301 +/agents/api-reference/mcp-client-api/ /agents/tools/mcp/apis/client-api/ 301 +/agents/api-reference/mcp-handler-api/ /agents/tools/mcp/apis/handler-api/ 301 /agents/api-reference/observability/ /agents/runtime/operations/observability/ 301 /agents/api-reference/protocol-messages/ /agents/runtime/communication/protocol-messages/ 301 /agents/api-reference/queue-tasks/ /agents/runtime/execution/queue-tasks/ 301 @@ -232,26 +233,26 @@ /agents/guides/anthropic-agent-patterns/ /agents/concepts/anthropic-agent-patterns/ 301 /agents/guides/autonomous-responses/ /agents/communication-channels/chat/autonomous-responses/ 301 /agents/guides/build-a-voice-agent/ /agents/examples/voice-agent/ 301 -/agents/guides/build-mcp-client/ /agents/mcp/guides/build-mcp-client/ 301 +/agents/guides/build-mcp-client/ /agents/tools/mcp/guides/build-mcp-client/ 301 /agents/guides/chatgpt-app/ /workers/demos/chatgpt-app/ 301 /agents/communication-channels/chat/chatgpt-app/ /workers/demos/chatgpt-app/ 301 -/agents/guides/connect-mcp-client/ /agents/mcp/guides/connect-mcp-client/ 301 +/agents/guides/connect-mcp-client/ /agents/tools/mcp/guides/connect-mcp-client/ 301 /agents/guides/cross-domain-authentication/ /agents/runtime/operations/cross-domain-authentication/ 301 /agents/guides/human-in-the-loop/ /agents/concepts/human-in-the-loop/ 301 -/agents/guides/oauth-mcp-client/ /agents/mcp/guides/oauth-mcp-client/ 301 +/agents/guides/oauth-mcp-client/ /agents/tools/mcp/guides/oauth-mcp-client/ 301 /agents/guides/push-notifications/ /agents/communication-channels/webhooks/push-notifications/ 301 -/agents/guides/remote-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 -/agents/guides/securing-mcp-server/ /agents/mcp/guides/securing-mcp-server/ 301 +/agents/guides/remote-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 +/agents/guides/securing-mcp-server/ /agents/tools/mcp/guides/securing-mcp-server/ 301 /agents/guides/slack-agent/ /agents/examples/slack-agent/ 301 -/agents/guides/test-remote-mcp-server/ /agents/mcp/guides/test-remote-mcp-server/ 301 +/agents/guides/test-remote-mcp-server/ /agents/tools/mcp/guides/test-remote-mcp-server/ 301 /agents/guides/webhooks/ /agents/communication-channels/webhooks/webhooks/ 301 -/agents/model-context-protocol/authorization/ /agents/mcp/protocol/authorization/ 301 -/agents/model-context-protocol/governance/ /agents/mcp/protocol/governance/ 301 -/agents/model-context-protocol/mcp-portal/ /agents/mcp/cloudflare/mcp-portal/ 301 -/agents/model-context-protocol/mcp-servers-for-cloudflare/ /agents/mcp/cloudflare/servers-for-cloudflare/ 301 -/agents/model-context-protocol/mcp-servers-for-cloudflare/community-mcp-server/ /agents/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 -/agents/model-context-protocol/tools/ /agents/mcp/protocol/tools/ 301 -/agents/model-context-protocol/transport/ /agents/mcp/protocol/transport/ 301 +/agents/model-context-protocol/authorization/ /agents/tools/mcp/protocol/authorization/ 301 +/agents/model-context-protocol/governance/ /agents/tools/mcp/protocol/governance/ 301 +/agents/model-context-protocol/mcp-portal/ /agents/tools/mcp/cloudflare/mcp-portal/ 301 +/agents/model-context-protocol/mcp-servers-for-cloudflare/ /agents/tools/mcp/cloudflare/servers-for-cloudflare/ 301 +/agents/model-context-protocol/mcp-servers-for-cloudflare/community-mcp-server/ /agents/tools/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 +/agents/model-context-protocol/tools/ /agents/tools/mcp/protocol/tools/ 301 +/agents/model-context-protocol/transport/ /agents/tools/mcp/protocol/transport/ 301 /agents/agentic-payments/ /agents/tools/payments/ 301 /agents/agentic-payments/x402/ /agents/tools/payments/x402/ 301 /agents/agentic-payments/mpp/ /agents/tools/payments/mpp/ 301 @@ -280,7 +281,7 @@ /agents/communication-channels/slack/slack-agent/ /agents/examples/slack-agent/ 301 /agents/tools/browser/browse-the-web/ /agents/tools/browser/ 301 /agents/tools/rag/rag/ /agents/tools/rag/ 301 -/agents/tools/sandbox/codemode/ /agents/mcp/protocol/codemode/ 301 +/agents/tools/sandbox/codemode/ /agents/tools/mcp/protocol/codemode/ 301 /agents/harnesses/ /agents/harnesses/think/ 301 /agents/platform/limits/ /agents/platform/ 301 /agents/tools/payments/mpp/charge-for-http-content/ /agents/tools/payments/mpp-charge-for-http-content/ 301 diff --git a/src/components/AgentsPlatformDiagram.astro b/src/components/AgentsPlatformDiagram.astro index 2178cbc53b06a18..4d63b428abd81b8 100644 --- a/src/components/AgentsPlatformDiagram.astro +++ b/src/components/AgentsPlatformDiagram.astro @@ -17,10 +17,10 @@ const runtime = [ ]; const tools = [ - { type: "Browser", name: "CDP", href: "/agents/tools/browser/" }, { type: "Sandbox", name: "Bash/Shell", href: "/agents/tools/sandbox/" }, - { type: "AI Search", name: "RAG", href: "/agents/tools/rag/" }, - { type: "MCP", name: "Servers", href: "/agents/mcp/" }, + { type: "MCP", name: "Servers", href: "/agents/tools/mcp/" }, + { type: "Browser", name: "CDP", href: "/agents/tools/browser/" }, + { type: "AI Search", name: "Retrieval Augmented Generation", href: "/agents/tools/rag/" }, { type: "Payments", name: "x402 · MPP", href: "/agents/tools/payments/" }, ]; --- diff --git a/src/content/docs/agents/communication-channels/slack.mdx b/src/content/docs/agents/communication-channels/slack.mdx index 9a7dedf538a1ecb..b47c40cd35f1457 100644 --- a/src/content/docs/agents/communication-channels/slack.mdx +++ b/src/content/docs/agents/communication-channels/slack.mdx @@ -453,7 +453,7 @@ export class MyAgent extends SlackAgent { ## Next steps - Add [Slack Interactive Components](https://api.slack.com/interactivity) (buttons, modals) -- Connect your Agent to an [MCP server](/agents/mcp/apis/client-api/) +- Connect your Agent to an [MCP server](/agents/tools/mcp/apis/client-api/) - Add rate limiting to prevent abuse - Implement conversation state management - Use [Workers Analytics Engine](/analytics/analytics-engine/) to track usage diff --git a/src/content/docs/agents/concepts/human-in-the-loop.mdx b/src/content/docs/agents/concepts/human-in-the-loop.mdx index cedc6ea06b0942b..26507e8983cb8a3 100644 --- a/src/content/docs/agents/concepts/human-in-the-loop.mdx +++ b/src/content/docs/agents/concepts/human-in-the-loop.mdx @@ -537,7 +537,7 @@ class MultiApprovalAgent extends Agent { diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index 02cb7619b015ec1..724a86bc0fe8b0e 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -62,7 +62,7 @@ An agent can dynamically generate an itinerary and execute on booking reservatio Agent systems typically have three primary components: - **Decision Engine**: Usually an LLM (Large Language Model) that determines action steps -- **Tool Integration**: APIs, functions, and services the agent can utilize — often via [MCP](/agents/mcp/) +- **Tool Integration**: APIs, functions, and services the agent can utilize — often via [MCP](/agents/tools/mcp/) - **Memory System**: Maintains context and tracks task progress ### How agents work diff --git a/src/content/docs/agents/examples/slack-agent.mdx b/src/content/docs/agents/examples/slack-agent.mdx index bbb2cf900becc68..d3cd5cb0fd27daf 100644 --- a/src/content/docs/agents/examples/slack-agent.mdx +++ b/src/content/docs/agents/examples/slack-agent.mdx @@ -453,7 +453,7 @@ export class MyAgent extends SlackAgent { ## Next steps - Add [Slack Interactive Components](https://api.slack.com/interactivity) (buttons, modals) -- Connect your Agent to an [MCP server](/agents/mcp/apis/client-api/) +- Connect your Agent to an [MCP server](/agents/tools/mcp/apis/client-api/) - Add rate limiting to prevent abuse - Implement conversation state management - Use [Workers Analytics Engine](/analytics/analytics-engine/) to track usage diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index 4bea0cc212cbad1..5f5ab27d5487c12 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -332,7 +332,7 @@ Now that you have a working agent, explore these topics: | Learn how to | Refer to | | ------------------------ | --------------------------------------------------------- | | Add AI/LLM capabilities | [Using AI models](/agents/runtime/operations/using-ai-models/) | -| Expose tools via MCP | [MCP servers](/agents/mcp/apis/agent-api/) | +| Expose tools via MCP | [MCP servers](/agents/tools/mcp/apis/agent-api/) | | Run background tasks | [Schedule tasks](/agents/runtime/execution/schedule-tasks/) | | Handle emails | [Email routing](/agents/communication-channels/email/) | | Use Cloudflare Workflows | [Run Workflows](/agents/runtime/execution/run-workflows/) | diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index db2430e8e557467..f25634b99a2e830 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -29,7 +29,7 @@ Agents on Cloudflare are composed from four parts: - **Communication channels** define how users and systems reach your agent, such as [chat](/agents/communication-channels/chat/), [voice](/agents/communication-channels/voice/), [email](/agents/communication-channels/email/), [Slack](/agents/communication-channels/slack/), [webhooks](/agents/communication-channels/webhooks/), and other event sources. - **The agent harness** defines the loop: how the agent calls models, selects tools, handles tool results, streams responses, and decides whether to continue. Use [Project Think](/agents/harnesses/think/) for an opinionated harness, or build your own loop directly on the [Agents SDK runtime](/agents/runtime/agents-api/). - **The Agents SDK runtime** provides durable infrastructure: the [`Agent` class](/agents/runtime/lifecycle/agent-class/), [state](/agents/runtime/lifecycle/state/), [sessions](/agents/runtime/lifecycle/sessions/), [routing](/agents/runtime/communication/routing/), [WebSockets](/agents/runtime/communication/websockets/), [scheduling](/agents/runtime/execution/schedule-tasks/), [fibers](/agents/runtime/execution/durable-execution/), and [observability](/agents/runtime/operations/observability/). -- **Tools** give the agent capabilities: [browser automation](/agents/tools/browser/), [sandboxed code execution](/agents/tools/sandbox/), retrieval with [AI Search and RAG](/agents/tools/rag/), [MCP tools](/agents/mcp/), and [payments](/agents/tools/payments/). +- **Tools** give the agent capabilities: [browser automation](/agents/tools/browser/), [sandboxed code execution](/agents/tools/sandbox/), retrieval with [AI Search and Retrieval Augmented Generation](/agents/tools/rag/), [MCP tools](/agents/tools/mcp/), and [payments](/agents/tools/payments/). ### Get started @@ -83,7 +83,7 @@ Build an agent that can pay for x402-protected tools. -Build a document agent with AI Search and RAG. +Build a document agent with AI Search and Retrieval Augmented Generation. diff --git a/src/content/docs/agents/runtime/agents-api.mdx b/src/content/docs/agents/runtime/agents-api.mdx index 1bede17c08075c8..086949344250fc4 100644 --- a/src/content/docs/agents/runtime/agents-api.mdx +++ b/src/content/docs/agents/runtime/agents-api.mdx @@ -86,7 +86,7 @@ flowchart TD | **HTTP/SSE** | `onRequest()` | [HTTP and SSE](/agents/runtime/communication/http-sse/) | | **Email** | `onEmail()`, `replyToEmail()` | [Email routing](/agents/communication-channels/email/) | | **Workflows** | `runWorkflow()`, `waitForApproval()` | [Run Workflows](/agents/runtime/execution/run-workflows/) | -| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/mcp/apis/client-api/) | +| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/tools/mcp/apis/client-api/) | | **AI Models** | Workers AI, OpenAI, Anthropic bindings | [Using AI models](/agents/runtime/operations/using-ai-models/) | | **Protocol messages** | `shouldSendProtocolMessages()`, `isConnectionProtocolEnabled()` | [Protocol messages](/agents/runtime/communication/protocol-messages/) | | **Context** | `getCurrentAgent()` | [getCurrentAgent()](/agents/runtime/lifecycle/get-current-agent/) | diff --git a/src/content/docs/agents/runtime/communication/protocol-messages.mdx b/src/content/docs/agents/runtime/communication/protocol-messages.mdx index db8fe71593607ae..ed6c643b0ba1de0 100644 --- a/src/content/docs/agents/runtime/communication/protocol-messages.mdx +++ b/src/content/docs/agents/runtime/communication/protocol-messages.mdx @@ -199,4 +199,4 @@ Unlike [readonly](/agents/runtime/communication/readonly-connections/) which can - [Readonly connections](/agents/runtime/communication/readonly-connections/) - [WebSockets](/agents/runtime/communication/websockets/) - [Store and sync state](/agents/runtime/lifecycle/state/) -- [MCP Client API](/agents/mcp/apis/client-api/) +- [MCP Client API](/agents/tools/mcp/apis/client-api/) diff --git a/src/content/docs/agents/runtime/communication/routing.mdx b/src/content/docs/agents/runtime/communication/routing.mdx index 446b42f95af9886..fa5b7dd2f409ba8 100644 --- a/src/content/docs/agents/runtime/communication/routing.mdx +++ b/src/content/docs/agents/runtime/communication/routing.mdx @@ -469,7 +469,7 @@ export default { For agent-specific initialization, use `getAgentByName` instead where you control exactly which agent receives the props. :::note -For `McpAgent`, props are automatically stored and accessible via `this.props`. Refer to [MCP servers](/agents/mcp/apis/agent-api/) for details. +For `McpAgent`, props are automatically stored and accessible via `this.props`. Refer to [MCP servers](/agents/tools/mcp/apis/agent-api/) for details. ::: ### Hooks diff --git a/src/content/docs/agents/runtime/lifecycle/agent-class.mdx b/src/content/docs/agents/runtime/lifecycle/agent-class.mdx index fd5f96c7d1f593e..9dc1b8bc0c31cad 100644 --- a/src/content/docs/agents/runtime/lifecycle/agent-class.mdx +++ b/src/content/docs/agents/runtime/lifecycle/agent-class.mdx @@ -325,7 +325,7 @@ Schedules are stored in the `cf_agents_schedules` SQL table. Cron schedules auto ### `this.mcp` and friends -`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is properly documented in [MCP client API](/agents/mcp/apis/client-api/). +`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is properly documented in [MCP client API](/agents/tools/mcp/apis/client-api/). ```ts class MyAgent extends Agent { diff --git a/src/content/docs/agents/tools/browser.mdx b/src/content/docs/agents/tools/browser.mdx index a55420a05a5ec11..59011f234f3e2aa 100644 --- a/src/content/docs/agents/tools/browser.mdx +++ b/src/content/docs/agents/tools/browser.mdx @@ -2,7 +2,7 @@ title: Browser pcx_content_type: reference sidebar: - order: 1 + order: 3 --- import { diff --git a/src/content/docs/agents/mcp/apis/agent-api.mdx b/src/content/docs/agents/tools/mcp/apis/agent-api.mdx similarity index 95% rename from src/content/docs/agents/mcp/apis/agent-api.mdx rename to src/content/docs/agents/tools/mcp/apis/agent-api.mdx index 9a4a5aefb78d3a0..009beaf18846dd3 100644 --- a/src/content/docs/agents/mcp/apis/agent-api.mdx +++ b/src/content/docs/agents/tools/mcp/apis/agent-api.mdx @@ -37,7 +37,7 @@ export class MyMCP extends McpAgent { This means that each instance of your MCP server has its own durable state, backed by a [Durable Object](/durable-objects/), with its own [SQL database](/agents/runtime/lifecycle/state/). -Your MCP server doesn't necessarily have to be an Agent. You can build MCP servers that are stateless, and just add [tools](/agents/mcp/tools) to your MCP server using the `@modelcontextprotocol/sdk` package. +Your MCP server doesn't necessarily have to be an Agent. You can build MCP servers that are stateless, and just add [tools](/agents/tools/mcp/tools) to your MCP server using the `@modelcontextprotocol/sdk` package. But if you want your MCP server to: @@ -155,7 +155,7 @@ Hibernation is enabled by default and requires no additional configuration. ## Authentication and authorization -The McpAgent class provides seamless integration with the [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) for [authentication and authorization](/agents/mcp/protocol/authorization/). +The McpAgent class provides seamless integration with the [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) for [authentication and authorization](/agents/tools/mcp/protocol/authorization/). When a user authenticates to your MCP server, their identity information and tokens are made available through the `props` parameter, allowing you to: @@ -175,7 +175,7 @@ The `McpAgent` class provides full access to the [Agent state APIs](/agents/runt - [`sql`](/agents/runtime/agents-api/#sql-api) — Execute SQL queries on embedded database :::note[State resets after the session ends] -Currently, each client session is backed by an instance of the `McpAgent` class. This is handled automatically for you, as shown in the [getting started guide](/agents/mcp/guides/remote-mcp-server/). This means that when the same client reconnects, they will start a new session, and the state will be reset. +Currently, each client session is backed by an instance of the `McpAgent` class. This is handled automatically for you, as shown in the [getting started guide](/agents/tools/mcp/guides/remote-mcp-server/). This means that when the same client reconnects, they will start a new session, and the state will be reset. ::: For example, the following code implements an MCP server that remembers a counter value, and updates the counter when the `add` tool is called: @@ -403,30 +403,30 @@ For more human-in-the-loop patterns including workflow-based approval, refer to diff --git a/src/content/docs/agents/mcp/apis/client-api.mdx b/src/content/docs/agents/tools/mcp/apis/client-api.mdx similarity index 98% rename from src/content/docs/agents/mcp/apis/client-api.mdx rename to src/content/docs/agents/tools/mcp/apis/client-api.mdx index 6dce035d4360bc3..d60c246592c7b13 100644 --- a/src/content/docs/agents/mcp/apis/client-api.mdx +++ b/src/content/docs/agents/tools/mcp/apis/client-api.mdx @@ -9,7 +9,7 @@ sidebar: import { Render, TypeScriptExample, LinkCard } from "~/components"; -Connect your agent to external [Model Context Protocol (MCP)](/agents/mcp/) servers to use their tools, resources, and prompts. This enables your agent to interact with GitHub, Slack, databases, and other services through a standardized protocol. +Connect your agent to external [Model Context Protocol (MCP)](/agents/tools/mcp/) servers to use their tools, resources, and prompts. This enables your agent to interact with GitHub, Slack, databases, and other services through a standardized protocol. ## Overview @@ -22,7 +22,7 @@ The MCP client capability lets your agent: :::note -This page covers connecting to MCP servers as a client. To create your own MCP server, refer to [Creating MCP servers](/agents/mcp/apis/agent-api/). +This page covers connecting to MCP servers as a client. To create your own MCP server, refer to [Creating MCP servers](/agents/tools/mcp/apis/agent-api/). ::: @@ -133,7 +133,7 @@ MCP server URLs are validated before connection to prevent Server-Side Request F Loopback addresses (`localhost`, `127.x.x.x`, `[::1]`) are **allowed** for local development. -For production connections to internal services, use the [RPC transport](/agents/mcp/protocol/transport/) with a Durable Object binding instead of HTTP. +For production connections to internal services, use the [RPC transport](/agents/tools/mcp/protocol/transport/) with a Durable Object binding instead of HTTP. ### Return value @@ -525,7 +525,7 @@ async addMcpServer( - `client` — MCP client configuration options - `retry` — Retry options for the connection -RPC transport connects your Agent directly to an `McpAgent` via Durable Object bindings without HTTP overhead. Refer to [MCP Transport](/agents/mcp/protocol/transport/) for details on configuring RPC transport. +RPC transport connects your Agent directly to an `McpAgent` via Durable Object bindings without HTTP overhead. Refer to [MCP Transport](/agents/tools/mcp/protocol/transport/) for details on configuring RPC transport. #### Returns @@ -941,7 +941,7 @@ export class MyAgent extends Agent { diff --git a/src/content/docs/agents/mcp/apis/handler-api.mdx b/src/content/docs/agents/tools/mcp/apis/handler-api.mdx similarity index 91% rename from src/content/docs/agents/mcp/apis/handler-api.mdx rename to src/content/docs/agents/tools/mcp/apis/handler-api.mdx index 6e741f5a7c89a27..2c0d75f124b1820 100644 --- a/src/content/docs/agents/mcp/apis/handler-api.mdx +++ b/src/content/docs/agents/tools/mcp/apis/handler-api.mdx @@ -9,7 +9,7 @@ sidebar: import { TypeScriptExample, LinkCard } from "~/components"; -The `createMcpHandler` function creates a fetch handler to serve your [MCP server](/agents/mcp/). Use it when you want a stateless MCP server that runs in a plain Worker (no Durable Object). For stateful MCP servers that persist state across requests, use the [`McpAgent`](/agents/mcp/apis/agent-api/) class instead. +The `createMcpHandler` function creates a fetch handler to serve your [MCP server](/agents/tools/mcp/). Use it when you want a stateless MCP server that runs in a plain Worker (no Durable Object). For stateful MCP servers that persist state across requests, use the [`McpAgent`](/agents/tools/mcp/apis/agent-api/) class instead. It uses an implementation of the MCP Transport interface, `WorkerTransport`, built on top of web standards, which conforms to the [streamable-http](https://modelcontextprotocol.io/specification/draft/basic/transports/#streamable-http) transport specification. @@ -86,9 +86,9 @@ const handler = createMcpHandler(server, { #### authContext -An authentication context object that will be available to MCP tools via [`getMcpAuthContext()`](/agents/mcp/apis/handler-api/#authentication-context). +An authentication context object that will be available to MCP tools via [`getMcpAuthContext()`](/agents/tools/mcp/apis/handler-api/#authentication-context). -When using the [`OAuthProvider`](/agents/mcp/protocol/authorization/) from `@cloudflare/workers-oauth-provider`, the authentication context is automatically populated with information from the OAuth flow. You typically don't need to set this manually. +When using the [`OAuthProvider`](/agents/tools/mcp/protocol/authorization/) from `@cloudflare/workers-oauth-provider`, the authentication context is automatically populated with information from the OAuth flow. You typically don't need to set this manually. #### transport @@ -124,7 +124,7 @@ MCP SDK 1.26.0 introduces a guard that prevents connecting to a server instance **If your stateless MCP server declares `McpServer` or transport instances in the global scope, you must create new instances per request.** -See the [migration guide](/agents/mcp/apis/handler-api/#migration-guide-for-mcp-sdk-1260) below for details. +See the [migration guide](/agents/tools/mcp/apis/handler-api/#migration-guide-for-mcp-sdk-1260) below for details. ::: @@ -543,7 +543,7 @@ const transport = new WorkerTransport({ ## Authentication Context -When using [OAuth authentication](/agents/mcp/protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available. +When using [OAuth authentication](/agents/tools/mcp/protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available. ```ts interface McpAuthContext { @@ -592,7 +592,7 @@ function createServer() { :::note -For a complete guide on setting up OAuth authentication with MCP servers, see the [MCP Authorization documentation](/agents/mcp/protocol/authorization/). View the [complete authenticated MCP server in a Worker example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). +For a complete guide on setting up OAuth authentication with MCP servers, see the [MCP Authorization documentation](/agents/tools/mcp/protocol/authorization/). View the [complete authenticated MCP server in a Worker example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). ::: ## Error Handling @@ -628,24 +628,24 @@ server.tool("riskyOperation", "An operation that might fail", {}, async () => { diff --git a/src/content/docs/agents/mcp/apis/index.mdx b/src/content/docs/agents/tools/mcp/apis/index.mdx similarity index 100% rename from src/content/docs/agents/mcp/apis/index.mdx rename to src/content/docs/agents/tools/mcp/apis/index.mdx diff --git a/src/content/docs/agents/mcp/cloudflare/index.mdx b/src/content/docs/agents/tools/mcp/cloudflare/index.mdx similarity index 100% rename from src/content/docs/agents/mcp/cloudflare/index.mdx rename to src/content/docs/agents/tools/mcp/cloudflare/index.mdx diff --git a/src/content/docs/agents/mcp/cloudflare/mcp-portal.mdx b/src/content/docs/agents/tools/mcp/cloudflare/mcp-portal.mdx similarity index 100% rename from src/content/docs/agents/mcp/cloudflare/mcp-portal.mdx rename to src/content/docs/agents/tools/mcp/cloudflare/mcp-portal.mdx diff --git a/src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx b/src/content/docs/agents/tools/mcp/cloudflare/servers-for-cloudflare.mdx similarity index 97% rename from src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx rename to src/content/docs/agents/tools/mcp/cloudflare/servers-for-cloudflare.mdx index ca46db66dfddc82..122abf0e3a94ea5 100644 --- a/src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx +++ b/src/content/docs/agents/tools/mcp/cloudflare/servers-for-cloudflare.mdx @@ -15,7 +15,7 @@ These MCP servers allow your MCP client to read configurations from your account The [Cloudflare API MCP server](https://github.com/cloudflare/mcp) provides access to the entire [Cloudflare API](/api/) — over 2,500 endpoints across DNS, Workers, R2, Zero Trust, and every other product — through just two tools: `search()` and `execute()`. -It uses [Codemode](/agents/mcp/protocol/codemode/), a technique where the model writes JavaScript against a typed representation of the OpenAPI spec and the Cloudflare API client, rather than loading individual tool definitions for each endpoint. The generated code runs inside an isolated [Dynamic Worker](/workers/runtime-apis/bindings/worker-loader/) sandbox. +It uses [Codemode](/agents/tools/mcp/protocol/codemode/), a technique where the model writes JavaScript against a typed representation of the OpenAPI spec and the Cloudflare API client, rather than loading individual tool definitions for each endpoint. The generated code runs inside an isolated [Dynamic Worker](/workers/runtime-apis/bindings/worker-loader/) sandbox. This approach uses approximately 1,000 tokens regardless of how many API endpoints exist. An equivalent MCP server that exposed every endpoint as a native tool would consume over 1 million tokens — more than the entire context window of most foundation models. diff --git a/src/content/docs/agents/mcp/guides/build-mcp-client.mdx b/src/content/docs/agents/tools/mcp/guides/build-mcp-client.mdx similarity index 100% rename from src/content/docs/agents/mcp/guides/build-mcp-client.mdx rename to src/content/docs/agents/tools/mcp/guides/build-mcp-client.mdx diff --git a/src/content/docs/agents/mcp/guides/connect-mcp-client.mdx b/src/content/docs/agents/tools/mcp/guides/connect-mcp-client.mdx similarity index 98% rename from src/content/docs/agents/mcp/guides/connect-mcp-client.mdx rename to src/content/docs/agents/tools/mcp/guides/connect-mcp-client.mdx index 8dba22517eecf18..bfdd897629dbe09 100644 --- a/src/content/docs/agents/mcp/guides/connect-mcp-client.mdx +++ b/src/content/docs/agents/tools/mcp/guides/connect-mcp-client.mdx @@ -232,12 +232,12 @@ Connections persist in the Agent's [SQL storage](/agents/runtime/lifecycle/state diff --git a/src/content/docs/agents/mcp/guides/index.mdx b/src/content/docs/agents/tools/mcp/guides/index.mdx similarity index 100% rename from src/content/docs/agents/mcp/guides/index.mdx rename to src/content/docs/agents/tools/mcp/guides/index.mdx diff --git a/src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx b/src/content/docs/agents/tools/mcp/guides/oauth-mcp-client.mdx similarity index 99% rename from src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx rename to src/content/docs/agents/tools/mcp/guides/oauth-mcp-client.mdx index 0124bb3663f30bb..c0bcc2fdffeb9bb 100644 --- a/src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx +++ b/src/content/docs/agents/tools/mcp/guides/oauth-mcp-client.mdx @@ -379,12 +379,12 @@ export default { diff --git a/src/content/docs/agents/mcp/guides/remote-mcp-server.mdx b/src/content/docs/agents/tools/mcp/guides/remote-mcp-server.mdx similarity index 89% rename from src/content/docs/agents/mcp/guides/remote-mcp-server.mdx rename to src/content/docs/agents/tools/mcp/guides/remote-mcp-server.mdx index f197e4c0d07e451..96e80e1161cf7b8 100644 --- a/src/content/docs/agents/mcp/guides/remote-mcp-server.mdx +++ b/src/content/docs/agents/tools/mcp/guides/remote-mcp-server.mdx @@ -9,10 +9,10 @@ sidebar: import { Details, Render, PackageManagers, LinkCard } from "~/components"; -This guide will show you how to deploy your own remote MCP server on Cloudflare using [Streamable HTTP transport](/agents/mcp/protocol/transport/), the current MCP specification standard. You have two options: +This guide will show you how to deploy your own remote MCP server on Cloudflare using [Streamable HTTP transport](/agents/tools/mcp/protocol/transport/), the current MCP specification standard. You have two options: - **Without authentication** — anyone can connect and use the server (no login required). -- **With [authentication and authorization](/agents/mcp/guides/remote-mcp-server/#add-authentication)** — users sign in before accessing tools, and you can control which tools an agent can call based on the user's permissions. +- **With [authentication and authorization](/agents/tools/mcp/guides/remote-mcp-server/#add-authentication)** — users sign in before accessing tools, and you can control which tools an agent can call based on the user's permissions. ## Choosing an approach @@ -20,8 +20,8 @@ The Agents SDK provides multiple ways to create MCP servers. Choose the approach | Approach | Stateful? | Requires Durable Objects? | Best for | | -------------------------------------------------------------- | --------- | ------------------------- | ---------------------------------------------- | -| [`createMcpHandler()`](/agents/mcp/apis/handler-api/) | No | No | Stateless tools, simplest setup | -| [`McpAgent`](/agents/mcp/apis/agent-api/) | Yes | Yes | Stateful tools, per-session state, elicitation | +| [`createMcpHandler()`](/agents/tools/mcp/apis/handler-api/) | No | No | Stateless tools, simplest setup | +| [`McpAgent`](/agents/tools/mcp/apis/agent-api/) | Yes | Yes | Stateful tools, per-session state, elicitation | | Raw `WebStandardStreamableHTTPServerTransport` | No | No | Full control, no SDK dependency | - **`createMcpHandler()`** is the fastest way to get a stateless MCP server running. Use it when your tools do not need per-session state. @@ -30,7 +30,7 @@ The Agents SDK provides multiple ways to create MCP servers. Choose the approach ## Deploy your first MCP server -You can start by deploying a [public MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) without authentication, then add user authentication and scoped authorization later. If you already know your server will require authentication, you can skip ahead to the [next section](/agents/mcp/guides/remote-mcp-server/#add-authentication). +You can start by deploying a [public MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) without authentication, then add user authentication and scoped authorization later. If you already know your server will require authentication, you can skip ahead to the [next section](/agents/tools/mcp/guides/remote-mcp-server/#add-authentication). ### Via the dashboard @@ -38,9 +38,9 @@ The button below will guide you through everything you need to do to deploy an [ [![Deploy to Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) -Once deployed, this server will be live at your `workers.dev` subdomain (for example, `remote-mcp-server-authless.your-account.workers.dev/mcp`). You can connect to it immediately using the [AI Playground](https://playground.ai.cloudflare.com/) (a remote MCP client), [MCP inspector](https://github.com/modelcontextprotocol/inspector) or [other MCP clients](/agents/mcp/guides/remote-mcp-server/#connect-from-an-mcp-client-via-a-local-proxy). +Once deployed, this server will be live at your `workers.dev` subdomain (for example, `remote-mcp-server-authless.your-account.workers.dev/mcp`). You can connect to it immediately using the [AI Playground](https://playground.ai.cloudflare.com/) (a remote MCP client), [MCP inspector](https://github.com/modelcontextprotocol/inspector) or [other MCP clients](/agents/tools/mcp/guides/remote-mcp-server/#connect-from-an-mcp-client-via-a-local-proxy). -A new git repository will be set up on your GitHub or GitLab account for your MCP server, configured to automatically deploy to Cloudflare each time you push a change or merge a pull request to the main branch of the repository. You can clone this repository, [develop locally](/agents/mcp/guides/remote-mcp-server/#via-the-cli), and start customizing the MCP server with your own [tools](/agents/mcp/protocol/tools/). +A new git repository will be set up on your GitHub or GitLab account for your MCP server, configured to automatically deploy to Cloudflare each time you push a change or merge a pull request to the main branch of the repository. You can clone this repository, [develop locally](/agents/tools/mcp/guides/remote-mcp-server/#via-the-cli), and start customizing the MCP server with your own [tools](/agents/tools/mcp/protocol/tools/). ### Via the CLI @@ -147,7 +147,7 @@ For example, to connect from Claude Desktop: Claude should invoke the tool and show the result generated by the remote MCP server. -To learn how to use remote MCP servers with other MCP clients, refer to [Test a Remote MCP Server](/agents/mcp/guides/test-remote-mcp-server/). +To learn how to use remote MCP servers with other MCP clients, refer to [Test a Remote MCP Server](/agents/tools/mcp/guides/test-remote-mcp-server/). ## Add Authentication @@ -161,7 +161,7 @@ For a step-by-step deployment guide, refer to [Secure MCP servers with Access fo ### Third-party OAuth -You can connect your MCP server with any [OAuth provider](/agents/mcp/protocol/authorization/#2-third-party-oauth-provider) that supports the OAuth 2.0 specification, including GitHub, Google, Slack, [Stytch](/agents/mcp/protocol/authorization/#stytch), [Auth0](/agents/mcp/protocol/authorization/#auth0), [WorkOS](/agents/mcp/protocol/authorization/#workos), and more. +You can connect your MCP server with any [OAuth provider](/agents/tools/mcp/protocol/authorization/#2-third-party-oauth-provider) that supports the OAuth 2.0 specification, including GitHub, Google, Slack, [Stytch](/agents/tools/mcp/protocol/authorization/#stytch), [Auth0](/agents/tools/mcp/protocol/authorization/#auth0), [WorkOS](/agents/tools/mcp/protocol/authorization/#workos), and more. The following example demonstrates how to use GitHub as an OAuth provider. @@ -303,18 +303,18 @@ npx wrangler secret put GITHUB_CLIENT_SECRET npm run deploy ``` -5. Connect to your server running at `worker-name.account-name.workers.dev/mcp` using the [AI Playground](https://playground.ai.cloudflare.com/), MCP Inspector, or [other MCP clients](/agents/mcp/guides/test-remote-mcp-server/), and authenticate with GitHub. +5. Connect to your server running at `worker-name.account-name.workers.dev/mcp` using the [AI Playground](https://playground.ai.cloudflare.com/), MCP Inspector, or [other MCP clients](/agents/tools/mcp/guides/test-remote-mcp-server/), and authenticate with GitHub. ## Next steps diff --git a/src/content/docs/agents/mcp/guides/securing-mcp-server.mdx b/src/content/docs/agents/tools/mcp/guides/securing-mcp-server.mdx similarity index 98% rename from src/content/docs/agents/mcp/guides/securing-mcp-server.mdx rename to src/content/docs/agents/tools/mcp/guides/securing-mcp-server.mdx index ba61fad159ec66d..1cd6eec78dac66a 100644 --- a/src/content/docs/agents/mcp/guides/securing-mcp-server.mdx +++ b/src/content/docs/agents/tools/mcp/guides/securing-mcp-server.mdx @@ -273,13 +273,13 @@ When reading the cookie, verify the HMAC signature before trusting the data. If diff --git a/src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx b/src/content/docs/agents/tools/mcp/guides/test-remote-mcp-server.mdx similarity index 97% rename from src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx rename to src/content/docs/agents/tools/mcp/guides/test-remote-mcp-server.mdx index d1ec14276747eee..b3f346a8d0dabed 100644 --- a/src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx +++ b/src/content/docs/agents/tools/mcp/guides/test-remote-mcp-server.mdx @@ -11,7 +11,7 @@ import { Render } from "~/components"; Remote, authorized connections are an evolving part of the [Model Context Protocol (MCP) specification](https://spec.modelcontextprotocol.io/specification/draft/basic/authorization/). Not all MCP clients support remote connections yet. -This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/mcp/guides/remote-mcp-server/) guide first. +This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/tools/mcp/guides/remote-mcp-server/) guide first. ## The Model Context Protocol (MCP) inspector diff --git a/src/content/docs/agents/mcp/index.mdx b/src/content/docs/agents/tools/mcp/index.mdx similarity index 95% rename from src/content/docs/agents/mcp/index.mdx rename to src/content/docs/agents/tools/mcp/index.mdx index 46dd480332415b9..47e031ea396c120 100644 --- a/src/content/docs/agents/mcp/index.mdx +++ b/src/content/docs/agents/tools/mcp/index.mdx @@ -2,7 +2,7 @@ title: MCP pcx_content_type: navigation sidebar: - order: 7 + order: 2 group: hideIndex: true --- diff --git a/src/content/docs/agents/mcp/protocol/authorization.mdx b/src/content/docs/agents/tools/mcp/protocol/authorization.mdx similarity index 96% rename from src/content/docs/agents/mcp/protocol/authorization.mdx rename to src/content/docs/agents/tools/mcp/protocol/authorization.mdx index a788a1d93265050..5a152ef8a21aa1f 100644 --- a/src/content/docs/agents/mcp/protocol/authorization.mdx +++ b/src/content/docs/agents/tools/mcp/protocol/authorization.mdx @@ -34,7 +34,7 @@ To deploy an [example MCP server](https://github.com/cloudflare/ai/tree/main/dem ### (2) Third-party OAuth Provider -The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/mcp/guides/remote-mcp-server/#add-authentication). +The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/tools/mcp/guides/remote-mcp-server/#add-authentication). When you use a third-party OAuth provider, you must provide a handler to the `OAuthProvider` that implements the OAuth flow for the third-party provider. @@ -145,7 +145,7 @@ export default new OAuthProvider({ }); ``` -Refer to the [getting started example](/agents/mcp/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. +Refer to the [getting started example](/agents/tools/mcp/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. The authorization flow in this case works like this: @@ -169,7 +169,7 @@ sequenceDiagram Note over C,M: Begin standard MCP message exchange ``` -Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/mcp/guides/remote-mcp-server/) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. +Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/tools/mcp/guides/remote-mcp-server/) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. ## Using authentication context in tools diff --git a/src/content/docs/agents/mcp/protocol/codemode.mdx b/src/content/docs/agents/tools/mcp/protocol/codemode.mdx similarity index 99% rename from src/content/docs/agents/mcp/protocol/codemode.mdx rename to src/content/docs/agents/tools/mcp/protocol/codemode.mdx index 57dc879541d1641..27975a187cfd8a3 100644 --- a/src/content/docs/agents/mcp/protocol/codemode.mdx +++ b/src/content/docs/agents/tools/mcp/protocol/codemode.mdx @@ -407,6 +407,6 @@ sanitizeToolName("delete"); // "delete_" diff --git a/src/content/docs/agents/mcp/protocol/governance.mdx b/src/content/docs/agents/tools/mcp/protocol/governance.mdx similarity index 64% rename from src/content/docs/agents/mcp/protocol/governance.mdx rename to src/content/docs/agents/tools/mcp/protocol/governance.mdx index 8be81477a79c1c0..9adaa74cbb9721d 100644 --- a/src/content/docs/agents/mcp/protocol/governance.mdx +++ b/src/content/docs/agents/tools/mcp/protocol/governance.mdx @@ -25,6 +25,6 @@ Cloudflare Access logs MCP server requests and tool executions made through the ## Remote MCP servers -To maintain a modern security posture, Cloudflare recommends the use of [remote MCP servers](/agents/mcp/guides/remote-mcp-server/) over local installations. Running MCP servers locally introduces risks similar to unmanaged [shadow IT](https://www.cloudflare.com/learning/access-management/what-is-shadow-it/), making it difficult to audit data flow or verify the integrity of the server code. Remote MCP servers give administrators visibility into what servers are being used, along with the ability to control who access them and what tools are authorized for employee use. +To maintain a modern security posture, Cloudflare recommends the use of [remote MCP servers](/agents/tools/mcp/guides/remote-mcp-server/) over local installations. Running MCP servers locally introduces risks similar to unmanaged [shadow IT](https://www.cloudflare.com/learning/access-management/what-is-shadow-it/), making it difficult to audit data flow or verify the integrity of the server code. Remote MCP servers give administrators visibility into what servers are being used, along with the ability to control who access them and what tools are authorized for employee use. -You can [build your remote MCP servers](/agents/mcp/guides/remote-mcp-server/) directly on Cloudflare Workers. When both your [MCP server portal](#mcp-server-portals) and remote MCP servers run on Cloudflare's network, requests stay on the same infrastructure, minimizing latency and maximizing performance. +You can [build your remote MCP servers](/agents/tools/mcp/guides/remote-mcp-server/) directly on Cloudflare Workers. When both your [MCP server portal](#mcp-server-portals) and remote MCP servers run on Cloudflare's network, requests stay on the same infrastructure, minimizing latency and maximizing performance. diff --git a/src/content/docs/agents/mcp/protocol/index.mdx b/src/content/docs/agents/tools/mcp/protocol/index.mdx similarity index 100% rename from src/content/docs/agents/mcp/protocol/index.mdx rename to src/content/docs/agents/tools/mcp/protocol/index.mdx diff --git a/src/content/docs/agents/mcp/protocol/tools.mdx b/src/content/docs/agents/tools/mcp/protocol/tools.mdx similarity index 86% rename from src/content/docs/agents/mcp/protocol/tools.mdx rename to src/content/docs/agents/tools/mcp/protocol/tools.mdx index 8b1136d1f68cbc4..6af5071b7291e7a 100644 --- a/src/content/docs/agents/mcp/protocol/tools.mdx +++ b/src/content/docs/agents/tools/mcp/protocol/tools.mdx @@ -9,9 +9,9 @@ sidebar: import { TypeScriptExample, LinkCard } from "~/components"; -MCP tools are functions that an [MCP server](/agents/mcp/) exposes for clients to call. When an LLM decides it needs to take an action — look up data, run a calculation, call an API — it invokes a tool. The MCP server executes the tool and returns the result. +MCP tools are functions that an [MCP server](/agents/tools/mcp/) exposes for clients to call. When an LLM decides it needs to take an action — look up data, run a calculation, call an API — it invokes a tool. The MCP server executes the tool and returns the result. -Tools are defined using the `@modelcontextprotocol/sdk` package. The Agents SDK handles transport and lifecycle; the tool definitions are the same regardless of whether you use [`createMcpHandler`](/agents/mcp/apis/handler-api/) or [`McpAgent`](/agents/mcp/apis/agent-api/). +Tools are defined using the `@modelcontextprotocol/sdk` package. The Agents SDK handles transport and lifecycle; the tool definitions are the same regardless of whether you use [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/) or [`McpAgent`](/agents/tools/mcp/apis/agent-api/). ## Defining tools @@ -119,7 +119,7 @@ server.tool( ## Using tools with `createMcpHandler` -For stateless MCP servers, define tools inside a factory function and pass the server to [`createMcpHandler`](/agents/mcp/apis/handler-api/): +For stateless MCP servers, define tools inside a factory function and pass the server to [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/): @@ -150,7 +150,7 @@ export default { ## Using tools with `McpAgent` -For stateful MCP servers, define tools in the `init()` method of an [`McpAgent`](/agents/mcp/apis/agent-api/). Tools have access to the agent instance via `this`, which means they can read and write state. +For stateful MCP servers, define tools in the `init()` method of an [`McpAgent`](/agents/tools/mcp/apis/agent-api/). Tools have access to the agent instance via `this`, which means they can read and write state. @@ -185,24 +185,24 @@ export class MyMCP extends McpAgent { diff --git a/src/content/docs/agents/mcp/protocol/transport.mdx b/src/content/docs/agents/tools/mcp/protocol/transport.mdx similarity index 92% rename from src/content/docs/agents/mcp/protocol/transport.mdx rename to src/content/docs/agents/tools/mcp/protocol/transport.mdx index 4dd6efa16d14ac3..76be90e6242d568 100644 --- a/src/content/docs/agents/mcp/protocol/transport.mdx +++ b/src/content/docs/agents/tools/mcp/protocol/transport.mdx @@ -15,14 +15,14 @@ The Model Context Protocol (MCP) specification defines two standard [transport m 2. **Streamable HTTP** — The standard transport method for remote MCP connections, [introduced](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) in March 2025. It uses a single HTTP endpoint for bidirectional messaging. :::note -Server-Sent Events (SSE) was previously used for remote MCP connections but has been deprecated in favor of Streamable HTTP. If you need SSE support for legacy clients, use the [`McpAgent`](/agents/mcp/apis/agent-api/) class. +Server-Sent Events (SSE) was previously used for remote MCP connections but has been deprecated in favor of Streamable HTTP. If you need SSE support for legacy clients, use the [`McpAgent`](/agents/tools/mcp/apis/agent-api/) class. ::: -MCP servers built with the [Agents SDK](/agents) use [`createMcpHandler`](/agents/mcp/apis/handler-api/) to handle Streamable HTTP transport. +MCP servers built with the [Agents SDK](/agents) use [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/) to handle Streamable HTTP transport. ## Implementing remote MCP transport -Use [`createMcpHandler`](/agents/mcp/apis/handler-api/) to create an MCP server that handles Streamable HTTP transport. This is the recommended approach for new MCP servers. +Use [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/) to create an MCP server that handles Streamable HTTP transport. This is the recommended approach for new MCP servers. #### Get started quickly @@ -100,7 +100,7 @@ export default new OAuthProvider({ If your MCP server needs to maintain state across requests, use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. This allows you to persist session state in Durable Object storage and use advanced MCP features like [elicitation](https://modelcontextprotocol.io/specification/draft/client/elicitation) and [sampling](https://modelcontextprotocol.io/specification/draft/client/sampling). -See [Stateful MCP Servers](/agents/mcp/apis/handler-api/#stateful-mcp-servers) for implementation details. +See [Stateful MCP Servers](/agents/tools/mcp/apis/handler-api/#stateful-mcp-servers) for implementation details. ## RPC transport @@ -187,7 +187,7 @@ export class Chat extends AIChatAgent { RPC connections are automatically restored after Durable Object hibernation, just like HTTP connections. The binding name and props are persisted to storage so the connection can be re-established without any extra code. -For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (refer to [MCP Client API](/agents/mcp/apis/client-api/) for details). This makes it safe to call in `onStart()`. +For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (refer to [MCP Client API](/agents/tools/mcp/apis/client-api/) for details). This makes it safe to call in `onStart()`. #### 3. Configure Durable Object bindings @@ -326,11 +326,11 @@ export class MyMCP extends McpAgent { If you have an existing MCP server using the `McpAgent` class: - **Not using state?** Replace your `McpAgent` class with `McpServer` from `@modelcontextprotocol/sdk` and use `createMcpHandler(server)` in a Worker `fetch` handler. -- **Using state?** Use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. See [Stateful MCP Servers](/agents/mcp/apis/handler-api/#stateful-mcp-servers) for details. -- **Need SSE support?** Continue using `McpAgent` with `serveSSE()` for legacy client compatibility. See the [McpAgent API reference](/agents/mcp/apis/agent-api/). +- **Using state?** Use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. See [Stateful MCP Servers](/agents/tools/mcp/apis/handler-api/#stateful-mcp-servers) for details. +- **Need SSE support?** Continue using `McpAgent` with `serveSSE()` for legacy client compatibility. See the [McpAgent API reference](/agents/tools/mcp/apis/agent-api/). ### Testing with MCP clients You can test your MCP server using an MCP client that supports remote connections, or use [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), an adapter that lets MCP clients that only support local connections work with remote MCP servers. -Follow [this guide](/agents/mcp/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server to Claude Desktop, Cursor, Windsurf, and other MCP clients. +Follow [this guide](/agents/tools/mcp/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server to Claude Desktop, Cursor, Windsurf, and other MCP clients. diff --git a/src/content/docs/agents/tools/payments/index.mdx b/src/content/docs/agents/tools/payments/index.mdx index 2bf8aa391c41a73..cd19ec7cc4ad761 100644 --- a/src/content/docs/agents/tools/payments/index.mdx +++ b/src/content/docs/agents/tools/payments/index.mdx @@ -2,7 +2,7 @@ title: Agentic Payments pcx_content_type: overview sidebar: - order: 8 + order: 5 group: hideIndex: false description: Let AI agents pay for services programmatically using payment protocols like MPP and x402 with Cloudflare's Agents SDK. diff --git a/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx b/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx index 16bf8e81804d657..f10431f03b9683c 100644 --- a/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx +++ b/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx @@ -90,4 +90,4 @@ For a complete working example, refer to [x402-mcp on GitHub](https://github.com - [Pay from Agents SDK](/agents/tools/payments/x402/pay-from-agents-sdk/) — Build clients that pay for tools - [Charge for HTTP content](/agents/tools/payments/x402/charge-for-http-content/) — Gate HTTP endpoints -- [MCP server guide](/agents/mcp/guides/remote-mcp-server/) — Build your first MCP server +- [MCP server guide](/agents/tools/mcp/guides/remote-mcp-server/) — Build your first MCP server diff --git a/src/content/docs/agents/tools/rag.mdx b/src/content/docs/agents/tools/rag.mdx index 031c90c0dc4bf77..e300d86271ff953 100644 --- a/src/content/docs/agents/tools/rag.mdx +++ b/src/content/docs/agents/tools/rag.mdx @@ -1,8 +1,8 @@ --- -title: RAG +title: Retrieval Augmented Generation pcx_content_type: concept sidebar: - order: 2 + order: 4 --- import { diff --git a/src/content/docs/agents/tools/sandbox.mdx b/src/content/docs/agents/tools/sandbox.mdx index f7e171e43c205ab..1d48ea847367509 100644 --- a/src/content/docs/agents/tools/sandbox.mdx +++ b/src/content/docs/agents/tools/sandbox.mdx @@ -2,7 +2,7 @@ title: Sandbox pcx_content_type: concept sidebar: - order: 3 + order: 1 description: Give agents isolated Linux environments for running code, managing files, and executing commands. --- @@ -22,7 +22,7 @@ Use Sandbox for agents that need to: - Run tests, linters, build tools, or data analysis scripts. - Maintain a workspace across multiple agent turns. -For lightweight JavaScript orchestration of MCP tools, use [Codemode](/agents/mcp/protocol/codemode/). Codemode runs generated JavaScript in an isolated Worker sandbox and is optimized for typed tool composition. Sandbox is for full Linux execution environments. +For lightweight JavaScript orchestration of MCP tools, use [Codemode](/agents/tools/mcp/protocol/codemode/). Codemode runs generated JavaScript in an isolated Worker sandbox and is optimized for typed tool composition. Sandbox is for full Linux execution environments. ## Basic pattern From fcdf44063369b15acde3b55f175192c034aa1a0f Mon Sep 17 00:00:00 2001 From: Thomas Gauvin Date: Wed, 27 May 2026 19:02:21 -0400 Subject: [PATCH 5/5] [Agents] Rename memory concept and refine MCP/RAG labels - Rename concept page title to Conversation state and memory (order 4) - Rename MCP top-level title to Model Context Protocol (MCP) - Update RAG title and diagram label to Retrieval Augmented Generation (RAG) - Add redirect for /agents/concepts/memory/ --- public/__redirects | 63 +++--- src/components/AgentsPlatformDiagram.astro | 4 +- .../chat/chat-agents.mdx | 8 +- .../agents/communication-channels/slack.mdx | 2 +- .../docs/agents/community-mcp-server.mdx | 111 ---------- .../human-in-the-loop.mdx | 4 +- .../index.mdx} | 8 +- .../long-running-agents.mdx | 10 +- .../concepts/anthropic-agent-patterns.mdx | 11 - ....mdx => conversation-state-and-memory.mdx} | 4 +- src/content/docs/agents/concepts/tools.mdx | 2 +- .../docs/agents/concepts/what-are-agents.mdx | 2 +- .../docs/agents/concepts/workflows.mdx | 204 ------------------ .../docs/agents/examples/chat-agent.mdx | 2 +- .../docs/agents/examples/payment-agent.mdx | 2 +- .../docs/agents/examples/slack-agent.mdx | 2 +- .../agents/getting-started/quick-start.mdx | 2 +- src/content/docs/agents/harnesses/index.mdx | 33 ++- src/content/docs/agents/harnesses/think.mdx | 2 +- src/content/docs/agents/index.mdx | 2 +- .../agents/{tools => }/mcp/apis/agent-api.mdx | 18 +- .../{tools => }/mcp/apis/client-api.mdx | 10 +- .../{tools => }/mcp/apis/handler-api.mdx | 20 +- .../agents/{tools => }/mcp/apis/index.mdx | 0 .../{tools => }/mcp/cloudflare/index.mdx | 0 .../{tools => }/mcp/cloudflare/mcp-portal.mdx | 0 .../mcp/cloudflare/servers-for-cloudflare.mdx | 2 +- .../mcp/guides/build-mcp-client.mdx | 0 .../mcp/guides/connect-mcp-client.mdx | 4 +- .../agents/{tools => }/mcp/guides/index.mdx | 0 .../mcp/guides/oauth-mcp-client.mdx | 4 +- .../mcp/guides/remote-mcp-server.mdx | 24 +-- .../mcp/guides/securing-mcp-server.mdx | 4 +- .../mcp/guides/test-remote-mcp-server.mdx | 2 +- .../docs/agents/{tools => }/mcp/index.mdx | 6 +- .../mcp/protocol/authorization.mdx | 6 +- .../{tools => }/mcp/protocol/codemode.mdx | 2 +- .../{tools => }/mcp/protocol/governance.mdx | 4 +- .../agents/{tools => }/mcp/protocol/index.mdx | 0 .../agents/{tools => }/mcp/protocol/tools.mdx | 16 +- .../{tools => }/mcp/protocol/transport.mdx | 16 +- .../docs/agents/runtime/agents-api.mdx | 2 +- .../communication/protocol-messages.mdx | 2 +- .../agents/runtime/communication/routing.mdx | 2 +- .../runtime/execution/durable-execution.mdx | 10 +- .../runtime/execution/run-workflows.mdx | 19 +- .../agents/runtime/execution/sub-agents.mdx | 2 +- .../agents/runtime/lifecycle/agent-class.mdx | 2 +- .../payments/x402/charge-for-mcp-tools.mdx | 2 +- .../payments/x402/pay-from-agents-sdk.mdx | 2 +- .../payments/x402/pay-with-tool-plugins.mdx | 2 +- src/content/docs/agents/tools/rag.mdx | 2 +- src/content/docs/agents/tools/sandbox.mdx | 2 +- 53 files changed, 191 insertions(+), 474 deletions(-) delete mode 100644 src/content/docs/agents/community-mcp-server.mdx rename src/content/docs/agents/concepts/{ => agentic-patterns}/human-in-the-loop.mdx (99%) rename src/content/docs/agents/concepts/{patterns.mdx => agentic-patterns/index.mdx} (91%) rename src/content/docs/agents/concepts/{ => agentic-patterns}/long-running-agents.mdx (98%) delete mode 100644 src/content/docs/agents/concepts/anthropic-agent-patterns.mdx rename src/content/docs/agents/concepts/{memory.mdx => conversation-state-and-memory.mdx} (99%) delete mode 100644 src/content/docs/agents/concepts/workflows.mdx rename src/content/docs/agents/{tools => }/mcp/apis/agent-api.mdx (94%) rename src/content/docs/agents/{tools => }/mcp/apis/client-api.mdx (98%) rename src/content/docs/agents/{tools => }/mcp/apis/handler-api.mdx (92%) rename src/content/docs/agents/{tools => }/mcp/apis/index.mdx (100%) rename src/content/docs/agents/{tools => }/mcp/cloudflare/index.mdx (100%) rename src/content/docs/agents/{tools => }/mcp/cloudflare/mcp-portal.mdx (100%) rename src/content/docs/agents/{tools => }/mcp/cloudflare/servers-for-cloudflare.mdx (97%) rename src/content/docs/agents/{tools => }/mcp/guides/build-mcp-client.mdx (100%) rename src/content/docs/agents/{tools => }/mcp/guides/connect-mcp-client.mdx (98%) rename src/content/docs/agents/{tools => }/mcp/guides/index.mdx (100%) rename src/content/docs/agents/{tools => }/mcp/guides/oauth-mcp-client.mdx (99%) rename src/content/docs/agents/{tools => }/mcp/guides/remote-mcp-server.mdx (89%) rename src/content/docs/agents/{tools => }/mcp/guides/securing-mcp-server.mdx (98%) rename src/content/docs/agents/{tools => }/mcp/guides/test-remote-mcp-server.mdx (97%) rename src/content/docs/agents/{tools => }/mcp/index.mdx (51%) rename src/content/docs/agents/{tools => }/mcp/protocol/authorization.mdx (96%) rename src/content/docs/agents/{tools => }/mcp/protocol/codemode.mdx (99%) rename src/content/docs/agents/{tools => }/mcp/protocol/governance.mdx (66%) rename src/content/docs/agents/{tools => }/mcp/protocol/index.mdx (100%) rename src/content/docs/agents/{tools => }/mcp/protocol/tools.mdx (87%) rename src/content/docs/agents/{tools => }/mcp/protocol/transport.mdx (92%) diff --git a/public/__redirects b/public/__redirects index 2d476ddebd7512c..238ed1a012c111a 100644 --- a/public/__redirects +++ b/public/__redirects @@ -208,32 +208,35 @@ /agents/examples/using-ai-models/ /agents/runtime/operations/using-ai-models/ 301 /agents/examples/websockets/ /agents/runtime/communication/websockets/ 301 /agents/examples/sdk/ /agents/runtime/agents-api/ 301 -/agents/examples/build-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 -/agents/api-reference/build-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 +/agents/examples/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/api-reference/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 /agents/api-reference/sdk/ /agents/runtime/agents-api/ 301 -/agents/guides/build-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 -/agents/capabilities/mcp-server/ /agents/tools/mcp/ 301 -/agents/mcp/ /agents/tools/mcp/ 301 -/agents/model-context-protocol/mcp-agent-api/ /agents/tools/mcp/apis/agent-api/ 301 -/agents/model-context-protocol/mcp-client-api/ /agents/tools/mcp/apis/client-api/ 301 -/agents/model-context-protocol/mcp-handler-api/ /agents/tools/mcp/apis/handler-api/ 301 +/agents/guides/build-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/capabilities/mcp-server/ /agents/mcp/ 301 +/agents/model-context-protocol/mcp-agent-api/ /agents/mcp/apis/agent-api/ 301 +/agents/model-context-protocol/mcp-client-api/ /agents/mcp/apis/client-api/ 301 +/agents/model-context-protocol/mcp-handler-api/ /agents/mcp/apis/handler-api/ 301 /agents/api-reference/calling-agents/ /agents/runtime/communication/routing/ 301 -/agents/community-mcp-server/ /agents/tools/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 -/agents/patterns/ /agents/concepts/patterns/ 301 +/agents/community-mcp-server/ /agents/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 +/agents/patterns/ /agents/concepts/agentic-patterns/ 301 +/agents/concepts/patterns/ /agents/concepts/agentic-patterns/ 301 +/agents/concepts/anthropic-agent-patterns/ /agents/concepts/agentic-patterns/ 301 +/agents/concepts/human-in-the-loop/ /agents/concepts/agentic-patterns/human-in-the-loop/ 301 +/agents/concepts/long-running-agents/ /agents/concepts/agentic-patterns/long-running-agents/ 301 /agents/api-reference/agents-api/ /agents/runtime/agents-api/ 301 /agents/api-reference/browse-the-web/ /agents/tools/browser/ 301 /agents/api-reference/callable-methods/ /agents/runtime/lifecycle/callable-methods/ 301 /agents/api-reference/chat-agents/ /agents/communication-channels/chat/chat-agents/ 301 /agents/api-reference/client-sdk/ /agents/communication-channels/chat/client-sdk/ 301 -/agents/api-reference/codemode/ /agents/tools/mcp/protocol/codemode/ 301 +/agents/api-reference/codemode/ /agents/mcp/protocol/codemode/ 301 /agents/api-reference/configuration/ /agents/runtime/operations/configuration/ 301 /agents/api-reference/durable-execution/ /agents/runtime/execution/durable-execution/ 301 /agents/api-reference/email/ /agents/communication-channels/email/ 301 /agents/api-reference/get-current-agent/ /agents/runtime/lifecycle/get-current-agent/ 301 /agents/api-reference/http-sse/ /agents/runtime/communication/http-sse/ 301 -/agents/api-reference/mcp-agent-api/ /agents/tools/mcp/apis/agent-api/ 301 -/agents/api-reference/mcp-client-api/ /agents/tools/mcp/apis/client-api/ 301 -/agents/api-reference/mcp-handler-api/ /agents/tools/mcp/apis/handler-api/ 301 +/agents/api-reference/mcp-agent-api/ /agents/mcp/apis/agent-api/ 301 +/agents/api-reference/mcp-client-api/ /agents/mcp/apis/client-api/ 301 +/agents/api-reference/mcp-handler-api/ /agents/mcp/apis/handler-api/ 301 /agents/api-reference/observability/ /agents/runtime/operations/observability/ 301 /agents/api-reference/protocol-messages/ /agents/runtime/communication/protocol-messages/ 301 /agents/api-reference/queue-tasks/ /agents/runtime/execution/queue-tasks/ 301 @@ -253,30 +256,32 @@ /agents/guides/anthropic-agent-patterns/ /agents/concepts/anthropic-agent-patterns/ 301 /agents/guides/autonomous-responses/ /agents/communication-channels/chat/autonomous-responses/ 301 /agents/guides/build-a-voice-agent/ /agents/examples/voice-agent/ 301 -/agents/guides/build-mcp-client/ /agents/tools/mcp/guides/build-mcp-client/ 301 +/agents/guides/build-mcp-client/ /agents/mcp/guides/build-mcp-client/ 301 /agents/guides/chatgpt-app/ /workers/demos/chatgpt-app/ 301 /agents/communication-channels/chat/chatgpt-app/ /workers/demos/chatgpt-app/ 301 -/agents/guides/connect-mcp-client/ /agents/tools/mcp/guides/connect-mcp-client/ 301 +/agents/guides/connect-mcp-client/ /agents/mcp/guides/connect-mcp-client/ 301 /agents/guides/cross-domain-authentication/ /agents/runtime/operations/cross-domain-authentication/ 301 -/agents/guides/human-in-the-loop/ /agents/concepts/human-in-the-loop/ 301 -/agents/guides/oauth-mcp-client/ /agents/tools/mcp/guides/oauth-mcp-client/ 301 +/agents/guides/human-in-the-loop/ /agents/concepts/agentic-patterns/human-in-the-loop/ 301 +/agents/guides/oauth-mcp-client/ /agents/mcp/guides/oauth-mcp-client/ 301 /agents/guides/push-notifications/ /agents/communication-channels/webhooks/push-notifications/ 301 -/agents/guides/remote-mcp-server/ /agents/tools/mcp/guides/remote-mcp-server/ 301 -/agents/guides/securing-mcp-server/ /agents/tools/mcp/guides/securing-mcp-server/ 301 +/agents/guides/remote-mcp-server/ /agents/mcp/guides/remote-mcp-server/ 301 +/agents/guides/securing-mcp-server/ /agents/mcp/guides/securing-mcp-server/ 301 /agents/guides/slack-agent/ /agents/examples/slack-agent/ 301 -/agents/guides/test-remote-mcp-server/ /agents/tools/mcp/guides/test-remote-mcp-server/ 301 +/agents/guides/test-remote-mcp-server/ /agents/mcp/guides/test-remote-mcp-server/ 301 /agents/guides/webhooks/ /agents/communication-channels/webhooks/webhooks/ 301 -/agents/model-context-protocol/authorization/ /agents/tools/mcp/protocol/authorization/ 301 -/agents/model-context-protocol/governance/ /agents/tools/mcp/protocol/governance/ 301 -/agents/model-context-protocol/mcp-portal/ /agents/tools/mcp/cloudflare/mcp-portal/ 301 -/agents/model-context-protocol/mcp-servers-for-cloudflare/ /agents/tools/mcp/cloudflare/servers-for-cloudflare/ 301 -/agents/model-context-protocol/mcp-servers-for-cloudflare/community-mcp-server/ /agents/tools/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 -/agents/model-context-protocol/tools/ /agents/tools/mcp/protocol/tools/ 301 -/agents/model-context-protocol/transport/ /agents/tools/mcp/protocol/transport/ 301 +/agents/model-context-protocol/authorization/ /agents/mcp/protocol/authorization/ 301 +/agents/model-context-protocol/governance/ /agents/mcp/protocol/governance/ 301 +/agents/model-context-protocol/mcp-portal/ /agents/mcp/cloudflare/mcp-portal/ 301 +/agents/model-context-protocol/mcp-servers-for-cloudflare/ /agents/mcp/cloudflare/servers-for-cloudflare/ 301 +/agents/model-context-protocol/mcp-servers-for-cloudflare/community-mcp-server/ /agents/mcp/cloudflare/servers-for-cloudflare/#cloudflare-community-mcp-server 301 +/agents/model-context-protocol/tools/ /agents/mcp/protocol/tools/ 301 +/agents/model-context-protocol/transport/ /agents/mcp/protocol/transport/ 301 /agents/agentic-payments/ /agents/tools/payments/ 301 /agents/agentic-payments/x402/ /agents/tools/payments/x402/ 301 /agents/agentic-payments/mpp/ /agents/tools/payments/mpp/ 301 /agents/concepts/agent-class/ /agents/runtime/lifecycle/agent-class/ 301 +/agents/concepts/workflows/ /agents/runtime/execution/run-workflows/ 301 +/agents/concepts/memory/ /agents/concepts/conversation-state-and-memory/ 301 /agents/getting-started/prompting/ /workers/get-started/prompting/ 301 /agents/platform/prompting/ /workers/get-started/prompting/ 301 /agents/platform/prompt.txt/ /workers/prompt.txt 301 @@ -301,7 +306,7 @@ /agents/communication-channels/slack/slack-agent/ /agents/examples/slack-agent/ 301 /agents/tools/browser/browse-the-web/ /agents/tools/browser/ 301 /agents/tools/rag/rag/ /agents/tools/rag/ 301 -/agents/tools/sandbox/codemode/ /agents/tools/mcp/protocol/codemode/ 301 +/agents/tools/sandbox/codemode/ /agents/mcp/protocol/codemode/ 301 /agents/harnesses/ /agents/harnesses/think/ 301 /agents/platform/limits/ /agents/platform/ 301 /agents/tools/payments/mpp/charge-for-http-content/ /agents/tools/payments/mpp-charge-for-http-content/ 301 diff --git a/src/components/AgentsPlatformDiagram.astro b/src/components/AgentsPlatformDiagram.astro index 4d63b428abd81b8..cf0bc8127ad4667 100644 --- a/src/components/AgentsPlatformDiagram.astro +++ b/src/components/AgentsPlatformDiagram.astro @@ -18,9 +18,9 @@ const runtime = [ const tools = [ { type: "Sandbox", name: "Bash/Shell", href: "/agents/tools/sandbox/" }, - { type: "MCP", name: "Servers", href: "/agents/tools/mcp/" }, + { type: "MCP", name: "Servers", href: "/agents/mcp/" }, { type: "Browser", name: "CDP", href: "/agents/tools/browser/" }, - { type: "AI Search", name: "Retrieval Augmented Generation", href: "/agents/tools/rag/" }, + { type: "AI Search", name: "Retrieval Augmented Generation (RAG)", href: "/agents/tools/rag/" }, { type: "Payments", name: "x402 · MPP", href: "/agents/tools/payments/" }, ]; --- diff --git a/src/content/docs/agents/communication-channels/chat/chat-agents.mdx b/src/content/docs/agents/communication-channels/chat/chat-agents.mdx index 7fe99267a8827cc..9abc5f647e702bd 100644 --- a/src/content/docs/agents/communication-channels/chat/chat-agents.mdx +++ b/src/content/docs/agents/communication-channels/chat/chat-agents.mdx @@ -652,7 +652,7 @@ The right strategy depends on whether the provider supports assistant prefill an | OpenAI (Responses API) | Retrieve completed response by ID — zero wasted tokens | Zero | | Anthropic | Persist partial, send a synthetic user message to continue | Medium | -For how chat recovery fits into the broader long-running agents story, refer to [Long-running agents: Recovering interrupted LLM streams](/agents/concepts/long-running-agents/#recovering-interrupted-llm-streams). For the underlying fiber API, refer to [Durable Execution](/agents/runtime/execution/durable-execution/). +For how chat recovery fits into the broader long-running agents story, refer to [Long-running agents: Recovering interrupted LLM streams](/agents/concepts/agentic-patterns/long-running-agents/#recovering-interrupted-llm-streams). For the underlying fiber API, refer to [Durable Execution](/agents/runtime/execution/durable-execution/). ## Client API @@ -891,7 +891,7 @@ This sends a `tool_result` to the LLM with your custom error text, so it can res `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. -For more patterns, refer to [Human-in-the-loop](/agents/concepts/human-in-the-loop/). +For more patterns, refer to [Human-in-the-loop](/agents/concepts/agentic-patterns/human-in-the-loop/). ## Custom request data @@ -1536,7 +1536,7 @@ If you are upgrading from an earlier version, replace deprecated calls with thei @@ -1554,6 +1554,6 @@ If you are upgrading from an earlier version, replace deprecated calls with thei diff --git a/src/content/docs/agents/communication-channels/slack.mdx b/src/content/docs/agents/communication-channels/slack.mdx index b47c40cd35f1457..9a7dedf538a1ecb 100644 --- a/src/content/docs/agents/communication-channels/slack.mdx +++ b/src/content/docs/agents/communication-channels/slack.mdx @@ -453,7 +453,7 @@ export class MyAgent extends SlackAgent { ## Next steps - Add [Slack Interactive Components](https://api.slack.com/interactivity) (buttons, modals) -- Connect your Agent to an [MCP server](/agents/tools/mcp/apis/client-api/) +- Connect your Agent to an [MCP server](/agents/mcp/apis/client-api/) - Add rate limiting to prevent abuse - Implement conversation state management - Use [Workers Analytics Engine](/analytics/analytics-engine/) to track usage diff --git a/src/content/docs/agents/community-mcp-server.mdx b/src/content/docs/agents/community-mcp-server.mdx deleted file mode 100644 index 2b9d1eff6d54ccd..000000000000000 --- a/src/content/docs/agents/community-mcp-server.mdx +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: Cloudflare Community MCP Server -pcx_content_type: tutorial -difficulty: Beginner -products: - - agents -description: Learn how to use the Cloudflare Community MCP server to search topics, read posts, and filter content. -sidebar: - order: 10 ---- - -The MCP server for the [Cloudflare Community forum](https://community.cloudflare.com) lets AI agents search topics, read posts, look up users, and filter content. - -The server is powered by [`@discourse/mcp`](https://www.npmjs.com/package/@discourse/mcp), the official Discourse MCP server. - -## Install - -```bash -npx @discourse/mcp@latest -``` - -## Configure - -### OpenCode - -Add to `~/.config/opencode/opencode.jsonc` inside the `"mcp"` block: - -```json -"discourse": { - "type": "local", - "command": ["npx", "-y", "@discourse/mcp@latest"], - "enabled": true -} -``` - -### Claude Desktop - -Add to `claude_desktop_config.json`: - -```json -{ - "mcpServers": { - "discourse": { - "command": "npx", - "args": ["-y", "@discourse/mcp@latest"] - } - } -} -``` - -### Cursor - -Add to `.cursor/mcp.json` in your project root: - -```json -{ - "mcpServers": { - "discourse": { - "command": "npx", - "args": ["-y", "@discourse/mcp@latest"] - } - } -} -``` - -## Connect to the Cloudflare Community - -After configuring your client, use the `discourse_select_site` tool with: - -```txt -https://community.cloudflare.com -``` - -No API key is needed for reading public data. An API key is only required for write operations (posting, moderation). - -## Available tools - -| Tool | Description | -|------|-------------| -| `discourse_select_site` | Connect to community.cloudflare.com | -| `discourse_search` | Full-text search across topics and posts | -| `discourse_filter_topics` | Filter by category, tags, status, dates | -| `discourse_read_topic` | Read a topic's posts and metadata | -| `discourse_read_post` | Read a specific post | -| `discourse_get_user` | Look up a user's profile | -| `discourse_list_user_posts` | List posts by a user | - -## Example usage - -Once connected, you can ask your AI assistant things like: - -- "Search the Cloudflare community for topics about Error 522" -- "Find unanswered topics in the SSL category from the last 3 days" -- "Read topic 42325 and summarize the issue" -- "Show me recent replies from user sandro" - -## Machine-readable discovery - -AI agents can automatically discover the MCP server through these endpoints on community.cloudflare.com: - -- [`/.well-known/mcp.json`](https://community.cloudflare.com/.well-known/mcp.json) — MCP Server Card -- [`/llms.txt`](https://community.cloudflare.com/llms.txt) — LLMs.txt with server info and install instructions -- [`/.well-known/agent.json`](https://community.cloudflare.com/.well-known/agent.json) — A2A Agent Card - -## Related resources - -- [Setup guide with detailed configuration instructions](https://community.cloudflare.com/mcp) -- [The official `npm: @discourse/mcp` package](https://www.npmjs.com/package/@discourse/mcp) -- [Model Context Protocol specification](https://modelcontextprotocol.io) -- [Building AI agents on Cloudflare](/agents/) -- [Cloudflare Community forum](https://community.cloudflare.com) diff --git a/src/content/docs/agents/concepts/human-in-the-loop.mdx b/src/content/docs/agents/concepts/agentic-patterns/human-in-the-loop.mdx similarity index 99% rename from src/content/docs/agents/concepts/human-in-the-loop.mdx rename to src/content/docs/agents/concepts/agentic-patterns/human-in-the-loop.mdx index 26507e8983cb8a3..840c6d20b5ff120 100644 --- a/src/content/docs/agents/concepts/human-in-the-loop.mdx +++ b/src/content/docs/agents/concepts/agentic-patterns/human-in-the-loop.mdx @@ -2,7 +2,7 @@ title: Human-in-the-loop patterns pcx_content_type: how-to sidebar: - order: 3 + order: 2 description: Implement human-in-the-loop functionality using Cloudflare Agents for workflow approvals and MCP elicitation --- @@ -537,7 +537,7 @@ class MultiApprovalAgent extends Agent { diff --git a/src/content/docs/agents/concepts/patterns.mdx b/src/content/docs/agents/concepts/agentic-patterns/index.mdx similarity index 91% rename from src/content/docs/agents/concepts/patterns.mdx rename to src/content/docs/agents/concepts/agentic-patterns/index.mdx index 620803069a7bff4..725425c9cd82d3e 100644 --- a/src/content/docs/agents/concepts/patterns.mdx +++ b/src/content/docs/agents/concepts/agentic-patterns/index.mdx @@ -1,9 +1,11 @@ --- pcx_content_type: concept -title: Patterns +title: Agentic patterns description: Implement common AI agent patterns like prompt chaining, routing, parallelization, and orchestrator-workers on Cloudflare. sidebar: - order: 3 + order: 99 + group: + hideIndex: false head: [] products: - agents @@ -11,7 +13,7 @@ products: import { GitHubCode } from "~/components"; -This page lists and defines common patterns for implementing AI agents, based on [Anthropic's patterns for building effective agents](https://www.anthropic.com/research/building-effective-agents). +This page lists and defines common patterns for implementing AI agents, based on [Anthropic's patterns for building effective agents](https://www.anthropic.com/research/building-effective-agents). For full examples, refer to the [Cloudflare Agents implementation examples](https://github.com/cloudflare/agents/tree/main/guides/anthropic-patterns). Code samples use the [AI SDK](https://ai-sdk.dev/docs/foundations/agents), running in [Durable Objects](/durable-objects). diff --git a/src/content/docs/agents/concepts/long-running-agents.mdx b/src/content/docs/agents/concepts/agentic-patterns/long-running-agents.mdx similarity index 98% rename from src/content/docs/agents/concepts/long-running-agents.mdx rename to src/content/docs/agents/concepts/agentic-patterns/long-running-agents.mdx index eae54955bf341ae..9e84a49f8bc0a4b 100644 --- a/src/content/docs/agents/concepts/long-running-agents.mdx +++ b/src/content/docs/agents/concepts/agentic-patterns/long-running-agents.mdx @@ -5,7 +5,7 @@ description: Build agents that persist for days, weeks, or months — surviving tags: - AI sidebar: - order: 7 + order: 3 --- Build agents that persist for days, weeks, or months — surviving restarts, waking on demand, and managing work that spans far longer than any single request. @@ -209,7 +209,7 @@ try { | ---------------- | ---------------------------------------------------------------------------- | | Seconds | Normal request handling | | Minutes | `keepAlive()` / `keepAliveWhile()` | -| Minutes to hours | [Workflows](/agents/concepts/workflows/) | +| Minutes to hours | [Workflows](/agents/runtime/execution/run-workflows/) | | Hours to days | Async pattern: start job, hibernate, wake on completion | ## Surviving crashes: fibers and recovery @@ -349,7 +349,7 @@ export class ProjectManager extends Agent { ### Pattern: workflow delegation -A production deployment involves multiple steps that must each retry independently — build, test, stage, promote. The project manager should not manage these steps internally; it delegates to a [Workflow](/agents/concepts/workflows/) that handles retries and step sequencing: +A production deployment involves multiple steps that must each retry independently — build, test, stage, promote. The project manager should not manage these steps internally; it delegates to a [Workflow](/agents/runtime/execution/run-workflows/) that handles retries and step sequencing: ```ts export class ProjectManager extends Agent { @@ -678,10 +678,10 @@ The agent does not need to run continuously to do any of this. It just needs to - [Durable Execution](/agents/runtime/execution/durable-execution/) — `runFiber()`, `stash()`, and crash recovery - [Schedule tasks](/agents/runtime/execution/schedule-tasks/) — delayed, cron, and interval tasks - [Retries](/agents/runtime/execution/retries/) — retry options and patterns -- [Workflows](/agents/concepts/workflows/) — durable multi-step processing +- [Workflows](/agents/runtime/execution/run-workflows/) — durable multi-step processing - [Store and sync state](/agents/runtime/lifecycle/state/) — `setState()` and persistence - [WebSockets](/agents/runtime/communication/websockets/) — lifecycle hooks and hibernation - [Callable methods](/agents/runtime/lifecycle/callable-methods/) — RPC via `@callable` and service bindings - [Email routing](/agents/communication-channels/email/) — receiving inbound email - [Webhooks](/agents/communication-channels/webhooks/) — receiving external events -- [Human in the loop](/agents/concepts/human-in-the-loop/) — approval flows +- [Human in the loop](/agents/concepts/agentic-patterns/human-in-the-loop/) — approval flows diff --git a/src/content/docs/agents/concepts/anthropic-agent-patterns.mdx b/src/content/docs/agents/concepts/anthropic-agent-patterns.mdx deleted file mode 100644 index 259f7e92725a3d2..000000000000000 --- a/src/content/docs/agents/concepts/anthropic-agent-patterns.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Implement effective agent patterns -external_link: https://github.com/cloudflare/agents/tree/main/guides/anthropic-patterns -sidebar: - order: 9 -head: [] -description: Implement common agent patterns using the Agents SDK framework. -products: - - agents ---- diff --git a/src/content/docs/agents/concepts/memory.mdx b/src/content/docs/agents/concepts/conversation-state-and-memory.mdx similarity index 99% rename from src/content/docs/agents/concepts/memory.mdx rename to src/content/docs/agents/concepts/conversation-state-and-memory.mdx index 605c408b93f5c76..009ce5da63feeee 100644 --- a/src/content/docs/agents/concepts/memory.mdx +++ b/src/content/docs/agents/concepts/conversation-state-and-memory.mdx @@ -1,11 +1,11 @@ --- -title: Memory +title: Conversation state and memory pcx_content_type: concept description: How agents store and recall information, including read-only context, writable short-form memory, searchable knowledge, and on-demand skills. tags: - AI sidebar: - order: 8 + order: 4 --- import { TypeScriptExample, LinkCard, WranglerConfig } from "~/components"; diff --git a/src/content/docs/agents/concepts/tools.mdx b/src/content/docs/agents/concepts/tools.mdx index 6ffcaa2729473e7..40a1831deae49a3 100644 --- a/src/content/docs/agents/concepts/tools.mdx +++ b/src/content/docs/agents/concepts/tools.mdx @@ -20,7 +20,7 @@ Cloudflare Agents support several tool patterns. Choose the smallest one that fi | ----------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | | Server-side tools | The tool can run entirely in the Worker, such as fetching an API or querying SQL | [Chat agents](/agents/api-reference/chat-agents/#server-side-tools) | | Client-side tools | The tool needs browser APIs such as geolocation, clipboard, or local storage | [Chat agents](/agents/api-reference/chat-agents/#client-side-tools) | -| Human approvals | The tool is sensitive and needs a user decision before it runs | [Human-in-the-loop](/agents/concepts/human-in-the-loop/) | +| Human approvals | The tool is sensitive and needs a user decision before it runs | [Human-in-the-loop](/agents/concepts/agentic-patterns/human-in-the-loop/) | | MCP tools | You want to expose or consume tools through the Model Context Protocol | [Model Context Protocol](/agents/model-context-protocol/) | | Agent tools | You want a chat agent to run another chat-capable sub-agent as a retained, streaming tool | [Agent tools](/agents/api-reference/agent-tools/) | diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index 0e670a4d16ae5bf..1c96d311a33e40f 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -65,7 +65,7 @@ An agent can dynamically generate an itinerary and execute on booking reservatio Agent systems typically have three primary components: - **Decision Engine**: Usually an LLM (Large Language Model) that determines action steps -- **Tool Integration**: APIs, functions, and services the agent can utilize — often via [MCP](/agents/tools/mcp/) +- **Tool Integration**: APIs, functions, and services the agent can utilize — often via [MCP](/agents/mcp/) - **Memory System**: Maintains context and tracks task progress ### How agents work diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx deleted file mode 100644 index f331a75501a6fe6..000000000000000 --- a/src/content/docs/agents/concepts/workflows.mdx +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: Workflows -description: Integrate Cloudflare Workflows with Agents for durable, multi-step background processing with automatic retries. -pcx_content_type: concept -sidebar: - order: 3 -products: - - agents ---- - -import { TypeScriptExample, LinkCard } from "~/components"; - -## What are Workflows? - -[Cloudflare Workflows](/workflows/) provide durable, multi-step execution for tasks that need to survive failures, retry automatically, and wait for external events. When integrated with Agents, Workflows handle long-running background processing while Agents manage real-time communication. - -### Agents vs. Workflows - -Agents and Workflows have complementary strengths: - -| Capability | Agents | Workflows | -| ----------------------- | ---------------------------------------- | ------------------------------ | -| Execution model | Long-lived identity that wakes on events | Run to completion | -| Real-time communication | WebSockets, HTTP streaming | Not supported | -| State persistence | Built-in SQL database | Step-level persistence | -| Failure handling | Application-defined | Automatic retries and recovery | -| External events | Direct handling | Pause and wait for events | -| User interaction | Direct (chat, UI) | Through Agent callbacks | - -Agents can loop, branch, and interact directly with users. Workflows execute steps sequentially with guaranteed delivery and can pause for days waiting for approvals or external data. - -### When to use each - -**Use Agents alone for:** - -- Chat and messaging applications -- Quick API calls and responses -- Real-time collaborative features -- Tasks under 30 seconds -- One durable Think chat turn with [`submitMessages()`](/agents/api-reference/think/#submitmessages) - -**Use Agents with Workflows for:** - -- Data processing pipelines -- Report generation -- Human-in-the-loop approval flows -- Tasks requiring guaranteed delivery -- Multi-step operations with retry requirements - -**Use Workflows alone for:** - -- Background jobs with or without user approval -- Scheduled data synchronization -- Event-driven processing pipelines - -## How Agents and Workflows communicate - -The `AgentWorkflow` class (imported from `agents/workflows`) provides bidirectional communication between Workflows and their originating Agent. - -### Workflow to Agent - -Workflows can communicate with Agents through several mechanisms: - -- **RPC calls**: Directly call Agent methods with full type safety via `this.agent` -- **Progress reporting**: Send progress updates via `this.reportProgress()` that trigger Agent callbacks -- **State updates**: Modify Agent state via `step.updateAgentState()` or `step.mergeAgentState()`, which broadcasts to connected clients -- **Client broadcasts**: Send messages to all WebSocket clients via `this.broadcastToClients()` - - - -```ts -// Inside a workflow's run() method -await this.agent.updateTaskStatus(taskId, "processing"); // RPC call -await this.reportProgress({ step: "process", percent: 0.5 }); // Progress (non-durable) -this.broadcastToClients({ type: "update", taskId }); // Broadcast (non-durable) -await step.mergeAgentState({ taskProgress: 0.5 }); // State update (durable) -``` - - - -### Agent to Workflow - -Agents can interact with running Workflows by: - -- **Starting workflows**: Launch new workflow instances with `runWorkflow()` -- **Sending events**: Dispatch events with `sendWorkflowEvent()` -- **Approval/rejection**: Respond to approval requests with `approveWorkflow()` / `rejectWorkflow()` -- **Workflow control**: Pause, resume, terminate, or restart workflows -- **Status queries**: Check workflow progress with `getWorkflow()` / `getWorkflows()` - -## Durable vs. non-durable operations - -Understanding durability is key to using workflows effectively: - -### Non-durable (may repeat on retry) - -These operations are lightweight and suitable for frequent updates, but may execute multiple times if the workflow retries: - -- `this.reportProgress()` — Progress reporting -- `this.broadcastToClients()` — WebSocket broadcasts -- Direct RPC calls to `this.agent` - -### Durable (idempotent, won't repeat) - -These operations use the `step` parameter and are guaranteed to execute exactly once: - -- `step.do()` — Execute durable steps -- `step.reportComplete()` / `step.reportError()` — Completion reporting -- `step.sendEvent()` — Custom events -- `step.updateAgentState()` / `step.mergeAgentState()` — State synchronization - -## Durability guarantees - -Workflows provide durability through step-based execution: - -1. **Step completion is permanent** — Once a step completes, it will not re-execute even if the workflow restarts -2. **Automatic retries** — Failed steps retry with configurable backoff -3. **Event persistence** — Workflows can wait for events for up to one year -4. **State recovery** — Workflow state survives infrastructure failures - -This durability model means workflows are well-suited for tasks where partial completion must be preserved, such as multi-stage data processing or transactions spanning multiple systems. - -## Workflow tracking - -When an Agent starts a workflow using `runWorkflow()`, the workflow is automatically tracked in the Agent's internal database. This enables: - -- Querying workflow status by ID, name, or metadata with cursor-based pagination -- Monitoring progress through lifecycle callbacks (`onWorkflowProgress`, `onWorkflowComplete`, `onWorkflowError`) -- Workflow control: pause, resume, terminate, restart -- Cleaning up completed workflow records with `deleteWorkflow()` / `deleteWorkflows()` -- Correlating workflows with users or sessions through metadata - -## Common patterns - -### Background processing with progress - -An Agent receives a request, starts a Workflow for heavy processing, and broadcasts progress updates to connected clients as the Workflow executes each step. - - - -```ts -// Workflow reports progress after each item -for (let i = 0; i < items.length; i++) { - await step.do(`process-${i}`, async () => processItem(items[i])); - await this.reportProgress({ - step: `process-${i}`, - percent: (i + 1) / items.length, - message: `Processed ${i + 1}/${items.length}`, - }); -} -``` - - - -### Human-in-the-loop approval - -A Workflow prepares a request, pauses to wait for approval using `waitForApproval()`, and the Agent provides UI for users to approve or reject via `approveWorkflow()` / `rejectWorkflow()`. The Workflow resumes or throws `WorkflowRejectedError` based on the decision. - -### Resilient external API calls - -A Workflow wraps external API calls in durable steps with retry logic. If the API fails or the workflow restarts, completed calls are not repeated and failed calls retry automatically. - - - -```ts -const result = await step.do( - "call-api", - { - retries: { limit: 5, delay: "10 seconds", backoff: "exponential" }, - timeout: "5 minutes", - }, - async () => { - const response = await fetch("https://api.example.com/process"); - if (!response.ok) throw new Error(`API error: ${response.status}`); - return response.json(); - }, -); -``` - - - -### State synchronization - -A Workflow updates Agent state at key milestones using `step.updateAgentState()` or `step.mergeAgentState()`. These state changes broadcast to all connected clients, keeping UIs synchronized without polling. - -## Related resources - - - - - - diff --git a/src/content/docs/agents/examples/chat-agent.mdx b/src/content/docs/agents/examples/chat-agent.mdx index 97e0c2ef3cd8229..2984361252fa1b8 100644 --- a/src/content/docs/agents/examples/chat-agent.mdx +++ b/src/content/docs/agents/examples/chat-agent.mdx @@ -365,6 +365,6 @@ Your chat agent has: diff --git a/src/content/docs/agents/examples/payment-agent.mdx b/src/content/docs/agents/examples/payment-agent.mdx index 61923d7a2df288c..18ecfa0c2a4a8b5 100644 --- a/src/content/docs/agents/examples/payment-agent.mdx +++ b/src/content/docs/agents/examples/payment-agent.mdx @@ -61,4 +61,4 @@ Use `base-sepolia` for testing. Get test USDC from the [Circle faucet](https://f - [Charge for MCP tools](/agents/tools/payments/x402/charge-for-mcp-tools/) — Build servers that charge for tools - [Pay from coding tools](/agents/tools/payments/x402/pay-with-tool-plugins/) — Add payments to OpenCode or Claude Code -- [Human-in-the-loop guide](/agents/concepts/human-in-the-loop/) — Implement approval workflows +- [Human-in-the-loop guide](/agents/concepts/agentic-patterns/human-in-the-loop/) — Implement approval workflows diff --git a/src/content/docs/agents/examples/slack-agent.mdx b/src/content/docs/agents/examples/slack-agent.mdx index d3cd5cb0fd27daf..bbb2cf900becc68 100644 --- a/src/content/docs/agents/examples/slack-agent.mdx +++ b/src/content/docs/agents/examples/slack-agent.mdx @@ -453,7 +453,7 @@ export class MyAgent extends SlackAgent { ## Next steps - Add [Slack Interactive Components](https://api.slack.com/interactivity) (buttons, modals) -- Connect your Agent to an [MCP server](/agents/tools/mcp/apis/client-api/) +- Connect your Agent to an [MCP server](/agents/mcp/apis/client-api/) - Add rate limiting to prevent abuse - Implement conversation state management - Use [Workers Analytics Engine](/analytics/analytics-engine/) to track usage diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index a9532843926d092..0850ca8e219fa09 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -334,7 +334,7 @@ Now that you have a working agent, explore these topics: | Learn how to | Refer to | | ------------------------ | --------------------------------------------------------- | | Add AI/LLM capabilities | [Using AI models](/agents/runtime/operations/using-ai-models/) | -| Expose tools via MCP | [MCP servers](/agents/tools/mcp/apis/agent-api/) | +| Expose tools via MCP | [MCP servers](/agents/mcp/apis/agent-api/) | | Run background tasks | [Schedule tasks](/agents/runtime/execution/schedule-tasks/) | | Handle emails | [Email routing](/agents/communication-channels/email/) | | Use Cloudflare Workflows | [Run Workflows](/agents/runtime/execution/run-workflows/) | diff --git a/src/content/docs/agents/harnesses/index.mdx b/src/content/docs/agents/harnesses/index.mdx index a441066cbf68c05..e7266d62ad5e8f8 100644 --- a/src/content/docs/agents/harnesses/index.mdx +++ b/src/content/docs/agents/harnesses/index.mdx @@ -9,18 +9,26 @@ sidebar: import { DirectoryListing, LinkCard } from "~/components"; -A harness is the loop that runs an agent. It decides how the agent receives a message, calls a model, selects tools, handles tool results, streams output, persists state, and decides whether to continue or stop. +A harness is the loop that makes an agent behave like an agent instead of a single model call. -You can build this loop yourself with the [Agents SDK runtime](/agents/runtime/agents-api/), or use an opinionated harness like [Project Think](/agents/harnesses/think/). +It is responsible for the turn-by-turn work around the model: building the prompt, loading memory, selecting tools, handling tool results, streaming responses, persisting messages, and deciding whether the agent should continue or stop. -## Harnesses and runtime +You can build this loop yourself on top of the [Agents SDK runtime](/agents/runtime/agents-api/), or use an opinionated harness like [Project Think](/agents/harnesses/think/). + +## How harnesses fit Harnesses sit on top of the Agents SDK runtime: -- **The runtime** provides durable infrastructure: the `Agent` class, state, sessions, routing, WebSockets, scheduling, fibers, and observability. -- **The harness** provides agent behavior: the model call, prompt construction, tool selection, stream handling, memory strategy, and extension points. +- **The runtime** gives the agent durable infrastructure: the [`Agent` class](/agents/runtime/lifecycle/agent-class/), [state](/agents/runtime/lifecycle/state/), [sessions](/agents/runtime/lifecycle/sessions/), [routing](/agents/runtime/communication/routing/), [WebSockets](/agents/runtime/communication/websockets/), [scheduling](/agents/runtime/execution/schedule-tasks/), [fibers](/agents/runtime/execution/durable-execution/), and [observability](/agents/runtime/operations/observability/). +- **The harness** gives the agent behavior: model calls, prompt construction, tool selection, stream handling, memory strategy, and lifecycle hooks. + +The runtime answers “where does this agent live and how does it stay durable?” The harness answers “what does this agent do on each turn?” + +## Choose an approach + +Use a build-your-own harness when you need full control over the model call, message format, tool loop, or UI protocol. This is the right approach when you want to compose low-level APIs directly from the Agents SDK. -Use the runtime directly when you need full control over every part of the loop. Use a harness when you want common agent behavior packaged into a reusable base class. +Use Project Think when you want an opinionated chat-agent harness with defaults for memory, workspace tools, streaming, lifecycle hooks, sub-agent RPC, and durable chat recovery. ## Current harnesses @@ -30,12 +38,23 @@ Use the runtime directly when you need full control over every part of the loop. description="An opinionated chat agent harness with built-in tools, persistent memory, lifecycle hooks, streaming, and sub-agent RPC." /> +## What a harness usually owns + +A harness usually owns: + +- **Prompt construction** — system prompts, memory, retrieved context, and per-turn instructions. +- **Model execution** — the call to Workers AI, OpenAI, Anthropic, Gemini, or another provider. +- **Tool orchestration** — server tools, client tools, MCP tools, approval flows, and continuation after tool results. +- **Message persistence** — how user, assistant, and tool messages are saved and replayed. +- **Streaming and recovery** — how responses stream to clients and resume after disconnects or Durable Object eviction. +- **Extension points** — hooks before and after turns, steps, tool calls, and recovery events. + ## Related resources diff --git a/src/content/docs/agents/tools/mcp/apis/client-api.mdx b/src/content/docs/agents/mcp/apis/client-api.mdx similarity index 98% rename from src/content/docs/agents/tools/mcp/apis/client-api.mdx rename to src/content/docs/agents/mcp/apis/client-api.mdx index b5ee00eea456771..c115d9243d61543 100644 --- a/src/content/docs/agents/tools/mcp/apis/client-api.mdx +++ b/src/content/docs/agents/mcp/apis/client-api.mdx @@ -12,7 +12,7 @@ products: import { Render, TypeScriptExample, LinkCard } from "~/components"; -Connect your agent to external [Model Context Protocol (MCP)](/agents/tools/mcp/) servers to use their tools, resources, and prompts. This enables your agent to interact with GitHub, Slack, databases, and other services through a standardized protocol. +Connect your agent to external [Model Context Protocol (MCP)](/agents/mcp/) servers to use their tools, resources, and prompts. This enables your agent to interact with GitHub, Slack, databases, and other services through a standardized protocol. ## Overview @@ -25,7 +25,7 @@ The MCP client capability lets your agent: :::note -This page covers connecting to MCP servers as a client. To create your own MCP server, refer to [Creating MCP servers](/agents/tools/mcp/apis/agent-api/). +This page covers connecting to MCP servers as a client. To create your own MCP server, refer to [Creating MCP servers](/agents/mcp/apis/agent-api/). ::: @@ -136,7 +136,7 @@ MCP server URLs are validated before connection to prevent Server-Side Request F Loopback addresses (`localhost`, `127.x.x.x`, `[::1]`) are **allowed** for local development. -For production connections to internal services, use the [RPC transport](/agents/tools/mcp/protocol/transport/) with a Durable Object binding instead of HTTP. +For production connections to internal services, use the [RPC transport](/agents/mcp/protocol/transport/) with a Durable Object binding instead of HTTP. ### Return value @@ -529,7 +529,7 @@ async addMcpServer( - `client` — MCP client configuration options - `retry` — Retry options for the connection -RPC transport connects your Agent directly to an `McpAgent` via Durable Object bindings without HTTP overhead. Refer to [MCP Transport](/agents/tools/mcp/protocol/transport/) for details on configuring RPC transport. +RPC transport connects your Agent directly to an `McpAgent` via Durable Object bindings without HTTP overhead. Refer to [MCP Transport](/agents/mcp/protocol/transport/) for details on configuring RPC transport. #### Returns @@ -945,7 +945,7 @@ export class MyAgent extends Agent { diff --git a/src/content/docs/agents/tools/mcp/apis/handler-api.mdx b/src/content/docs/agents/mcp/apis/handler-api.mdx similarity index 92% rename from src/content/docs/agents/tools/mcp/apis/handler-api.mdx rename to src/content/docs/agents/mcp/apis/handler-api.mdx index 33bfe134cc34b7b..a9832e59e910b7c 100644 --- a/src/content/docs/agents/tools/mcp/apis/handler-api.mdx +++ b/src/content/docs/agents/mcp/apis/handler-api.mdx @@ -12,7 +12,7 @@ products: import { TypeScriptExample, LinkCard } from "~/components"; -The `createMcpHandler` function creates a fetch handler to serve your [MCP server](/agents/tools/mcp/). Use it when you want a stateless MCP server that runs in a plain Worker (no Durable Object). For stateful MCP servers that persist state across requests, use the [`McpAgent`](/agents/tools/mcp/apis/agent-api/) class instead. +The `createMcpHandler` function creates a fetch handler to serve your [MCP server](/agents/mcp/). Use it when you want a stateless MCP server that runs in a plain Worker (no Durable Object). For stateful MCP servers that persist state across requests, use the [`McpAgent`](/agents/mcp/apis/agent-api/) class instead. It uses an implementation of the MCP Transport interface, `WorkerTransport`, built on top of web standards, which conforms to the [streamable-http](https://modelcontextprotocol.io/specification/draft/basic/transports/#streamable-http) transport specification. @@ -89,9 +89,9 @@ const handler = createMcpHandler(server, { #### authContext -An authentication context object that will be available to MCP tools via [`getMcpAuthContext()`](/agents/tools/mcp/apis/handler-api/#authentication-context). +An authentication context object that will be available to MCP tools via [`getMcpAuthContext()`](/agents/mcp/apis/handler-api/#authentication-context). -When using the [`OAuthProvider`](/agents/tools/mcp/protocol/authorization/) from `@cloudflare/workers-oauth-provider`, the authentication context is automatically populated with information from the OAuth flow. You typically don't need to set this manually. +When using the [`OAuthProvider`](/agents/mcp/protocol/authorization/) from `@cloudflare/workers-oauth-provider`, the authentication context is automatically populated with information from the OAuth flow. You typically don't need to set this manually. #### transport @@ -127,7 +127,7 @@ MCP SDK 1.26.0 introduces a guard that prevents connecting to a server instance **If your stateless MCP server declares `McpServer` or transport instances in the global scope, you must create new instances per request.** -See the [migration guide](/agents/tools/mcp/apis/handler-api/#migration-guide-for-mcp-sdk-1260) below for details. +See the [migration guide](/agents/mcp/apis/handler-api/#migration-guide-for-mcp-sdk-1260) below for details. ::: @@ -546,7 +546,7 @@ const transport = new WorkerTransport({ ## Authentication Context -When using [OAuth authentication](/agents/tools/mcp/protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available. +When using [OAuth authentication](/agents/mcp/protocol/authorization/) with `createMcpHandler`, user information is made available to your MCP tools through `getMcpAuthContext()`. Under the hood this uses `AsyncLocalStorage` to pass the request to the tool handler, keeping the authentication context available. ```ts interface McpAuthContext { @@ -595,7 +595,7 @@ function createServer() { :::note -For a complete guide on setting up OAuth authentication with MCP servers, see the [MCP Authorization documentation](/agents/tools/mcp/protocol/authorization/). View the [complete authenticated MCP server in a Worker example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). +For a complete guide on setting up OAuth authentication with MCP servers, see the [MCP Authorization documentation](/agents/mcp/protocol/authorization/). View the [complete authenticated MCP server in a Worker example on GitHub](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). ::: ## Error Handling @@ -631,24 +631,24 @@ server.tool("riskyOperation", "An operation that might fail", {}, async () => { diff --git a/src/content/docs/agents/tools/mcp/apis/index.mdx b/src/content/docs/agents/mcp/apis/index.mdx similarity index 100% rename from src/content/docs/agents/tools/mcp/apis/index.mdx rename to src/content/docs/agents/mcp/apis/index.mdx diff --git a/src/content/docs/agents/tools/mcp/cloudflare/index.mdx b/src/content/docs/agents/mcp/cloudflare/index.mdx similarity index 100% rename from src/content/docs/agents/tools/mcp/cloudflare/index.mdx rename to src/content/docs/agents/mcp/cloudflare/index.mdx diff --git a/src/content/docs/agents/tools/mcp/cloudflare/mcp-portal.mdx b/src/content/docs/agents/mcp/cloudflare/mcp-portal.mdx similarity index 100% rename from src/content/docs/agents/tools/mcp/cloudflare/mcp-portal.mdx rename to src/content/docs/agents/mcp/cloudflare/mcp-portal.mdx diff --git a/src/content/docs/agents/tools/mcp/cloudflare/servers-for-cloudflare.mdx b/src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx similarity index 97% rename from src/content/docs/agents/tools/mcp/cloudflare/servers-for-cloudflare.mdx rename to src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx index 3b466a5e0811b51..249025114c0b06f 100644 --- a/src/content/docs/agents/tools/mcp/cloudflare/servers-for-cloudflare.mdx +++ b/src/content/docs/agents/mcp/cloudflare/servers-for-cloudflare.mdx @@ -18,7 +18,7 @@ These MCP servers allow your MCP client to read configurations from your account The [Cloudflare API MCP server](https://github.com/cloudflare/mcp) provides access to the entire [Cloudflare API](/api/) — over 2,500 endpoints across DNS, Workers, R2, Zero Trust, and every other product — through just two tools: `search()` and `execute()`. -It uses [Codemode](/agents/tools/mcp/protocol/codemode/), a technique where the model writes JavaScript against a typed representation of the OpenAPI spec and the Cloudflare API client, rather than loading individual tool definitions for each endpoint. The generated code runs inside an isolated [Dynamic Worker](/workers/runtime-apis/bindings/worker-loader/) sandbox. +It uses [Codemode](/agents/mcp/protocol/codemode/), a technique where the model writes JavaScript against a typed representation of the OpenAPI spec and the Cloudflare API client, rather than loading individual tool definitions for each endpoint. The generated code runs inside an isolated [Dynamic Worker](/workers/runtime-apis/bindings/worker-loader/) sandbox. This approach uses approximately 1,000 tokens regardless of how many API endpoints exist. An equivalent MCP server that exposed every endpoint as a native tool would consume over 1 million tokens — more than the entire context window of most foundation models. diff --git a/src/content/docs/agents/tools/mcp/guides/build-mcp-client.mdx b/src/content/docs/agents/mcp/guides/build-mcp-client.mdx similarity index 100% rename from src/content/docs/agents/tools/mcp/guides/build-mcp-client.mdx rename to src/content/docs/agents/mcp/guides/build-mcp-client.mdx diff --git a/src/content/docs/agents/tools/mcp/guides/connect-mcp-client.mdx b/src/content/docs/agents/mcp/guides/connect-mcp-client.mdx similarity index 98% rename from src/content/docs/agents/tools/mcp/guides/connect-mcp-client.mdx rename to src/content/docs/agents/mcp/guides/connect-mcp-client.mdx index 4b73354e1c29df6..ff3bdc10b55ac33 100644 --- a/src/content/docs/agents/tools/mcp/guides/connect-mcp-client.mdx +++ b/src/content/docs/agents/mcp/guides/connect-mcp-client.mdx @@ -236,12 +236,12 @@ Connections persist in the Agent's [SQL storage](/agents/runtime/lifecycle/state diff --git a/src/content/docs/agents/tools/mcp/guides/index.mdx b/src/content/docs/agents/mcp/guides/index.mdx similarity index 100% rename from src/content/docs/agents/tools/mcp/guides/index.mdx rename to src/content/docs/agents/mcp/guides/index.mdx diff --git a/src/content/docs/agents/tools/mcp/guides/oauth-mcp-client.mdx b/src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx similarity index 99% rename from src/content/docs/agents/tools/mcp/guides/oauth-mcp-client.mdx rename to src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx index f311e3dd4c5e6a1..48fa01bc22927d8 100644 --- a/src/content/docs/agents/tools/mcp/guides/oauth-mcp-client.mdx +++ b/src/content/docs/agents/mcp/guides/oauth-mcp-client.mdx @@ -382,12 +382,12 @@ export default { diff --git a/src/content/docs/agents/tools/mcp/guides/remote-mcp-server.mdx b/src/content/docs/agents/mcp/guides/remote-mcp-server.mdx similarity index 89% rename from src/content/docs/agents/tools/mcp/guides/remote-mcp-server.mdx rename to src/content/docs/agents/mcp/guides/remote-mcp-server.mdx index d72f6c8ca5f563a..4d91e41ad185ba6 100644 --- a/src/content/docs/agents/tools/mcp/guides/remote-mcp-server.mdx +++ b/src/content/docs/agents/mcp/guides/remote-mcp-server.mdx @@ -12,10 +12,10 @@ products: import { Details, Render, PackageManagers, LinkCard } from "~/components"; -This guide will show you how to deploy your own remote MCP server on Cloudflare using [Streamable HTTP transport](/agents/tools/mcp/protocol/transport/), the current MCP specification standard. You have two options: +This guide will show you how to deploy your own remote MCP server on Cloudflare using [Streamable HTTP transport](/agents/mcp/protocol/transport/), the current MCP specification standard. You have two options: - **Without authentication** — anyone can connect and use the server (no login required). -- **With [authentication and authorization](/agents/tools/mcp/guides/remote-mcp-server/#add-authentication)** — users sign in before accessing tools, and you can control which tools an agent can call based on the user's permissions. +- **With [authentication and authorization](/agents/mcp/guides/remote-mcp-server/#add-authentication)** — users sign in before accessing tools, and you can control which tools an agent can call based on the user's permissions. ## Choosing an approach @@ -23,8 +23,8 @@ The Agents SDK provides multiple ways to create MCP servers. Choose the approach | Approach | Stateful? | Requires Durable Objects? | Best for | | -------------------------------------------------------------- | --------- | ------------------------- | ---------------------------------------------- | -| [`createMcpHandler()`](/agents/tools/mcp/apis/handler-api/) | No | No | Stateless tools, simplest setup | -| [`McpAgent`](/agents/tools/mcp/apis/agent-api/) | Yes | Yes | Stateful tools, per-session state, elicitation | +| [`createMcpHandler()`](/agents/mcp/apis/handler-api/) | No | No | Stateless tools, simplest setup | +| [`McpAgent`](/agents/mcp/apis/agent-api/) | Yes | Yes | Stateful tools, per-session state, elicitation | | Raw `WebStandardStreamableHTTPServerTransport` | No | No | Full control, no SDK dependency | - **`createMcpHandler()`** is the fastest way to get a stateless MCP server running. Use it when your tools do not need per-session state. @@ -33,7 +33,7 @@ The Agents SDK provides multiple ways to create MCP servers. Choose the approach ## Deploy your first MCP server -You can start by deploying a [public MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) without authentication, then add user authentication and scoped authorization later. If you already know your server will require authentication, you can skip ahead to the [next section](/agents/tools/mcp/guides/remote-mcp-server/#add-authentication). +You can start by deploying a [public MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) without authentication, then add user authentication and scoped authorization later. If you already know your server will require authentication, you can skip ahead to the [next section](/agents/mcp/guides/remote-mcp-server/#add-authentication). ### Via the dashboard @@ -41,9 +41,9 @@ The button below will guide you through everything you need to do to deploy an [ [![Deploy to Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless) -Once deployed, this server will be live at your `workers.dev` subdomain (for example, `remote-mcp-server-authless.your-account.workers.dev/mcp`). You can connect to it immediately using the [AI Playground](https://playground.ai.cloudflare.com/) (a remote MCP client), [MCP inspector](https://github.com/modelcontextprotocol/inspector) or [other MCP clients](/agents/tools/mcp/guides/remote-mcp-server/#connect-from-an-mcp-client-via-a-local-proxy). +Once deployed, this server will be live at your `workers.dev` subdomain (for example, `remote-mcp-server-authless.your-account.workers.dev/mcp`). You can connect to it immediately using the [AI Playground](https://playground.ai.cloudflare.com/) (a remote MCP client), [MCP inspector](https://github.com/modelcontextprotocol/inspector) or [other MCP clients](/agents/mcp/guides/remote-mcp-server/#connect-from-an-mcp-client-via-a-local-proxy). -A new git repository will be set up on your GitHub or GitLab account for your MCP server, configured to automatically deploy to Cloudflare each time you push a change or merge a pull request to the main branch of the repository. You can clone this repository, [develop locally](/agents/tools/mcp/guides/remote-mcp-server/#via-the-cli), and start customizing the MCP server with your own [tools](/agents/tools/mcp/protocol/tools/). +A new git repository will be set up on your GitHub or GitLab account for your MCP server, configured to automatically deploy to Cloudflare each time you push a change or merge a pull request to the main branch of the repository. You can clone this repository, [develop locally](/agents/mcp/guides/remote-mcp-server/#via-the-cli), and start customizing the MCP server with your own [tools](/agents/mcp/protocol/tools/). ### Via the CLI @@ -150,7 +150,7 @@ For example, to connect from Claude Desktop: Claude should invoke the tool and show the result generated by the remote MCP server. -To learn how to use remote MCP servers with other MCP clients, refer to [Test a Remote MCP Server](/agents/tools/mcp/guides/test-remote-mcp-server/). +To learn how to use remote MCP servers with other MCP clients, refer to [Test a Remote MCP Server](/agents/mcp/guides/test-remote-mcp-server/). ## Add Authentication @@ -164,7 +164,7 @@ For a step-by-step deployment guide, refer to [Secure MCP servers with Access fo ### Third-party OAuth -You can connect your MCP server with any [OAuth provider](/agents/tools/mcp/protocol/authorization/#2-third-party-oauth-provider) that supports the OAuth 2.0 specification, including GitHub, Google, Slack, [Stytch](/agents/tools/mcp/protocol/authorization/#stytch), [Auth0](/agents/tools/mcp/protocol/authorization/#auth0), [WorkOS](/agents/tools/mcp/protocol/authorization/#workos), and more. +You can connect your MCP server with any [OAuth provider](/agents/mcp/protocol/authorization/#2-third-party-oauth-provider) that supports the OAuth 2.0 specification, including GitHub, Google, Slack, [Stytch](/agents/mcp/protocol/authorization/#stytch), [Auth0](/agents/mcp/protocol/authorization/#auth0), [WorkOS](/agents/mcp/protocol/authorization/#workos), and more. The following example demonstrates how to use GitHub as an OAuth provider. @@ -308,18 +308,18 @@ Use any random string for `COOKIE_ENCRYPTION_KEY`, for example the output of `op npm run deploy ``` -5. Connect to your server running at `worker-name.account-name.workers.dev/mcp` using the [AI Playground](https://playground.ai.cloudflare.com/), MCP Inspector, or [other MCP clients](/agents/tools/mcp/guides/test-remote-mcp-server/), and authenticate with GitHub. +5. Connect to your server running at `worker-name.account-name.workers.dev/mcp` using the [AI Playground](https://playground.ai.cloudflare.com/), MCP Inspector, or [other MCP clients](/agents/mcp/guides/test-remote-mcp-server/), and authenticate with GitHub. ## Next steps diff --git a/src/content/docs/agents/tools/mcp/guides/securing-mcp-server.mdx b/src/content/docs/agents/mcp/guides/securing-mcp-server.mdx similarity index 98% rename from src/content/docs/agents/tools/mcp/guides/securing-mcp-server.mdx rename to src/content/docs/agents/mcp/guides/securing-mcp-server.mdx index be2189bd362e558..791a260718c7d95 100644 --- a/src/content/docs/agents/tools/mcp/guides/securing-mcp-server.mdx +++ b/src/content/docs/agents/mcp/guides/securing-mcp-server.mdx @@ -276,13 +276,13 @@ When reading the cookie, verify the HMAC signature before trusting the data. If diff --git a/src/content/docs/agents/tools/mcp/guides/test-remote-mcp-server.mdx b/src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx similarity index 97% rename from src/content/docs/agents/tools/mcp/guides/test-remote-mcp-server.mdx rename to src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx index 1a1ef83e69c57b7..b4372a9f5a0e4a3 100644 --- a/src/content/docs/agents/tools/mcp/guides/test-remote-mcp-server.mdx +++ b/src/content/docs/agents/mcp/guides/test-remote-mcp-server.mdx @@ -14,7 +14,7 @@ import { Render } from "~/components"; Remote, authorized connections are an evolving part of the [Model Context Protocol (MCP) specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization). Not all MCP clients support remote connections yet. -This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/tools/mcp/guides/remote-mcp-server/) guide first. +This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/mcp/guides/remote-mcp-server/) guide first. ## The Model Context Protocol (MCP) inspector diff --git a/src/content/docs/agents/tools/mcp/index.mdx b/src/content/docs/agents/mcp/index.mdx similarity index 51% rename from src/content/docs/agents/tools/mcp/index.mdx rename to src/content/docs/agents/mcp/index.mdx index 47e031ea396c120..5d9d01e86d941d3 100644 --- a/src/content/docs/agents/tools/mcp/index.mdx +++ b/src/content/docs/agents/mcp/index.mdx @@ -1,14 +1,14 @@ --- -title: MCP +title: Model Context Protocol (MCP) pcx_content_type: navigation sidebar: - order: 2 + order: 7 group: hideIndex: true --- import { DirectoryListing } from "~/components"; -Model Context Protocol (MCP) integration for agents. +Build MCP clients and servers, expose tools, and connect agents to external capabilities. diff --git a/src/content/docs/agents/tools/mcp/protocol/authorization.mdx b/src/content/docs/agents/mcp/protocol/authorization.mdx similarity index 96% rename from src/content/docs/agents/tools/mcp/protocol/authorization.mdx rename to src/content/docs/agents/mcp/protocol/authorization.mdx index 44b60b57cbc598a..8f9847cf932a907 100644 --- a/src/content/docs/agents/tools/mcp/protocol/authorization.mdx +++ b/src/content/docs/agents/mcp/protocol/authorization.mdx @@ -37,7 +37,7 @@ To deploy an [example MCP server](https://github.com/cloudflare/ai/tree/main/dem ### (2) Third-party OAuth Provider -The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/tools/mcp/guides/remote-mcp-server/#add-authentication). +The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/mcp/guides/remote-mcp-server/#add-authentication). When you use a third-party OAuth provider, you must provide a handler to the `OAuthProvider` that implements the OAuth flow for the third-party provider. @@ -148,7 +148,7 @@ export default new OAuthProvider({ }); ``` -Refer to the [getting started example](/agents/tools/mcp/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. +Refer to the [getting started example](/agents/mcp/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. The authorization flow in this case works like this: @@ -172,7 +172,7 @@ sequenceDiagram Note over C,M: Begin standard MCP message exchange ``` -Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/tools/mcp/guides/remote-mcp-server/) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. +Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/mcp/guides/remote-mcp-server/) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. ## Using authentication context in tools diff --git a/src/content/docs/agents/tools/mcp/protocol/codemode.mdx b/src/content/docs/agents/mcp/protocol/codemode.mdx similarity index 99% rename from src/content/docs/agents/tools/mcp/protocol/codemode.mdx rename to src/content/docs/agents/mcp/protocol/codemode.mdx index 27975a187cfd8a3..57dc879541d1641 100644 --- a/src/content/docs/agents/tools/mcp/protocol/codemode.mdx +++ b/src/content/docs/agents/mcp/protocol/codemode.mdx @@ -407,6 +407,6 @@ sanitizeToolName("delete"); // "delete_" diff --git a/src/content/docs/agents/tools/mcp/protocol/governance.mdx b/src/content/docs/agents/mcp/protocol/governance.mdx similarity index 66% rename from src/content/docs/agents/tools/mcp/protocol/governance.mdx rename to src/content/docs/agents/mcp/protocol/governance.mdx index 8dc82c4967525b3..a2f014510c9f78b 100644 --- a/src/content/docs/agents/tools/mcp/protocol/governance.mdx +++ b/src/content/docs/agents/mcp/protocol/governance.mdx @@ -28,6 +28,6 @@ Cloudflare Access logs MCP server requests and tool executions made through the ## Remote MCP servers -To maintain a modern security posture, Cloudflare recommends the use of [remote MCP servers](/agents/tools/mcp/guides/remote-mcp-server/) over local installations. Running MCP servers locally introduces risks similar to unmanaged [shadow IT](https://www.cloudflare.com/learning/access-management/what-is-shadow-it/), making it difficult to audit data flow or verify the integrity of the server code. Remote MCP servers give administrators visibility into what servers are being used, along with the ability to control who access them and what tools are authorized for employee use. +To maintain a modern security posture, Cloudflare recommends the use of [remote MCP servers](/agents/mcp/guides/remote-mcp-server/) over local installations. Running MCP servers locally introduces risks similar to unmanaged [shadow IT](https://www.cloudflare.com/learning/access-management/what-is-shadow-it/), making it difficult to audit data flow or verify the integrity of the server code. Remote MCP servers give administrators visibility into what servers are being used, along with the ability to control who access them and what tools are authorized for employee use. -You can [build your remote MCP servers](/agents/tools/mcp/guides/remote-mcp-server/) directly on Cloudflare Workers. When both your [MCP server portal](#mcp-server-portals) and remote MCP servers run on Cloudflare's network, requests stay on the same infrastructure, minimizing latency and maximizing performance. +You can [build your remote MCP servers](/agents/mcp/guides/remote-mcp-server/) directly on Cloudflare Workers. When both your [MCP server portal](#mcp-server-portals) and remote MCP servers run on Cloudflare's network, requests stay on the same infrastructure, minimizing latency and maximizing performance. diff --git a/src/content/docs/agents/tools/mcp/protocol/index.mdx b/src/content/docs/agents/mcp/protocol/index.mdx similarity index 100% rename from src/content/docs/agents/tools/mcp/protocol/index.mdx rename to src/content/docs/agents/mcp/protocol/index.mdx diff --git a/src/content/docs/agents/tools/mcp/protocol/tools.mdx b/src/content/docs/agents/mcp/protocol/tools.mdx similarity index 87% rename from src/content/docs/agents/tools/mcp/protocol/tools.mdx rename to src/content/docs/agents/mcp/protocol/tools.mdx index f168ab355df4fbb..79c68cb6b223690 100644 --- a/src/content/docs/agents/tools/mcp/protocol/tools.mdx +++ b/src/content/docs/agents/mcp/protocol/tools.mdx @@ -12,9 +12,9 @@ products: import { TypeScriptExample, LinkCard } from "~/components"; -MCP tools are functions that an [MCP server](/agents/tools/mcp/) exposes for clients to call. When an LLM decides it needs to take an action — look up data, run a calculation, call an API — it invokes a tool. The MCP server executes the tool and returns the result. +MCP tools are functions that an [MCP server](/agents/mcp/) exposes for clients to call. When an LLM decides it needs to take an action — look up data, run a calculation, call an API — it invokes a tool. The MCP server executes the tool and returns the result. -Tools are defined using the `@modelcontextprotocol/sdk` package. The Agents SDK handles transport and lifecycle; the tool definitions are the same regardless of whether you use [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/) or [`McpAgent`](/agents/tools/mcp/apis/agent-api/). +Tools are defined using the `@modelcontextprotocol/sdk` package. The Agents SDK handles transport and lifecycle; the tool definitions are the same regardless of whether you use [`createMcpHandler`](/agents/mcp/apis/handler-api/) or [`McpAgent`](/agents/mcp/apis/agent-api/). :::note[Experimental WebMCP adapter] @@ -134,7 +134,7 @@ server.tool( ## Using tools with `createMcpHandler` -For stateless MCP servers, define tools inside a factory function and pass the server to [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/): +For stateless MCP servers, define tools inside a factory function and pass the server to [`createMcpHandler`](/agents/mcp/apis/handler-api/): @@ -165,7 +165,7 @@ export default { ## Using tools with `McpAgent` -For stateful MCP servers, define tools in the `init()` method of an [`McpAgent`](/agents/tools/mcp/apis/agent-api/). Tools have access to the agent instance via `this`, which means they can read and write state. +For stateful MCP servers, define tools in the `init()` method of an [`McpAgent`](/agents/mcp/apis/agent-api/). Tools have access to the agent instance via `this`, which means they can read and write state. @@ -200,24 +200,24 @@ export class MyMCP extends McpAgent { diff --git a/src/content/docs/agents/tools/mcp/protocol/transport.mdx b/src/content/docs/agents/mcp/protocol/transport.mdx similarity index 92% rename from src/content/docs/agents/tools/mcp/protocol/transport.mdx rename to src/content/docs/agents/mcp/protocol/transport.mdx index d3c2f925cf192f8..271bb6d7fe029d7 100644 --- a/src/content/docs/agents/tools/mcp/protocol/transport.mdx +++ b/src/content/docs/agents/mcp/protocol/transport.mdx @@ -18,14 +18,14 @@ The Model Context Protocol (MCP) specification defines two standard [transport m 2. **Streamable HTTP** — The standard transport method for remote MCP connections, [introduced](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) in March 2025. It uses a single HTTP endpoint for bidirectional messaging. :::note -Server-Sent Events (SSE) was previously used for remote MCP connections but has been deprecated in favor of Streamable HTTP. If you need SSE support for legacy clients, use the [`McpAgent`](/agents/tools/mcp/apis/agent-api/) class. +Server-Sent Events (SSE) was previously used for remote MCP connections but has been deprecated in favor of Streamable HTTP. If you need SSE support for legacy clients, use the [`McpAgent`](/agents/mcp/apis/agent-api/) class. ::: -MCP servers built with the [Agents SDK](/agents) use [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/) to handle Streamable HTTP transport. +MCP servers built with the [Agents SDK](/agents) use [`createMcpHandler`](/agents/mcp/apis/handler-api/) to handle Streamable HTTP transport. ## Implementing remote MCP transport -Use [`createMcpHandler`](/agents/tools/mcp/apis/handler-api/) to create an MCP server that handles Streamable HTTP transport. This is the recommended approach for new MCP servers. +Use [`createMcpHandler`](/agents/mcp/apis/handler-api/) to create an MCP server that handles Streamable HTTP transport. This is the recommended approach for new MCP servers. #### Get started quickly @@ -103,7 +103,7 @@ export default new OAuthProvider({ If your MCP server needs to maintain state across requests, use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. This allows you to persist session state in Durable Object storage and use advanced MCP features like [elicitation](https://modelcontextprotocol.io/specification/draft/client/elicitation) and [sampling](https://modelcontextprotocol.io/specification/draft/client/sampling). -See [Stateful MCP Servers](/agents/tools/mcp/apis/handler-api/#stateful-mcp-servers) for implementation details. +See [Stateful MCP Servers](/agents/mcp/apis/handler-api/#stateful-mcp-servers) for implementation details. ## RPC transport @@ -190,7 +190,7 @@ export class Chat extends AIChatAgent { RPC connections are automatically restored after Durable Object hibernation, just like HTTP connections. The binding name and props are persisted to storage so the connection can be re-established without any extra code. -For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (refer to [MCP Client API](/agents/tools/mcp/apis/client-api/) for details). This makes it safe to call in `onStart()`. +For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (refer to [MCP Client API](/agents/mcp/apis/client-api/) for details). This makes it safe to call in `onStart()`. #### 3. Configure Durable Object bindings @@ -329,11 +329,11 @@ export class MyMCP extends McpAgent { If you have an existing MCP server using the `McpAgent` class: - **Not using state?** Replace your `McpAgent` class with `McpServer` from `@modelcontextprotocol/sdk` and use `createMcpHandler(server)` in a Worker `fetch` handler. -- **Using state?** Use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. See [Stateful MCP Servers](/agents/tools/mcp/apis/handler-api/#stateful-mcp-servers) for details. -- **Need SSE support?** Continue using `McpAgent` with `serveSSE()` for legacy client compatibility. See the [McpAgent API reference](/agents/tools/mcp/apis/agent-api/). +- **Using state?** Use `createMcpHandler` with a `WorkerTransport` inside an [Agent](/agents/) class. See [Stateful MCP Servers](/agents/mcp/apis/handler-api/#stateful-mcp-servers) for details. +- **Need SSE support?** Continue using `McpAgent` with `serveSSE()` for legacy client compatibility. See the [McpAgent API reference](/agents/mcp/apis/agent-api/). ### Testing with MCP clients You can test your MCP server using an MCP client that supports remote connections, or use [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), an adapter that lets MCP clients that only support local connections work with remote MCP servers. -Follow [this guide](/agents/tools/mcp/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server to Claude Desktop, Cursor, Windsurf, and other MCP clients. +Follow [this guide](/agents/mcp/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server to Claude Desktop, Cursor, Windsurf, and other MCP clients. diff --git a/src/content/docs/agents/runtime/agents-api.mdx b/src/content/docs/agents/runtime/agents-api.mdx index 086949344250fc4..1bede17c08075c8 100644 --- a/src/content/docs/agents/runtime/agents-api.mdx +++ b/src/content/docs/agents/runtime/agents-api.mdx @@ -86,7 +86,7 @@ flowchart TD | **HTTP/SSE** | `onRequest()` | [HTTP and SSE](/agents/runtime/communication/http-sse/) | | **Email** | `onEmail()`, `replyToEmail()` | [Email routing](/agents/communication-channels/email/) | | **Workflows** | `runWorkflow()`, `waitForApproval()` | [Run Workflows](/agents/runtime/execution/run-workflows/) | -| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/tools/mcp/apis/client-api/) | +| **MCP Client** | `addMcpServer()`, `removeMcpServer()`, `getMcpServers()` | [MCP Client API](/agents/mcp/apis/client-api/) | | **AI Models** | Workers AI, OpenAI, Anthropic bindings | [Using AI models](/agents/runtime/operations/using-ai-models/) | | **Protocol messages** | `shouldSendProtocolMessages()`, `isConnectionProtocolEnabled()` | [Protocol messages](/agents/runtime/communication/protocol-messages/) | | **Context** | `getCurrentAgent()` | [getCurrentAgent()](/agents/runtime/lifecycle/get-current-agent/) | diff --git a/src/content/docs/agents/runtime/communication/protocol-messages.mdx b/src/content/docs/agents/runtime/communication/protocol-messages.mdx index 6e3b04ac03ad6c5..c7ef371cd344a2d 100644 --- a/src/content/docs/agents/runtime/communication/protocol-messages.mdx +++ b/src/content/docs/agents/runtime/communication/protocol-messages.mdx @@ -202,4 +202,4 @@ Unlike [readonly](/agents/runtime/communication/readonly-connections/) which can - [Readonly connections](/agents/runtime/communication/readonly-connections/) - [WebSockets](/agents/runtime/communication/websockets/) - [Store and sync state](/agents/runtime/lifecycle/state/) -- [MCP Client API](/agents/tools/mcp/apis/client-api/) +- [MCP Client API](/agents/mcp/apis/client-api/) diff --git a/src/content/docs/agents/runtime/communication/routing.mdx b/src/content/docs/agents/runtime/communication/routing.mdx index d6521493ea054c1..8094393b700cee0 100644 --- a/src/content/docs/agents/runtime/communication/routing.mdx +++ b/src/content/docs/agents/runtime/communication/routing.mdx @@ -472,7 +472,7 @@ export default { For agent-specific initialization, use `getAgentByName` instead where you control exactly which agent receives the props. :::note -For `McpAgent`, props are automatically stored and accessible via `this.props`. Refer to [MCP servers](/agents/tools/mcp/apis/agent-api/) for details. +For `McpAgent`, props are automatically stored and accessible via `this.props`. Refer to [MCP servers](/agents/mcp/apis/agent-api/) for details. ::: ### Routing retry diff --git a/src/content/docs/agents/runtime/execution/durable-execution.mdx b/src/content/docs/agents/runtime/execution/durable-execution.mdx index 539eabb5ea5235b..017845836f25947 100644 --- a/src/content/docs/agents/runtime/execution/durable-execution.mdx +++ b/src/content/docs/agents/runtime/execution/durable-execution.mdx @@ -12,7 +12,7 @@ Run work that survives Durable Object eviction. `runFiber()` registers a task in :::note -For how fibers fit into the bigger picture of building agents that run for weeks or months, refer to [Long-running agents](/agents/concepts/long-running-agents/). +For how fibers fit into the bigger picture of building agents that run for weeks or months, refer to [Long-running agents](/agents/concepts/agentic-patterns/long-running-agents/). ::: @@ -56,7 +56,7 @@ When eviction happens mid-work, the upstream HTTP connection (to an LLM provider `keepAlive()` reduces the chance of eviction. `runFiber()` makes eviction survivable. -For work that should run independently of the agent with per-step retries and multi-step orchestration, use [Workflows](/agents/concepts/workflows/) instead. Fibers are for work that is part of the agent's own execution. Refer to [Long-running agents: Workflows vs agent-internal patterns](/agents/concepts/long-running-agents/#when-to-use-workflows-vs-agent-internal-patterns) for a comparison. +For work that should run independently of the agent with per-step retries and multi-step orchestration, use [Workflows](/agents/runtime/execution/run-workflows/) instead. Fibers are for work that is part of the agent's own execution. Refer to [Long-running agents: Workflows vs agent-internal patterns](/agents/concepts/agentic-patterns/long-running-agents/#when-to-use-workflows-vs-agent-internal-patterns) for a comparison. ## keepAlive @@ -283,7 +283,7 @@ Key points: ### Chat recovery -`AIChatAgent` builds on fibers for LLM streaming recovery. When `chatRecovery` is enabled, each chat turn is wrapped in a fiber automatically. The framework handles the internal recovery path and exposes `onChatRecovery` for provider-specific strategies. Refer to [Long-running agents: Recovering interrupted LLM streams](/agents/concepts/long-running-agents/#recovering-interrupted-llm-streams) for details. +`AIChatAgent` builds on fibers for LLM streaming recovery. When `chatRecovery` is enabled, each chat turn is wrapped in a fiber automatically. The framework handles the internal recovery path and exposes `onChatRecovery` for provider-specific strategies. Refer to [Long-running agents: Recovering interrupted LLM streams](/agents/concepts/agentic-patterns/long-running-agents/#recovering-interrupted-llm-streams) for details. ## Concurrent fibers @@ -341,7 +341,7 @@ Run an async function while keeping the DO alive. Heartbeat starts before `fn` a ## Related -- [Long-running agents](/agents/concepts/long-running-agents/) — how fibers compose with schedules, plans, and async operations +- [Long-running agents](/agents/concepts/agentic-patterns/long-running-agents/) — how fibers compose with schedules, plans, and async operations - [Schedule tasks](/agents/runtime/execution/schedule-tasks/) — `keepAlive` details and the alarm system -- [Workflows](/agents/concepts/workflows/) — durable multi-step execution outside the agent +- [Workflows](/agents/runtime/execution/run-workflows/) — durable multi-step execution outside the agent - [Chat agents](/agents/communication-channels/chat/chat-agents/) — `chatRecovery` and `onChatRecovery` diff --git a/src/content/docs/agents/runtime/execution/run-workflows.mdx b/src/content/docs/agents/runtime/execution/run-workflows.mdx index f60ff102bbdc47b..374d0b2c751136a 100644 --- a/src/content/docs/agents/runtime/execution/run-workflows.mdx +++ b/src/content/docs/agents/runtime/execution/run-workflows.mdx @@ -12,6 +12,10 @@ import { TypeScriptExample, WranglerConfig, LinkCard } from "~/components"; Integrate [Cloudflare Workflows](/workflows/) with Agents for durable, multi-step background processing while Agents handle real-time communication. +## What are Workflows? + +[Cloudflare Workflows](/workflows/) provide durable, multi-step execution for tasks that need to survive failures, retry automatically, and wait for external events. When integrated with Agents, Workflows handle long-running background processing while Agents manage real-time communication. + :::note[Agents vs. Workflows] Agents excel at real-time communication and state management. Workflows excel at durable execution with automatic retries, failure recovery, and waiting for external events. @@ -20,6 +24,19 @@ Use Agents alone for chat, messaging, and quick API calls. Use Agent + Workflow ::: +Agents and Workflows have complementary strengths: + +| Capability | Agents | Workflows | +| --- | --- | --- | +| Execution model | Long-lived identity that wakes on events | Run to completion | +| Real-time communication | WebSockets, HTTP streaming | Not supported | +| State persistence | Built-in SQL database | Step-level persistence | +| Failure handling | Application-defined | Automatic retries and recovery | +| External events | Direct handling | Pause and wait for events | +| User interaction | Direct, such as chat or UI | Through Agent callbacks | + +Use Agents alone for chat, messaging applications, quick API calls, real-time collaboration, and short tasks. Use Agents with Workflows for data processing pipelines, report generation, human-in-the-loop approval flows, guaranteed delivery, and multi-step operations with retry requirements. + ## Quick start ### 1. Define a Workflow @@ -859,6 +876,6 @@ Workflows cannot open WebSocket connections directly. Use `broadcastToClients()` diff --git a/src/content/docs/agents/runtime/execution/sub-agents.mdx b/src/content/docs/agents/runtime/execution/sub-agents.mdx index e5f7733ecc59bad..9684833086475ad 100644 --- a/src/content/docs/agents/runtime/execution/sub-agents.mdx +++ b/src/content/docs/agents/runtime/execution/sub-agents.mdx @@ -332,6 +332,6 @@ For scheduled work, have the parent schedule the task and delegate to the sub-ag ## Related - [Think](/agents/harnesses/think/) — `chat()` method for streaming AI turns through sub-agents -- [Long-running agents](/agents/concepts/long-running-agents/) — sub-agent delegation in the context of multi-week agent lifetimes +- [Long-running agents](/agents/concepts/agentic-patterns/long-running-agents/) — sub-agent delegation in the context of multi-week agent lifetimes - [Callable methods](/agents/runtime/lifecycle/callable-methods/) — RPC via `@callable` and service bindings - [Chat agents](/agents/communication-channels/chat/chat-agents/) — `ToolLoopAgent` for in-process AI SDK sub-calls diff --git a/src/content/docs/agents/runtime/lifecycle/agent-class.mdx b/src/content/docs/agents/runtime/lifecycle/agent-class.mdx index a5c3e086aa105d7..fce4cf5067fc404 100644 --- a/src/content/docs/agents/runtime/lifecycle/agent-class.mdx +++ b/src/content/docs/agents/runtime/lifecycle/agent-class.mdx @@ -328,7 +328,7 @@ Schedules are stored in the `cf_agents_schedules` SQL table. Cron schedules auto ### `this.mcp` and friends -`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is properly documented in [MCP client API](/agents/tools/mcp/apis/client-api/). +`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is properly documented in [MCP client API](/agents/mcp/apis/client-api/). ```ts class MyAgent extends Agent { diff --git a/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx b/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx index 986b165c88fa0c4..94354fc7b3c09bd 100644 --- a/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx +++ b/src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx @@ -92,4 +92,4 @@ For a complete working example, refer to [x402-mcp on GitHub](https://github.com - [Pay from Agents SDK](/agents/tools/payments/x402/pay-from-agents-sdk/) — Build clients that pay for tools - [Charge for HTTP content](/agents/tools/payments/x402/charge-for-http-content/) — Gate HTTP endpoints -- [MCP server guide](/agents/tools/mcp/guides/remote-mcp-server/) — Build your first MCP server +- [MCP server guide](/agents/mcp/guides/remote-mcp-server/) — Build your first MCP server diff --git a/src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx b/src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx index 19978fce11bf3ea..aeb80aada22c437 100644 --- a/src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx +++ b/src/content/docs/agents/tools/payments/x402/pay-from-agents-sdk.mdx @@ -63,4 +63,4 @@ Use `base-sepolia` for testing. Get test USDC from the [Circle faucet](https://f - [Charge for MCP tools](/agents/tools/payments/x402/charge-for-mcp-tools/) — Build servers that charge for tools - [Pay from coding tools](/agents/tools/payments/x402/pay-with-tool-plugins/) — Add payments to OpenCode or Claude Code -- [Human-in-the-loop guide](/agents/concepts/human-in-the-loop/) — Implement approval workflows +- [Human-in-the-loop guide](/agents/concepts/agentic-patterns/human-in-the-loop/) — Implement approval workflows diff --git a/src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx b/src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx index cc11ec701ae5f21..8fec047db451918 100644 --- a/src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx +++ b/src/content/docs/agents/tools/payments/x402/pay-with-tool-plugins.mdx @@ -160,5 +160,5 @@ Register the hook in `.claude/settings.json`: - [Pay from Agents SDK](/agents/tools/payments/x402/pay-from-agents-sdk/) — Use the Agents SDK for more control - [Charge for HTTP content](/agents/tools/payments/x402/charge-for-http-content/) — Build the server side -- [Human-in-the-loop guide](/agents/concepts/human-in-the-loop/) — Implement approval workflows +- [Human-in-the-loop guide](/agents/concepts/agentic-patterns/human-in-the-loop/) — Implement approval workflows - [x402.org](https://x402.org) — Protocol specification diff --git a/src/content/docs/agents/tools/rag.mdx b/src/content/docs/agents/tools/rag.mdx index e300d86271ff953..a7607a9267e6615 100644 --- a/src/content/docs/agents/tools/rag.mdx +++ b/src/content/docs/agents/tools/rag.mdx @@ -1,5 +1,5 @@ --- -title: Retrieval Augmented Generation +title: Retrieval Augmented Generation (RAG) pcx_content_type: concept sidebar: order: 4 diff --git a/src/content/docs/agents/tools/sandbox.mdx b/src/content/docs/agents/tools/sandbox.mdx index 1d48ea847367509..68498ffee2e6450 100644 --- a/src/content/docs/agents/tools/sandbox.mdx +++ b/src/content/docs/agents/tools/sandbox.mdx @@ -22,7 +22,7 @@ Use Sandbox for agents that need to: - Run tests, linters, build tools, or data analysis scripts. - Maintain a workspace across multiple agent turns. -For lightweight JavaScript orchestration of MCP tools, use [Codemode](/agents/tools/mcp/protocol/codemode/). Codemode runs generated JavaScript in an isolated Worker sandbox and is optimized for typed tool composition. Sandbox is for full Linux execution environments. +For lightweight JavaScript orchestration of MCP tools, use [Codemode](/agents/mcp/protocol/codemode/). Codemode runs generated JavaScript in an isolated Worker sandbox and is optimized for typed tool composition. Sandbox is for full Linux execution environments. ## Basic pattern