# Why Your AI UX Is Broken (and It's Not the Model's Fault) — Mike Christensen, Ably

AI Engineer · 2026-05-17

<https://aie.addtry.com/dc032fc8-3b6c-4a86-97d6-e5208484a595>

Mike Christensen, a staff engineer at Ably, argues that direct HTTP streaming (SSE) for AI chat apps breaks because it ties a response stream to a single connection, making resumability, multi-device sync, and live control mutually exclusive. He introduces durable sessions—a persistent, shared resource decoupled from any individual client or agent—built on Ably's Pub/Sub channels, which automatically handle reconnection, cross-tab synchronization, and concurrent multi-agent activity without complex plumbing. Christensen demonstrates with a live demo: a forced network disconnect that self-recovers, two tabs in perfect sync, two agents running in parallel without an orchestrator, and a handoff to a human agent who joins mid-conversation with full history. The episode concludes that treating the session as a durable shared resource unlocks resilient, multi-surface, and live-controllable AI experiences that the standard request-response model cannot support.

## Questions this episode answers

### Why is it impossible to support both cancel and resume in AI chat streams that use server-sent events?

Mike Christensen explains that SSE is a one-way pipe from server to client. To cancel a generation, the client can only close the connection. The agent then can't distinguish a cancel from a disconnect, so resume and cancel are mutually exclusive. Vercel's AI SDK explicitly documents that abort is incompatible with resume functionality for this reason.

