<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Weili Gao</title>
    <description>The latest articles on DEV Community by Weili Gao (@weiligao).</description>
    <link>https://dev.to/weiligao</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2831040%2F560444a6-37dd-4e26-a580-e9b98f6e0613.jpg</url>
      <title>DEV Community: Weili Gao</title>
      <link>https://dev.to/weiligao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/weiligao"/>
    <language>en</language>
    <item>
      <title>Generative UI - The Future of Human-AI Interaction</title>
      <dc:creator>Weili Gao</dc:creator>
      <pubDate>Thu, 28 May 2026 05:00:00 +0000</pubDate>
      <link>https://dev.to/ipt/generative-ui-the-future-of-human-ai-interaction-5eol</link>
      <guid>https://dev.to/ipt/generative-ui-the-future-of-human-ai-interaction-5eol</guid>
      <description>&lt;p&gt;This article was co-authored with my colleague&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__3956086"&gt;
    &lt;a href="/benjamin_buergisser" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3956086%2F9608b1cf-6ac5-40ae-9f91-1b6b6aac5329.jpg" alt="benjamin_buergisser image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/benjamin_buergisser"&gt;Benjamin Bürgisser&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/benjamin_buergisser"&gt;Hi, I'm Benjamin, a software engineer and IT architect based near Zurich, Switzerland. 
https://b-dimension.com/&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Generative UI is the next evolution of AI interaction, moving beyond text to create dynamic, agent-driven user interfaces. We explored three key patterns - Static (AG-UI), Declarative (A2UI), and Open-ended UI - and used the CopilotKit framework to build two demos: a Tic-Tac-Toe assistant, and a 2D RPG with LangGraph NPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Generative UI?
&lt;/h2&gt;

&lt;p&gt;Today’s AI agents primarily communicate through text. While revolutionary, this often forces humans to interact with a conversational interface, even for tasks that would be more efficient or intuitive within a traditional graphical user interface.&lt;/p&gt;

&lt;p&gt;Generative UI is the paradigm shift that enables AI agents to dynamically generate the UI elements required to complete a task. Instead of the user describing what they see, the agent reads the UI state directly and acts through it - clicking buttons, moving characters, proposing decisions.&lt;/p&gt;

&lt;p&gt;This shift blends the power of LLMs with familiar interactive components and is critical for implementing &lt;strong&gt;human-in-the-loop&lt;/strong&gt; workflows, where the agent can propose an action but requires human confirmation via an interactive UI before execution. This ensures control and a better user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Core Patterns of Generative UI
&lt;/h2&gt;

&lt;p&gt;Three core patterns exist for building Generative UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Generative UI&lt;/strong&gt; (&lt;a href="https://docs.ag-ui.com/introduction" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt;): the agent generates a command (like a function call) for a predefined frontend tool. The UI for that tool is already built and the agent simply triggers it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative Generative UI&lt;/strong&gt; (&lt;a href="https://a2ui.org/" rel="noopener noreferrer"&gt;A2UI&lt;/a&gt;, &lt;a href="https://docs.copilotkit.ai/learn/generative-ui/specs/open-json-ui" rel="noopener noreferrer"&gt;Open-JSON-UI&lt;/a&gt;): the agent generates a structured data format (like JSON) that describes the UI it wants to render (e.g., a form, a chart, or a list). The frontend then interprets this data and renders the elements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-ended Generative UI&lt;/strong&gt; (&lt;a href="https://modelcontextprotocol.io/extensions/apps/overview" rel="noopener noreferrer"&gt;MCP Apps&lt;/a&gt;): the agent generates raw, open-ended content, such as a block of custom HTML/CSS, which is then rendered directly in the UI. This is the most flexible approach but requires careful security measures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The different patterns are not mutually exclusive and can be complementary, e.g. both AG-UI and A2UI are used by the CopilotKit framework for implementing Generative UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Generative UI Frameworks
&lt;/h2&gt;

&lt;p&gt;The Generative UI approach is seeing rapid development from several frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.copilotkit.ai/" rel="noopener noreferrer"&gt;CopilotKit:&lt;/a&gt; a comprehensive framework for building agent-driven interfaces.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://trypillar.com/" rel="noopener noreferrer"&gt;Pillar:&lt;/a&gt; a simpler, headless framework focused on the core logic of agent tool routing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vercel.com/docs/ai-sdk" rel="noopener noreferrer"&gt;Vercel AI SDK:&lt;/a&gt; provides foundational support for streaming and model integrations, and is used as the runtime for CopilotKit's built-in agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducing CopilotKit
&lt;/h2&gt;

