splash image

June 10, 2025Ask AI

Multi-user AI chat with RedwoodSDK RSC and Cloudflare agents

At a recent event in London, I was excited to learn how RedwoodSDK makes it easy to run React Server Components (RSC) on Cloudflare.

I decided to learn more about this by building multi-user AI chat - 4 times.

  1. RSC Chat - sync via RedwoodSDK realtime websockets
  2. Agent Chat - sync via Cloudflare Agents websockets
  3. Agent SDK Chat - uses AIChatAgent with the useAgentChat hook
  4. TinyBase Chat - sync via TinyBase websockets

Deployed at https://agents-chat.jldec.workers.dev/

The primary challenge with this use-case is live-streaming AI responses back to multiple connected clients at the same time. Details in the code on GitHub.

First impressions

RedwoodSK realtime RSC

Cloudflare Agents websockets

Cloudflare Agents SDK with AIChatAgent

TinyBase sync

What's next?

I'd ❤️ to see if there are ways to combine the best of all the approaches above.

And I believe multi-user AI chat could be the beginning of something much bigger.

  • Agents and humans organize into specialized groups.
  • Agents with tools do much of the work.
  • Persisted conversations become the new basis for organizational memory.

Bright futures ahead 🚀

debug

user: anonymous

{
  "path": "/blog/multi-user-ai-chat-with-redwoodsdk-rsc-and-cloudflare-agents",
  "attrs": {
    "title": "Multi-user AI chat with RedwoodSDK RSC and Cloudflare agents",
    "date": "2025-06-10",
    "splash": {
      "image": "/images/flowzer.webp"
    },
    "layout": "BlogPostLayout"
  },
  "md": "# Multi-user AI chat with RedwoodSDK RSC and Cloudflare agents\n\nAt a recent event in London, I was excited to learn how [RedwoodSDK](https://rwsdk.com/) makes it easy to run React Server Components (RSC) on Cloudflare.\n\nI decided to learn more about this by building multi-user AI chat - 4 times.\n\n> 1. [RSC Chat](https://agents-chat.jldec.workers.dev/chat-rsc) - sync via [RedwoodSDK realtime websockets](https://docs.rwsdk.com/core/realtime/)\n> 2. [Agent Chat](https://agents-chat.jldec.workers.dev/chat-agent) - sync via [Cloudflare Agents websockets](https://developers.cloudflare.com/agents/api-reference/websockets/)\n> 3. [Agent SDK Chat](https://agents-chat.jldec.workers.dev/chat-agent-sdk) - uses [AIChatAgent](https://developers.cloudflare.com/agents/api-reference/agents-api/#aichatagent) with the [useAgentChat](https://developers.cloudflare.com/agents/api-reference/agents-api/#chat-agent-react-api) hook\n> 3. [TinyBase Chat](https://agents-chat.jldec.workers.dev/chat-tinybase) - sync via [TinyBase websockets](https://tinybase.org/)\n\nDeployed at https://agents-chat.jldec.workers.dev/\n\nThe primary challenge with this use-case is live-streaming AI responses back to multiple connected clients at the same time. Details in the code on [GitHub](https://github.com/jldec/agents-chat).\n\n## First impressions\n- RedwoodSDK (RSCs on Cloudflare workers) is very interesting. The upcoming addition of client-side routing (SPA mode) together with Cloudflare cache integration for SSR, would make this stack hard to beat.\n- All four implementations rely on Cloudflare [durable objects](https://developers.cloudflare.com/durable-objects/#what-are-durable-objects) with websockets. This is great for runtime performance and makes deployment easy. There are no containers to build or servers to manage.\n- React is great for a use case like this where updates are coming from both the server and the client. All four implementations use the same [MessageList](https://github.com/jldec/agents-chat/blob/main/src/app/shared/MessageList.tsx) component.\n\n#### RedwoodSK realtime RSC\n- Server components are a [succinct](https://github.com/jldec/agents-chat/blob/main/src/app/chat-rsc/ChatRSC.tsx) way to pre-populate JSX with data and then keep clients up to date.\n- It's nice to be able to use async data loading inline on the server. Rendering with data from remote storage during streaming can be slower unless data is memoized.\n- The scope of the RSC update payload sent to clients may become a problem during streaming, e.g. for pages with a lot of data. Discussion about this in the [rwsdk discord](https://discord.com/channels/679514959968993311/1374715298636238968/1376288266789064734).\n- Server functions are convenient, but should be used with care since they generate HTTP APIs which is where auth/authz is commonly required. See [this take](https://www.youtube.com/watch?v=yD-KK4hiULU) from Jack Herrington for more.\n\n#### Cloudflare Agents websockets\n- Using Cloudflare Agents websockets means that we have [full control](https://github.com/jldec/agents-chat/blob/main/src/app/chat-agent/WebsocketAgent.ts) over the payloads. This allows for nice optimizations e.g. to send partial data during streaming.\n- Rendering chat history on the client via fetch or via websocket makes the initial UX a little janky. (TODO: investigate pre-rendering)\n- Agents can combine both the chat storage and the websocket in one durable object. (TODO)\n\n#### Cloudflare Agents SDK with AIChatAgent\n- [AIChatAgent](https://developers.cloudflare.com/agents/api-reference/agents-api/#aichatagent) handles multi-user real-time message sync over websockets. This simplifies the implementation. (_still investigating [in #23](https://github.com/jldec/agents-chat/issues/23) why not all clients see the streaming_)\n- The SDK abstracts tool calling and supports different LLMs with Vercel's [AI SDK](https://ai-sdk.dev/docs/introduction).\n- [useAgentChat](https://developers.cloudflare.com/agents/api-reference/agents-api/#chat-agent-react-api) manages chat interactions with react.\n- With React Server Components (RSC), this component needs to be wrapped to prevent server-side rendering since the hook makes assumptions about running in a browser environment. More details in [this PR](https://github.com/jldec/agents-chat/pull/20).\n\n#### TinyBase sync\n- Synchronization is happening between memory and persistence on every node, and between nodes.\n- This improves the UX once data is persisted on the client and makes it easy to use React hooks listening for database updates.\n- The APIs for [persistence and synchronization](https://github.com/jldec/agents-chat/blob/main/src/app/chat-tinybase/store.ts#L14-L38) feel like they could be consolidated.\n- Since store operations run on the client we have to be extra careful with validation e.g. to deal with  clients being compromised.\n- Localstorage persistence has an [issue](https://github.com/jldec/agents-chat/issues/13) with multiple tabs.\n\n## What's next?\n\nI'd ❤️ to see if there are ways to combine the best of all the approaches above.\n\nAnd I believe multi-user AI chat could be the beginning of something much bigger.\n\n> - Agents and humans organize into specialized groups.\n> - Agents with tools do much of the work.\n> - Persisted conversations become the new basis for organizational memory.\n\nBright futures ahead 🚀",
  "html": "<h1>Multi-user AI chat with RedwoodSDK RSC and Cloudflare agents</h1>\n<p>At a recent event in London, I was excited to learn how <a href=\"https://rwsdk.com/\">RedwoodSDK</a> makes it easy to run React Server Components (RSC) on Cloudflare.</p>\n<p>I decided to learn more about this by building multi-user AI chat - 4 times.</p>\n<blockquote>\n<ol>\n<li><a href=\"https://agents-chat.jldec.workers.dev/chat-rsc\">RSC Chat</a> - sync via <a href=\"https://docs.rwsdk.com/core/realtime/\">RedwoodSDK realtime websockets</a></li>\n<li><a href=\"https://agents-chat.jldec.workers.dev/chat-agent\">Agent Chat</a> - sync via <a href=\"https://developers.cloudflare.com/agents/api-reference/websockets/\">Cloudflare Agents websockets</a></li>\n<li><a href=\"https://agents-chat.jldec.workers.dev/chat-agent-sdk\">Agent SDK Chat</a> - uses <a href=\"https://developers.cloudflare.com/agents/api-reference/agents-api/#aichatagent\">AIChatAgent</a> with the <a href=\"https://developers.cloudflare.com/agents/api-reference/agents-api/#chat-agent-react-api\">useAgentChat</a> hook</li>\n<li><a href=\"https://agents-chat.jldec.workers.dev/chat-tinybase\">TinyBase Chat</a> - sync via <a href=\"https://tinybase.org/\">TinyBase websockets</a></li>\n</ol>\n</blockquote>\n<p>Deployed at <a href=\"https://agents-chat.jldec.workers.dev/\">https://agents-chat.jldec.workers.dev/</a></p>\n<p>The primary challenge with this use-case is live-streaming AI responses back to multiple connected clients at the same time. Details in the code on <a href=\"https://github.com/jldec/agents-chat\">GitHub</a>.</p>\n<h2>First impressions</h2>\n<ul>\n<li>RedwoodSDK (RSCs on Cloudflare workers) is very interesting. The upcoming addition of client-side routing (SPA mode) together with Cloudflare cache integration for SSR, would make this stack hard to beat.</li>\n<li>All four implementations rely on Cloudflare <a href=\"https://developers.cloudflare.com/durable-objects/#what-are-durable-objects\">durable objects</a> with websockets. This is great for runtime performance and makes deployment easy. There are no containers to build or servers to manage.</li>\n<li>React is great for a use case like this where updates are coming from both the server and the client. All four implementations use the same <a href=\"https://github.com/jldec/agents-chat/blob/main/src/app/shared/MessageList.tsx\">MessageList</a> component.</li>\n</ul>\n<h4>RedwoodSK realtime RSC</h4>\n<ul>\n<li>Server components are a <a href=\"https://github.com/jldec/agents-chat/blob/main/src/app/chat-rsc/ChatRSC.tsx\">succinct</a> way to pre-populate JSX with data and then keep clients up to date.</li>\n<li>It's nice to be able to use async data loading inline on the server. Rendering with data from remote storage during streaming can be slower unless data is memoized.</li>\n<li>The scope of the RSC update payload sent to clients may become a problem during streaming, e.g. for pages with a lot of data. Discussion about this in the <a href=\"https://discord.com/channels/679514959968993311/1374715298636238968/1376288266789064734\">rwsdk discord</a>.</li>\n<li>Server functions are convenient, but should be used with care since they generate HTTP APIs which is where auth/authz is commonly required. See <a href=\"https://www.youtube.com/watch?v=yD-KK4hiULU\">this take</a> from Jack Herrington for more.</li>\n</ul>\n<h4>Cloudflare Agents websockets</h4>\n<ul>\n<li>Using Cloudflare Agents websockets means that we have <a href=\"https://github.com/jldec/agents-chat/blob/main/src/app/chat-agent/WebsocketAgent.ts\">full control</a> over the payloads. This allows for nice optimizations e.g. to send partial data during streaming.</li>\n<li>Rendering chat history on the client via fetch or via websocket makes the initial UX a little janky. (TODO: investigate pre-rendering)</li>\n<li>Agents can combine both the chat storage and the websocket in one durable object. (TODO)</li>\n</ul>\n<h4>Cloudflare Agents SDK with AIChatAgent</h4>\n<ul>\n<li><a href=\"https://developers.cloudflare.com/agents/api-reference/agents-api/#aichatagent\">AIChatAgent</a> handles multi-user real-time message sync over websockets. This simplifies the implementation. (<em>still investigating <a href=\"https://github.com/jldec/agents-chat/issues/23\">in #23</a> why not all clients see the streaming</em>)</li>\n<li>The SDK abstracts tool calling and supports different LLMs with Vercel's <a href=\"https://ai-sdk.dev/docs/introduction\">AI SDK</a>.</li>\n<li><a href=\"https://developers.cloudflare.com/agents/api-reference/agents-api/#chat-agent-react-api\">useAgentChat</a> manages chat interactions with react.</li>\n<li>With React Server Components (RSC), this component needs to be wrapped to prevent server-side rendering since the hook makes assumptions about running in a browser environment. More details in <a href=\"https://github.com/jldec/agents-chat/pull/20\">this PR</a>.</li>\n</ul>\n<h4>TinyBase sync</h4>\n<ul>\n<li>Synchronization is happening between memory and persistence on every node, and between nodes.</li>\n<li>This improves the UX once data is persisted on the client and makes it easy to use React hooks listening for database updates.</li>\n<li>The APIs for <a href=\"https://github.com/jldec/agents-chat/blob/main/src/app/chat-tinybase/store.ts#L14-L38\">persistence and synchronization</a> feel like they could be consolidated.</li>\n<li>Since store operations run on the client we have to be extra careful with validation e.g. to deal with  clients being compromised.</li>\n<li>Localstorage persistence has an <a href=\"https://github.com/jldec/agents-chat/issues/13\">issue</a> with multiple tabs.</li>\n</ul>\n<h2>What's next?</h2>\n<p>I'd ❤️ to see if there are ways to combine the best of all the approaches above.</p>\n<p>And I believe multi-user AI chat could be the beginning of something much bigger.</p>\n<blockquote>\n<ul>\n<li>Agents and humans organize into specialized groups.</li>\n<li>Agents with tools do much of the work.</li>\n<li>Persisted conversations become the new basis for organizational memory.</li>\n</ul>\n</blockquote>\n<p>Bright futures ahead 🚀</p>\n"
}