[7:43](https://aie.addtry.com/dc032fc8-3b6c-4a86-97d6-e5208484a595?t=463000)

### How can I ensure that an AI chat session stays in sync across multiple browser tabs or devices, even during live streaming?

Christensen notes that with direct HTTP streaming, a response stream is tied to a single client connection, so other tabs or devices have no visibility of in-progress responses. By adopting a durable session layer—a shared resource that decouples agents from clients—any client can subscribe to the session and maintain a persistent connection, seeing all live activity and enabling full synchronization.

[9:13](https://aie.addtry.com/dc032fc8-3b6c-4a86-97d6-e5208484a595?t=553000)

### What is Ably's AI Transport SDK and how does it help build durable AI experiences?

Mike Christensen presents Ably AI Transport as a drop-in SDK that automatically plugs into any event stream format. It leverages Ably channels under the hood to provide a durable session layer, offering automatic resumability, multi-client fan-out, bidirectional control, event materialization, and additional tools like push notifications and shared data objects—all without custom plumbing.

[14:02](https://aie.addtry.com/dc032fc8-3b6c-4a86-97d6-e5208484a595?t=842000)

## Key moments

- **[0:00] Intro**
  - [0:43] Direct HTTP streaming with SSE ties a response stream to a single connection, limiting the richness of AI products.
  - [1:22] The paradigm of a single client, connection, and agent fundamentally limits quality of AI experiences.
  - [2:12] Ably processes traffic from 2 billion devices, 30 billion connections, and 2 trillion API operations monthly.
- **[3:03] Core Capabilities**
  - [3:03] Three capabilities separate fragile AI demos from great products: resilient delivery, continuity across surfaces, and live control.
- **[4:34] Limitations**
  - [4:34] Direct HTTP streaming couples everything to a single request; dropping the connection loses the in-progress response stream.
- **[5:21] Durable Sessions**
  - [5:21] A durable session is a shared, persistent medium between agent and client layers, enabling resilient, multi-device AI experiences.
- **[6:06] Resumability**
  - [6:06] Supporting resumable streams on direct HTTP requires storing events with sequence numbers and building custom resume handlers.
  - [7:43] "Abort is incompatible with resume functionality" — Vercel AI SDK documentation on SSE limitations.
- **[9:13] Multi-Device**
  - [9:13] Multi-device sync fails with direct HTTP streaming: a second tab or phone sees nothing of an in-progress response.
- **[11:12] Multi-Agent**
  - [12:33] Durable sessions let all agents write independently to the session, eliminating the need for an orchestrator to proxy updates.
- **[12:54] Ably Channels**
- **[14:12] AI Transport**
  - [14:12] Ably AI Transport SDK plugs into any event stream format and provides automatic resumability, multiplexing, and multi-client fan-out.
- **[15:34] Live Demo**
  - [15:34] Live demo shows multi-tab session sync, network disconnect recovery, and concurrent agents without additional coordination.
  - [17:38] Demo: Human support agent joins mid-session with full AI interaction history, enabling seamless handoff.

## Speakers

- **Mike Christensen** (guest)

## Topics

Agent Engineering, Multi-Agent Orchestration

## Mentioned

Ably (company), Ably AI Transport (product), Ably channels (product), Claude (product), Redis (product), TanStack AI (product), Vercel's AI SDK (product)

## Transcript

### Intro

**Mike Christensen** [0:15]
Okay, uh, I think time to start.

Can we start with a quick show of hands? So, who here's built some kind of AI chat app,right? Some kind of AI chat experience? Okay, but that was quick,right? Almost everybody in this room,right? So this is the case where you've got some kind of chat app, you've got an agent on the back end, the user sends a message to the agent, and the agent streams a response back live to the user as it's being generated,right?

And this is a fundamental building block of AI user experiences we see in every AI chat app today. And first, I want to have a quick look at how this is implemented today,right? So the default pattern is to use Direct HTTP streaming.

So the most popular frameworks, Vercel's AI SDK, TanStack AI, use SSE by default, server-sent events. And so concretely, what this means is the client makes a request to the agent, and it establishes a persistent point-to-point connection with the agent, and the agent then invokes the LLM and it obtains the stream of events, and it pipes those events back to the client over the connection as server-sent events,right?

And this is great,right? It's really easy to get something working. But this paradigm is kind of fundamentally oriented on the idea of a single client establishing a single connection to a single agent. And today I'm going to make the case that that fundamentally limits the quality and the richness of the experiences that we can build in our AI products.

So my name is Mike Christensen. I'm a staff engineer at Ably. Ably is a real-time messaging platform, and we build SDKs and APIs for any kind of live or interactive experience, and that includes AI experiences. And we operate our platform at real scale, so every month we handle traffic from more than 2 billion devices, we handle more than 30 billion monthly connections, we process more than 2 trillion API operations.

And over the past year, we've been speaking to engineering teams at more than 40 companies across 10 industries, and these are companies that are shipping AI agents, AI co-pilots, AI assistants in their products to millions of users. And these companies are really pushing the boundaries of what AI products can feel like,right?

Because when you add AI capabilities to your product, it fundamentally changes the user experience. So these companies are exploring these new interaction models, and they're working through the engineering challenges to deliver these experiences reliably in production. And so today I'm going to share what we've learned by talking to these companies.

I'm going to show you where the sort of Direct HTTP streaming model starts to break down and why. And I'm going to share with you the emerging patterns that we're seeing many engineering teams adopt to tackle these problems.

### Core Capabilities

**Mike Christensen** [3:03]
So we've found that companies shipping the best AI experiences really invest in three foundational capabilities. And we think that these capabilities really separate a fragile demo from a great AI product experience. So the first of these capabilities is resilient delivery.

This is about building streams that survive disconnections,right? Think about mobile. You know, you walk out of the house, your phone drops off the WiFi, connects to 5G, that severs the connection,right? Or maybe the user refreshes the page, or they navigate away from the app and they come back.

And what you want is that when the connection drops, clients are able to reconnect and pick up exactly from where they left off. The second core capability is about providing continuity across surfaces,right? So users move between surfaces all the time.

You know, you open the experience in a new tab, or you open it on your phone. And really, the conversation session should follow you around,right? No matter which device you're using, the session should be fully in sync, including any live activity.

And the third core capability is about live control,right? So the best AI products do better than a simple sequential request-response interaction pattern,right? They let you communicate with the agent while it's working. So think about how you use Claude code,right?

You know, you can see Claude's doing something, you might send a message, steer it, you send a follow-up, you ask it to do something else. And this requires visibility into what the agent is doing, and it allows clients it requires clients to be able to communicate with the agent while it's working.

### Limitations

**Mike Christensen** [4:34]
So why is this hard with a Direct HTTP streaming approach? The root cause is because everything is coupled to a single request,right? So if you think about that live response stream that you've got from an agent, the health of that stream is essentially tied to the health of that end client's connection,right?

So if that connection drops, the stream's gone. Another problem is with Direct HTTP streaming, that connection is now a private pipe between the client and the agent. So if you open the experience on another tab or on your phone, you have no visibility of that in-progress response.

And a third problem is because this stream,right, isn't a shared resource, other clients and other tabs, other devices can't communicate with the agent, can't reach the agent to interact with it, steer it, interrupt it. So a pattern we're seeing many companies adopt is to decouple the agent layer from the client layer.

### Durable Sessions

**Mike Christensen** [5:28]
And many teams are doing this with a concept called durable sessions. And so what this is, is a shared resource that sits between the agent layer and the client layer, and it's a persistent and stateful medium through which agents and clients can interact.

And as we'll see, this makes it much easier to build, uh, resilient streaming experiences, streaming experiences that work across multiple tabs or devices, and it allows any client to interact with agents as they work. So let's have a quick look at some examples now of where the sort of Direct HTTP streaming model breaks down, and we'll see how this durable sessions idea can help us.

### Resumability

**Mike Christensen** [6:06]
So let's look at how you might support resumable HTT uh, resumable streams with a Direct HTTP streaming approach. So in this scenario, the client sends a request to the agent, and the agent starts streaming the response, and then the client's connection drops halfway through,right?

And what we want is the client can re-establish the connection and can resume the stream from where it left off. So when the client's connection drops, the LLM is still working,right? It's still generating events, and these events have nowhere to go,right?

So how do you build resumes? Well, you need to store these events. You know, maybe you write them to an in-memory store, like Redis. You need to store them with sequence numbers so you know the order of these events.

And then you need some kind of explicit resume handler on your back end so that when the client tries to reconnect and resume, the resume handler is able to work out the exact set of events that the client missed and replay those back to the client in the correct order.

And so the problem here is that the stream is being explicitly managed by the agent, and so the agent has to do this for every reconnecting client because, you know, their connections drop at different times, and so each client has a different set of events that need to be replayed.

So you need to build all of this complex plumbing from scratch, you know, instead of focusing on building great agents. So how does durable sessions help? So by decoupling the agent from the client, uh, you allow the agent to write events directly to the session without thinking about the health of the end client's connection,right?

And simultaneously, you let clients connect directly to the session and replay events or resume the stream from the session without the agent having to worry about implementing that logic.

And there's an interesting problem here if you're using, um, SSE, server-sent events, um, in particular, because there's a conflict between supporting resumability and offering live control over agents to clients. And the reason for this is that SSE is one-way,right?

It's a strictly one-way pipe from the server to the client. So this comes up if you think about you want to add a stop button,right, into your into your experience. And the agent's streaming a response, you hit stop, and it cancels that in-progress generation.

And so the client has no upstream channel through which it can signal to the agent to cancel the generation,right? So the only thing it can do is close the connection. And that now creates ambiguity because what does the agent do,right?

Does it allow the LLM to keep generating events and buffer these events, assuming the client's going to try and reconnect and resume later? Or does it treat it as a cancellation, cancel the LLM, um, LLM, and stop burning through these expensive tokens?

And so, you know, resume and cancel are mutually exclusive when you're using, uh, SSE in particular, and there's some evidence for this. So Vercel's AI SDK, for example, uses SSE by default, and their doc state that Abort is incompatible with resume functionality, and it's for this reason.

So what do we need? We need bidirectional control,right? So maybe we can replace SSE, we can use something like WebSockets. And that then opens up the possibility for much richer interactions where clients can interact with agents. Okay, so we've swapped out our SSE, uh, transport for WebSockets.

### Multi-Device

**Mike Christensen** [9:19]
But as we'll see, a bidirectional transport doesn't solve all of our problems automatically. And these problems arise when you try to interact, uh, from multiple devices. So in this scenario, uh, you send a message to the agent, the agent is streaming a response, and then you open that same session in another tab,right?

And so the problem is, in this second tab, you have no visibility over that live response stream,right? Because the second tab isn't the one that sent the request that invoked the agent and established the connection. So the second tab doesn't see anything,right?

While that response is being streamed, there's no visibility. And then this presents a problem when we think about steering or controlling or guiding the agent, um, from multiple tabs or devices. So you send an, uh, a message to the agent.

In this case, you ask it, uh, book me a flight for next Tuesday. Agent's working on this in the background. You swap to your phone, uh, and you have the same problem here. The phone doesn't have visibility of the ongoing work of the agent.

But also, the phone has no upstream channel to the agent in order to send your follow-up request, which is, "Tuesday doesn't work for me. I need I need the flight on Wednesday." There's no way to reach the agent.

So a durable sessions layer, again, makes this easier, um, for us to support these multi-client experiences with live control. And we can do this because all clients can hold a persistent connection to the durable session that is always active,right?

So the connection's not just there when you invoke and initiate a request with an agent. You have constant visibility over the activity in the session through a continuously maintained connection. And clients can continue to resume,right, through the session.

But because the session is also a shared resource,right, and the agent has full visibility of the activity in the session as well, it means that any client can route to and interact with the agent. So you can do this from any tab or any device.

And so the final example I want to talk about is about concurrent activity,right? So this is about multi-agent architectures. We've got multiple agents that are participating in this session. And so the pattern we've got here is the, uh, uh, user is establishing making a request to, uh, an orchestrator agent.

### Multi-Agent

**Mike Christensen** [11:29]
And this orchestrator agent is then delegating subtasks to these specialized agents,right? And what we'd like to provide is full visibility of all the granular progress that these sub-agents are, are working on. Um, now, the problem here is the orchestrator is handling the user's request,right?

So we're kind of forcing the orchestrator to do two things. There's a dual-purpose role of both orchestrating the task and delegating tasks, and also proxying back these sort of granular updates from these sub-agents,right? So this is adding a lot of complexity to your architecture when really the orchestrator, uh, only cares about the final results from these sub-agents.

You shouldn't need to worry about relaying granular progress. So again, a durable sessions model makes this easier. Um, so in this model, all agents can write independently to the durable session layer,right? So now we don't have to flow all these granular updates through some centralized agent to pro-provide full visibility of all the activity in the session.

And clients only need to subscribe to a single entity as well,right? Um, they only subscribe to the session, and they have full visibility of activity from all these agents, however many there are working on the task, but also activity from other clients.

And this, uh, pattern can drastically simplify your architecture. So what we've described here sounds an awful like Pub/Sub,right? Um, and we can build durable sessions on top of, uh, Pub/Sub. So, um, at Ably, we have this concept called channels.

### Ably Channels

**Mike Christensen** [13:07]
And Ably channels let you communicate. Um, so publishers of messages and subscribers of messages can communicate with each other, but not directly. They do this through a shared resource, which we call a channel. Um, and this inherently decouples, uh, publishers and subscribers.

So it decouples clients and agents. And Ably channels have the kind of key properties that we would need to build a durable session layer. So they are independently addressable. So this means that any client or any agent can connect to this session just by specifying theright channel name.

They are persistent, which means the messages on the channel outlive the life cycle of any individual connection, any individual device, um, any individual agent. And they're fully resumable,right? So if you're a client that drops a connection, you can automatically reconnect to the channel, and all the events are, um, delivered exactly from where you left off.

So this is how, um, we found many of our customers have built these kind of resilient multi, uh, surface experiences. Um, to make building durable sessions even easier, we've, um, been working on, uh, something we call Ably AI Transport.

### AI Transport

**Mike Christensen** [14:18]
So this is a, a drop-in layer for building this durable session pattern. Um, and it's a new SDK, which automatically plugs into any event stream format, so whatever model provider or agent framework you're using. Um, and under the hood, it's using Ably channels to provide this sort of durable session layer, but with all the complexity of building a durable session, uh, handled for you out of the box.

So, um, the channel does some cool things as well,right? So it, like, materializes events in the channel. So you can stream in text chunks that are being generated from the LLM, and the channel automatically materializes that into the complete response.

They, uh, provide automatic resumability. They handle multiplexing, so you can have concurrent activity over the channel, and it's all fully multiplexed and handled. And it supports multi-client and multi-device fan-out with full bidirectional control. Uh, it also includes a suite of additional tools for building great AI user experiences.

So some of these are really important,right? Things like push notifications. If you've got an agent doing some background asynchronous work, you want to be notified when it's completed. There's also things like APIs for shared or subscribable data objects.

So if you've got agents and users kind of collaborating over some shared data in real time, this is possible. So to try and make some of this a little bit more concrete, um, I have a quick demo, um, to show you kind of what this looks like in practice.

### Live Demo

**Mike Christensen** [15:41]
So this is a, a classic kind of AI chat interface for a AI support chat for, uh, like an electronics shop,right? Um, so let's see if we can get the video.

Cool. So, you know, the usual kind of features exist in this kind of conversational interface. So here, you know, the agent's making a client-side call tool call to get the user's location. It's making a server-side tool call to show the user a list of stores in its location.

And we can see that this works across multiple tabs, um, out of the box. This is because it's powered by this durable session layer underneath. And it gives all clients a shared view of the session. Now, here we've got a streamed response, and we can refresh the page, and you can see it all remains absolutely automatically in sync.

There is no additional le agent logic to make this work,right? This just works from the client, um, consuming and subscribing from the channel. We can even kill the, uh, the network here. So we're forcing the client to disconnect and reconnect.

And everything just carries on automatically, um, without any additional complexity. We can also sort of interact for multiple tabs. So here in the second tab, we've kicked off a, a specialized sub-agent that's going to do some product research, and we've got some granular visibility.

We're going to cancel that from the first tab. So you can, from whichever client or device, you can cancel that, um, that work. Um, here we've kicked off a, uh, a product research task from one tab. Um, this specialized agent is writing these events directly.

There's no centralized orchestrator that's managing this. Um, here the user decided, okay, they're going to purchase a pair of headphones, but at the same time, they're going to cancel their existing order. So now you've got concurrent activity in the session.

Two agents working in the session simultaneously. It's fully synchronized without all this, uh, uh, additional coordination.

And now this is quite cool,right? So the, the user here isn't happy with the re the return pr uh, the refund price. So they want to speak to a human. So we can now add another participant into this session and transfer them over to a human agent.

So we're going to open up a, a support agent view over here. And we can see that this, uh, human support agent can has full visibility of all of the activity in that session. So they can see the full interaction history that the customer had with the AI agent, and they can then send a message to follow on as a human participant in that session to now communicate directly with that customer.

That's everything for today. Thank you very much. Please check out.

---

This library is powered by PodHood (https://podhood.com), the podcast website platform.
