The Wall0:00
I asked my AI assistant to help me reserve a table at a popular restaurant. Here's what it gave me. Now, it's not wrong. The phone number is there. The hours areright. It even knows the walk-in oyster bar at the front.
The model did the real work. But look at the outcome. I have to do my research and work toward actually booking that table. Like, we've been here for a while. Now imagine if you were to build something like this for your customers.
What would you want it to do? Same answer, rendered like this instead. A date. A time. A couple of taps, and then you're done. The agentic product you're building already has all the tools to support your customer's needs.
Missing Layer0:53
The only thing that you need to focus on is the layer between the model and something that a human can interact with. That layer is what I'm going to talk about. The models and agents are here to stay, and we should learn how to make it friendly to the humans.
Hello, welcome to my talk. I'm Bala Ramdoss. I've been building customer-facing apps for over a decade, and the past 6 years I've spent building Amazon Lens. Amazon Lens is our suite of camera features powered by AI. It enables you to shop using images, screenshots, and barcodes to discover visually similar products.
If you have an Amazon app installed, I encourage you to try it. This talk comes from my experience building customer-facing products that are in millions and millions of mobile devices. Quick disclaimer before I go further: I am giving this talk on my own.
The opinions in this talk are mine and not my employer's.
Delivery Problems1:56
When you think of building UX for an agentic AI, obviously ChatGPT comes into mind. How do you draw these cards? How do you choose carousel versus list? How do you craft this so the human can understand and interact better?
When you attempt to build something like this, you run into a wall. There are problems that need to be solved from the very early stages of your system. Is that experience going to be snappy or slow? Do we get all the information at first, or one thing at a time?
And how do you scale this for mobile apps where versions and device capabilities are fragmented? If you notice, none of these problems are due to the model itself. The model does its job well. These are delivery problems, and they live in between the model output and what's on the screen.
Generative UI2:50
That is the layer that decides whether your product succeeds or not. So for this delivery problem, if you had asked me about this layer 2 years ago, I wouldn't have had a name for it. I had built a couple of AI features by then, and every single time I solved this part from scratch, a bespoke pattern shaped around whatever system I was in.
There was no shared vocabulary for any of it. What gets me is that this thing now has a name: generative UI. And there's an open spec for it, ATU UI from Google. Instead of the agent handing you a raw text or HTML, it describes the UI as data: a list of components, and the client renders them with its own native widgets.
A problem I used to solve alone is becoming something teams get to start from. And that's exactly what I'm excited to dig into. A normal API returns data, and the client decides how to draw it. Your model is good at tool use, coding, and even other complex tasks.
It can do UI too. And that is what the generative UI is about. It's a spectrum. Copilot kit, a company that does this primarily, lays out in 3 runs. At the bottom we have controlled. The model picks a prebuilt component, like a product card.
It never invents anything. In the middle, declarative. The model composes UI from a catalog: a date field, a time field, or a summit button. That's where A2 UI sits. And at the top, it's fully open-ended. The model generates a novel UI on the fly, like MCP apps.
The higher you go, the more your client has to trust whatever the model hands it. Most production mobile apps live in the bottom 2 runs, because that's where you stay safe. And that's what we'll focus on.
Mobile Reality5:07
Adding to the complexity of UX building, mobile apps play an important part. On the web, if a renderer breaks, you ship a fix and it's live in minutes. Mobile apps cannot do that. You're looking at hundreds of millions of installs, and you don't control when any of them update.
So when a client meets a content type it's never seen, it doesn't gracefully degrade. It crashes. And it keeps crashing for days or weeks in the hands of people who haven't updated. So one rule holds everything that follows for mobile clients.
You cannot meaningfully patch the client. How does this system look when you zoom out? Here's the whole simplified pipeline. Version-aware context space that feeds the model. Yes, that is context engineering. The model outputs typed UI intent that flows through a BFF, Backend-for-Frontend, and to a client renderer that draws it and falls back safely when it cannot.
Rendering Contract6:17
We'll break it into 3 patterns. Pattern 1: the rendering contract. Pattern 2: streaming. That's the flow in between them. Pattern 3: the BFF that sits in the middle. We'll take them one at a time, starting with the contract.
The contract is all about making the model be aware of what the client capabilities are. You ensure it stays true to the client that the model is trying to draw the UI for. What it ensures is that the onus is not on the client or the rendering layer to infer what to show by looking at the token output.
You also maintain a repository of version map with the capabilities. For example, you introduce a new flight card UI in version 2.0. Make sure to surface it to the model only from version 2.0 onwards when you build the context.
The takeaway here is that the model is going to choose the CX, and you provide theright information in its context. Let's take a look at this example. This is usually the hard part of building the system. This is the model-facing half of the contract.
You don't want the model to send back text. You want it to stream blocks of UI components. A conversation block for what it says in text, and a UI block for what it wants the client to render. The contract even encodes layout rules.
In this example, 1 to 3 flights, a swipable carousel, 4 or more, a vertical list. The model picks the intent. And notice what the model never does. It never invents a component. It chooses from a fixed menu that you provide to it.
Obviously, it won't be in the millions. It would be a handful. It turns out that it gets significantly harder as you scale your features to more surfaces. I'll let you think about how to engineer that context to make sure the model succeeds in picking one.
Streaming UI8:42
So that's the contract. Now let's move on to the streaming part. This was eye-opening to me when I first encountered it. Traditionally, apps make an API call and wait for something to happen. When LLMs are involved, this pattern becomes ineffective, as often the latency is higher due to the model themselves.
And on top of it, there are tons of additional checks to ensure safety and whatnot. And we also introduce a new layer that's going to be a little bit complex to do the dynamic UI. Streaming helps here by not making the client wait for the whole response.
It renders things in chunks at a time. Take a look at the illustrative example when you have to surface information one chunk at a time. First you show a skeleton, then partially fill it, then complete it. It may take 3 to 4 seconds to get there, but the wait is bearable.
That kind of changes what you measure for an app. You stop chasing the total latency, which we have done for over a decade. You start chasing time to first chunk, the first useful thing that your user sees. For this reason, the traditional loading spinner won't work for AI features.
Sometimes you have to get creative and design your feature around it. This may not work for all, but here's a product example. When you know it's going to take time to render something, keep the user engaged. The lens live allows the user to focus different things, tap on an object that they are interested in, while they wait for the results.
If you don't have the full screen in your control, you can show the thinking CX. But please use it sparingly. The overall AI users have moved out of the forgiving phase, and now they expect to know what is happening.
Now that you have a way to stream back different states, you know how to show what your agent is doing. Here's an example I copied from Gemini. When it starts to work on a task, it gives a glimpse into what the agent is doing.
Even though it takes 10 seconds, I'm okay if I know what's happening and be able to trust the agent's final output.
BFF Layer11:18
We have covered streaming. Let's move on to the final and most important part: your new BFF. Pattern 1 was about how UI gets picked. Pattern 2 was about how the chunks are delivered. Pattern 3 is all about how the chunks become meaningful UI elements.
This is the concept of server-driven UI, and it's a spectrum of server control. And the more the server controls, the more you build. The BFF is a subset of it and decides how to render. It owns the platform-specific rules, like Android versus iOS, that kind of stuff.
It also helps the client to make less decisions and draw what's handed to it. That's the whole idea.
The BFF doesn't just ship layout. It does a little more. In addition to the format and context, it does the hydration and adds actions. Every rendered element carries an action payload to handle what a tap does, what the deep link hit opens.
It could even name the impression metric to log. It carries this conversational context across turns so the next response knows what came before. And the good thing about this is that you can actually do this to your existing apps.
You can reuse the existing CX units you already have: the flight row, the product card, the components your app already shipped in production. You're not building a new agentic look into your app, and that's a good way to build for humans.
Same brand, same density, same familiar feel. It looks and feels native.
And that brings to our takeaways.
Takeaways13:14
One, the models are highly capable already. You feed a properly typed, versioned contract so it can pick and choose theright CX. Two, stream into typed components, not text. Let the user know what your agent is doing. Three, let the BFF absorb the model output so the client can stay dumb and safe.
No, none of these are about the model. The model was fine. This layer is what ships the product.
Bringing back to where we started, your agent output is not the CX you build on it. Thanks for watching. If you'd like to learn more or connect with me, here's the QR code.