&lt;p&gt;We picked CopilotKit for building our two demos. It is an open-source (MIT) framework with 30k+ stars on GitHub that connects AI agents to your frontend. It is the company behind the AG-UI protocol.&lt;/p&gt;

&lt;p&gt;Its core concepts are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Readables:&lt;/strong&gt; expose app state to the agent (board positions, inventories, distances).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actions:&lt;/strong&gt; let the agent do things in your UI (make a move, take an item, spawn a reward).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat UI:&lt;/strong&gt; a themed sidebar or popup, with streaming and tool-call rendering, out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It supports React/Next.js and Angular, and works with agent backends like LangGraph or Microsoft Agent Framework. CopilotKit is partnered with Microsoft and Google for development on the AG-UI and A2UI protocols.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Demos
&lt;/h2&gt;

&lt;p&gt;To gain hands-on experience with Generative UI, we have developed two demos with CopilotKit: a Tic-Tac-Toe Assistant and a 2D RPG. They demonstrate how a front-end application can expose its state and functionality (tools) to an agent, allowing the agent to perform actions that are visible and interactive for the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo 1: Tic-Tac-Toe Assistant
&lt;/h3&gt;

&lt;p&gt;In our first demo we built a tic-tac-toe assistant that coaches the player at the immensely sophisticated game of tic-tac-toe. The agent can suggest moves (with an accept/reject dialog for human-in-the-loop), annotate the board with threats and opportunities, and render a custom "Coach Card" via generated HTML. The demo illustrates key Generative UI features by applying the patterns discussed above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI Move Suggestion (AG-UI + Human-in-the-Loop):&lt;/strong&gt; The agent calls a predefined &lt;code&gt;proposeNextMove&lt;/code&gt; tool, and the result is rendered as an "Accept / Reject" dialog (&lt;code&gt;renderAndWaitForResponse&lt;/code&gt;), requiring user confirmation before the move is made.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffv2xit7hzlgz66clpejq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffv2xit7hzlgz66clpejq.png" alt="AI move suggestions" width="799" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Board Annotations (AG-UI):&lt;/strong&gt; The agent calls an &lt;code&gt;analyzeBoard&lt;/code&gt; tool, which returns data used to render overlay symbols (threats, opportunities) directly onto the existing UI components (&lt;code&gt;Board.tsx&lt;/code&gt;/&lt;code&gt;Square.tsx&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08en7ql7nrug5oa1ma1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08en7ql7nrug5oa1ma1s.png" alt="Board annotations" width="799" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coach Card (Open-ended Generative UI):&lt;/strong&gt; The agent calls a &lt;code&gt;renderCoachCard&lt;/code&gt; tool, which generates fully custom HTML for the "Coach Card" component, rendered using a secure mechanism (&lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt; with DOMPurify).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3re6uoj0pntou7cohp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3re6uoj0pntou7cohp7.png" alt="Coach card" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shared Game State (Agent Context / Readable State):&lt;/strong&gt; The &lt;code&gt;useAgentContext&lt;/code&gt; hook is used to publish the current board state, player, and winner status, giving the agent a "readable state" of the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application is structured as a Next.js app, with all frontend logic (tools, UI) in the browser, communicating with the backend API route (&lt;code&gt;/api/copilotkit&lt;/code&gt;) which hosts the CopilotKit’s built-in agent and handles the model interaction (Azure OpenAI &lt;code&gt;gpt-5-mini&lt;/code&gt; via &lt;code&gt;@ai-sdk/azure&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This demo validated that exposing React state as readables and defining actions as tools is a clean, working pattern. The built-in agent made setup fast - readables and the instructions prop on the chat sidebar just worked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo 2: 2D RPG with LangGraph NPC
&lt;/h3&gt;

&lt;p&gt;For the second demo we wanted to go deeper: custom system prompts, richer agent logic, and a more complex scenario. We built a 2D RPG where the player walks around a medieval world collecting bananas, berries, and crystals. An NPC - powered by a LangGraph agent - acts as a quest giver. The agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See the game state: positions, inventories, objects on the map, player–NPC distance.&lt;/li&gt;
&lt;li&gt;Move the NPC through the world using A* pathfinding around obstacles.&lt;/li&gt;
&lt;li&gt;Give quests dynamically based on what's available on the map.
Take items from the player and reward coins for completed quests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this runs through CopilotKit's readables and actions - the agent never touches the DOM directly; it just reads structured state and calls named functions.&lt;/p&gt;

&lt;h4&gt;
  
  
  A Quest in Three Acts
&lt;/h4&gt;

&lt;p&gt;Nothing is scripted. The NPC reads the world state, decides what to ask for, and reacts to whatever the player actually does.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Act 1 - The Quest:&lt;/strong&gt; We ask the NPC for a quest. It inspects the map and decides: "Bring me 3 crystals." No quest table - just the agent reasoning over game state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddknwapnldfw6x7azphb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddknwapnldfw6x7azphb.png" alt="We ask the NPC for a quest. It inspects the map and decides: " width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Act 2 - The Pivot:&lt;/strong&gt; Instead of crystals, we grab a banana and call the NPC over. It pathfinds around the brick walls to reach us. In a scripted game, offering the wrong item would be a dead end. Here, the agent goes off-script and reluctantly accepts the banana anyway.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12ws1f32oneivhg44tm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12ws1f32oneivhg44tm9.png" alt="Instead of crystals, we grab a banana and call the NPC over. It pathfinds around the brick walls to reach us." width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Act 3 - The Reward:&lt;/strong&gt; We ask for a reward. The agent decides a single coin is fair, spawns it next to the NPC, and we pick it up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn3i7nsblm3b9ff4lf0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn3i7nsblm3b9ff4lf0q.png" alt="We ask for a reward. The agent decides a single coin is fair, spawns it next to the NPC, and we pick it up." width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The NPC feels more real because we can freely talk to it and it makes decisions on the fly - exactly the kind of dynamic interaction that's hard to achieve with traditional game scripting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Summary of what we've learned from the demos.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Worked Well
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The readable/action model is clean.&lt;/strong&gt; You declare what the agent can see (&lt;code&gt;useCopilotReadable&lt;/code&gt;) and do (&lt;code&gt;useCopilotAction&lt;/code&gt;) right next to the React components that own the state. CopilotKit handles serialization, transport, and tool binding. It feels like a natural extension of React's component model - state flows down, actions flow up, and the agent plugs into that loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The chat UI saved real time.&lt;/strong&gt; A themed sidebar with message history, streaming, and tool-call rendering - for free. We styled it to match our medieval parchment theme with a few CSS custom properties.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LangGraph integration is straightforward.&lt;/strong&gt; Define a graph, export it, point the Next.js route at the deployment URL. CopilotKit's state annotation passes readables and actions through cleanly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What Tripped Us Up
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Readables don't auto-inject with custom agents.&lt;/strong&gt; This was the biggest surprise. With the built-in agent (as in the Tic-Tac-Toe demo), &lt;code&gt;useCopilotReadable&lt;/code&gt; values appear in the model's context automatically. With a custom LangGraph agent, they arrive in &lt;code&gt;state.copilotkit.context&lt;/code&gt; - but you have to manually inject them into your system message. Actions worked immediately; readables silently did nothing until we traced the issue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;instructions&lt;/code&gt; prop is ignored with custom agents.&lt;/strong&gt; We set system instructions via CopilotSidebar's instructions field and they were silently dropped. This is a &lt;a href="https://github.com/CopilotKit/CopilotKit/issues/3037" rel="noopener noreferrer"&gt;known open CopilotKit issue&lt;/a&gt;. The workaround: define instructions in the agent's system message directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React's async batching vs. rapid tool calls&lt;/strong&gt; - when the agent fired two rapid calls (e.g. "take 1 berry" then "take 3 crystals"), the second read stale state because React hasn't re-rendered yet. We had to move from useEffect-based ref syncing to immediate ref updates - a useful pattern when bridging async agent actions with React state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Is Using CopilotKit Worth It?
&lt;/h3&gt;

&lt;p&gt;Couldn't we just append state to the user's message and define function-calling tools on our own? Yes - but CopilotKit gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A structured protocol&lt;/strong&gt; - AG-UI standardizes the agent–frontend connection so you don't reinvent the wheel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A full chat framework&lt;/strong&gt; - sidebar, streaming, theming. Non-trivial to build and maintain yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A component-level API&lt;/strong&gt; - readables and actions co-located with the components that own the state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a quick prototype, rolling your own is fine. For anything that will grow - multiple agents, generative UI patterns, shared state - a framework pays off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Generative UI represents an exciting step forward in AI-powered applications, moving beyond simple text generation to dynamic, context-aware user interaction. Our experience with CopilotKit in developing the two demos validated the effectiveness of the AG-UI and open-ended patterns for creating engaging and powerful Human-in-the-Loop experiences. As frameworks mature, Generative UI is poised to become a core part of how developers integrate AI into modern web applications.&lt;/p&gt;

</description>
      <category>ui</category>
      <category>frontend</category>
      <category>ai</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
