<?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: Kenta Miyazaki / Takenoko</title>
    <description>The latest articles on DEV Community by Kenta Miyazaki / Takenoko (@k5arultkua4594).</description>
    <link>https://dev.to/k5arultkua4594</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%2F3766267%2F7a5c12ea-b87d-44a7-a44f-6fe0ff94948c.jpg</url>
      <title>DEV Community: Kenta Miyazaki / Takenoko</title>
      <link>https://dev.to/k5arultkua4594</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/k5arultkua4594"/>
    <language>en</language>
    <item>
      <title>A2UI x AG-UI: Building an AI Agent that Supports A2UI (v0.9) with CopilotKit and Strands Agents</title>
      <dc:creator>Kenta Miyazaki / Takenoko</dc:creator>
      <pubDate>Sun, 14 Jun 2026 13:37:46 +0000</pubDate>
      <link>https://dev.to/aws-builders/a2ui-x-ag-ui-building-an-ai-agent-that-supports-a2ui-v09-with-copilotkit-and-strands-agents-37k1</link>
      <guid>https://dev.to/aws-builders/a2ui-x-ag-ui-building-an-ai-agent-that-supports-a2ui-v09-with-copilotkit-and-strands-agents-37k1</guid>
      <description>&lt;p&gt;Original Articles:&lt;br&gt;
&lt;a href="https://qiita.com/Takenoko4594/items/dab65ccac9038fa2ad6b" rel="noopener noreferrer"&gt;https://qiita.com/Takenoko4594/items/dab65ccac9038fa2ad6b&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most chat-based AI agents can only reply with text. But what if your agent could search for tech meetups and show you the results as a list of clickable cards instead of a wall of text?&lt;/p&gt;

&lt;p&gt;That's exactly what I tried to build, using &lt;a href="https://github.com/copilotkit/copilotkit" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt; together with &lt;a href="https://github.com/strands-agents/harness-sdk/tree/main/strands-py" rel="noopener noreferrer"&gt;Strands Agents&lt;/a&gt;, AWS's SDK for building AI agents, and a spec called &lt;strong&gt;A2UI&lt;/strong&gt; that lets an agent control the frontend UI.&lt;/p&gt;

&lt;p&gt;If you've heard of "Generative UI" but aren't sure how an agent actually gets a button or a card to show up on screen, this post is for you.&lt;/p&gt;

&lt;p&gt;Code is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is A2UI?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A2UI is one spec for achieving Generative UI
&lt;/h3&gt;

&lt;p&gt;Generative UI is the idea that an AI can dynamically generate the user interface itself — not just text, but interactive buttons, cards, graphs, and more, depending on the situation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a2ui.org" rel="noopener noreferrer"&gt;A2UI&lt;/a&gt;, provided by Google, is one of the specs that makes this possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  A2UI represents UI as JSON
&lt;/h3&gt;

&lt;p&gt;So how does A2UI actually pull this off?&lt;/p&gt;

&lt;p&gt;Let's think about it from the perspective of the frontend and the AI agent.&lt;/p&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%2Fo2wg13fwedsrhk7ecahb.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%2Fo2wg13fwedsrhk7ecahb.png" alt=" " width="472" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A2UI defines the UI not as source code, but as &lt;strong&gt;JSON&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The AI agent receives a prompt from the frontend and returns the UI to display as JSON. The frontend then renders the screen based on that JSON.&lt;/p&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%2Fcjwmbxkbb1fn2owzs0f6.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%2Fcjwmbxkbb1fn2owzs0f6.png" alt=" " width="472" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The JSON is made up of three elements, combined together to build the UI:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Surface&lt;/td&gt;
&lt;td&gt;A canvas-like area where the UI is drawn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Component&lt;/td&gt;
&lt;td&gt;A UI element placed on the Surface — buttons, text fields, cards, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Model&lt;/td&gt;
&lt;td&gt;The state of the UI/application — e.g. the current value of a text field&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A2UI prepares a blank canvas called a Surface, places Components on it, and binds the data to display to those Components via the Data Model.&lt;/p&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%2Fzs04gcy13k81mdqaqem4.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%2Fzs04gcy13k81mdqaqem4.png" alt=" " width="574" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In other words, A2UI is a mechanism where the AI generates the JSON "blueprint" of the UI, and the frontend renders the UI from that blueprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI agent assembles the UI with 4 types of JSON messages
&lt;/h3&gt;

&lt;p&gt;So we've covered the three building blocks — Surface, Component, and Data Model. But how are they actually exchanged between the agent and the frontend?&lt;/p&gt;

&lt;p&gt;There are four types of JSON messages the AI agent sends to the frontend:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createSurface&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Instructs the frontend to create a Surface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;updateComponents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Instructs the frontend to add/update Components on a Surface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;updateDataModel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Instructs the frontend to update the Data Model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deleteSurface&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deletes a Surface along with its Components and Data Model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's how the flow looks once these messages start flowing and the UI gets built:&lt;/p&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%2F3fgcg0p4rx5cnnbdyzcp.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%2F3fgcg0p4rx5cnnbdyzcp.png" alt=" " width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The best way to get a feel for the actual JSON exchanged is to check out the sample here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a2ui.org/introduction/what-is-a2ui/#example" rel="noopener noreferrer"&gt;https://a2ui.org/introduction/what-is-a2ui/#example&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A2UI's message spec differs between v0.8 and v0.9. The example above assumes v0.9.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  UI patterns come from a catalog
&lt;/h3&gt;

&lt;p&gt;The UI components you specify in &lt;code&gt;updateComponents&lt;/code&gt; are managed as a &lt;strong&gt;catalog&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A catalog defines "which components are available" and "what properties each component has."&lt;/p&gt;

&lt;p&gt;There are broadly two types of catalogs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Catalog&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;basicCatalog (default catalog)&lt;/td&gt;
&lt;td&gt;The standard set of UI components provided by A2UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYOC (custom catalog)&lt;/td&gt;
&lt;td&gt;A custom catalog where you can register your own components&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://a2ui.org/concepts/catalogs/" rel="noopener noreferrer"&gt;https://a2ui.org/concepts/catalogs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can browse the components included in basicCatalog here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a2ui.org/reference/components/" rel="noopener noreferrer"&gt;https://a2ui.org/reference/components/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The frontend renders with an A2UI-specific renderer
&lt;/h3&gt;

&lt;p&gt;The components defined in the catalog get rendered on the frontend by a &lt;strong&gt;renderer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A renderer is a library that receives A2UI JSON messages and draws the UI on the frontend.&lt;/p&gt;

&lt;p&gt;A2UI officially provides renderers for multiple platforms, including React, Lit (Web Components), Angular, and Flutter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://a2ui.org/reference/renderers/" rel="noopener noreferrer"&gt;https://a2ui.org/reference/renderers/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Actions&lt;/strong&gt;&lt;br&gt;
A2UI also lets users interact with the UI it renders.&lt;br&gt;
&lt;a href="https://a2ui.org/concepts/actions/" rel="noopener noreferrer"&gt;https://a2ui.org/concepts/actions/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This opens the door to Human-in-the-Loop flows and more interactive Generative UI experiences. (I'll save that for a future post — it gets complicated fast.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The overall architecture
&lt;/h2&gt;

&lt;p&gt;Here's the overall architecture of the app I built.&lt;/p&gt;

&lt;p&gt;We've covered the basics of A2UI — from here, let's talk about what happens when you combine it with CopilotKit and Strands Agents.&lt;/p&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%2Fyl5lqdrh7q1qjx2lqndd.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%2Fyl5lqdrh7q1qjx2lqndd.png" alt=" " width="799" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I should mention that AWS already has a sample combining CopilotKit and Generative UI, which I used as a reference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aws-samples/sample-FAST-applications/tree/main/samples/copilotkit-generative-ui" rel="noopener noreferrer"&gt;https://github.com/aws-samples/sample-FAST-applications/tree/main/samples/copilotkit-generative-ui&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building an AG-UI-compliant agent with CopilotKit
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/copilotkit/copilotkit" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt; is a framework for building AI agents. With it, you can easily build agents that have a graphical UI powered by things like A2UI.&lt;/p&gt;

&lt;p&gt;CopilotKit talks to the agent through &lt;strong&gt;AG-UI&lt;/strong&gt;, an event-based protocol that connects the frontend and the AI agent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ag-ui-protocol/ag-ui" rel="noopener noreferrer"&gt;https://github.com/ag-ui-protocol/ag-ui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the frontend and the agent communicate through this shared protocol, the two stay loosely coupled — and you can swap out the agent implementation without touching the frontend.&lt;/p&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%2Fal3obrtkioqb344eh1y6.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%2Fal3obrtkioqb344eh1y6.png" alt=" " width="725" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Combining AG-UI with Strands Agents
&lt;/h3&gt;

&lt;p&gt;Strands Agents is AWS's SDK for building AI agents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/strands-agents/harness-sdk/tree/main/strands-py" rel="noopener noreferrer"&gt;https://github.com/strands-agents/harness-sdk/tree/main/strands-py&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn't support AG-UI out of the box, so you need to add a dedicated adapter to make it AG-UI compatible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ag-ui-protocol/ag-ui/tree/main/integrations/aws-strands/python/src/ag_ui_strands" rel="noopener noreferrer"&gt;https://github.com/ag-ui-protocol/ag-ui/tree/main/integrations/aws-strands/python/src/ag_ui_strands&lt;/a&gt;&lt;/p&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%2Fqjqsphamm0wzkqkhiy9f.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%2Fqjqsphamm0wzkqkhiy9f.png" alt=" " width="753" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding A2UI on top
&lt;/h3&gt;

&lt;p&gt;With the CopilotKit + AG-UI setup in place, you can layer A2UI on top.&lt;/p&gt;

&lt;p&gt;A2UI and AG-UI sit at different layers: AG-UI is the transport that carries events back and forth, while A2UI is the content of the messages carried over that transport.&lt;/p&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%2Fe6meigi9m9gkd46wfkux.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%2Fe6meigi9m9gkd46wfkux.png" alt=" " width="788" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this project, I deployed everything on AWS using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: AWS Amplify (Hosting)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: AWS Lambda + Amazon API Gateway (HTTPS)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Agent&lt;/strong&gt;: Amazon Bedrock AgentCore&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Now let's get into the actual code. The agent I built searches for tech meetups and proposes results visually as cards or lists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;First, the A2UI-related code on the frontend.&lt;/p&gt;

&lt;h4&gt;
  
  
  Defining schemas and components
&lt;/h4&gt;

&lt;p&gt;I defined components like &lt;code&gt;StudyEventCard&lt;/code&gt; (a meetup card) and &lt;code&gt;StudyEventList&lt;/code&gt; (a list view). Each component's schema is defined with Zod and consumed as props.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/lib/a2ui/StudyEventCard.tsx" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/lib/a2ui/StudyEventCard.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From these components and schemas, I built a catalog.&lt;/p&gt;

&lt;p&gt;Setting &lt;code&gt;includeBasicCatalog: true&lt;/code&gt; pulls in A2UI's default components (basicCatalog). Setting it to &lt;code&gt;false&lt;/code&gt; means only your custom components are available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/lib/a2ui/app-catalog.tsx#L18-L31" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/lib/a2ui/app-catalog.tsx#L18-L31&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, &lt;code&gt;createA2UIMessageRenderer&lt;/code&gt; builds a renderer from that catalog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/components/chat/index.tsx#L24-L27" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/components/chat/index.tsx#L24-L27&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I wire the catalog and renderer into CopilotKit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/components/chat/index.tsx#L68-L77" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/frontend/src/components/chat/index.tsx#L68-L77&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A2UI renderer for CopilotKit&lt;/strong&gt;&lt;br&gt;
A2UI publishes an official React renderer, but CopilotKit ships its own renderer customized for CopilotKit:&lt;br&gt;
&lt;a href="https://github.com/CopilotKit/CopilotKit/tree/v1.56.5/packages/a2ui-renderer" rel="noopener noreferrer"&gt;https://github.com/CopilotKit/CopilotKit/tree/v1.56.5/packages/a2ui-renderer&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;Next, the backend implementation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enabling A2UI in the CopilotKit Runtime
&lt;/h4&gt;

&lt;p&gt;Adding &lt;code&gt;a2ui: { injectA2UITool: true }&lt;/code&gt; to the CopilotRuntime config enables A2UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/dev/frontend/amplify/functions/copilotkit/handler.ts#L100-L112" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/dev/frontend/amplify/functions/copilotkit/handler.ts#L100-L112&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;injectA2UITool: true&lt;/code&gt;, &lt;code&gt;A2UIMiddleware&lt;/code&gt; from &lt;code&gt;@ag-ui/a2ui-middleware&lt;/code&gt; is automatically applied to request handling.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;A2UIMiddleware&lt;/code&gt; injects a &lt;code&gt;render_a2ui&lt;/code&gt; tool into the AI agent — but only if the frontend has registered a catalog. It also injects instructions into the &lt;code&gt;context&lt;/code&gt; so the agent knows how to use that tool.&lt;/p&gt;

&lt;p&gt;The catch: the Strands Agents AG-UI adapter (covered next) ignores &lt;code&gt;context&lt;/code&gt;, so I had to add those instructions myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Agent
&lt;/h3&gt;

&lt;p&gt;The agent combines Strands Agents with an AG-UI adapter.&lt;/p&gt;

&lt;h4&gt;
  
  
  Wrapping with the AG-UI adapter's &lt;code&gt;StrandsAgent&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Wrapping the agent in &lt;code&gt;StrandsAgent&lt;/code&gt; makes Strands Agents AG-UI compatible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/agent/strands_agents.py#L127-L132" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/agent/strands_agents.py#L127-L132&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I covered this part in more detail in a separate post (Japanese):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qiita.com/Takenoko4594/items/2e9e171d60854d77652f" rel="noopener noreferrer"&gt;https://qiita.com/Takenoko4594/items/2e9e171d60854d77652f&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Preparing an A2UI skill
&lt;/h4&gt;

&lt;p&gt;As mentioned above, &lt;code&gt;ag_ui_strands&lt;/code&gt; (the AG-UI adapter) currently can't automatically inject &lt;code&gt;context&lt;/code&gt; into the agent.&lt;/p&gt;

&lt;p&gt;As a workaround, I prepared a Strands Agents &lt;strong&gt;Skill&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://strandsagents.com/docs/user-guide/concepts/plugins/skills/" rel="noopener noreferrer"&gt;https://strandsagents.com/docs/user-guide/concepts/plugins/skills/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By writing how to use A2UI in this file, the agent loads it as part of its system prompt and learns how to call the &lt;code&gt;render_a2ui&lt;/code&gt; tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/agent/skills/a2ui-common/SKILL.md" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/agent/skills/a2ui-common/SKILL.md&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Loading the skill into the agent
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;AgentSkills&lt;/code&gt; plugin automatically merges any &lt;code&gt;SKILL.md&lt;/code&gt; files under a given directory into the agent's system prompt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/agent/strands_agents.py#L113-L125" rel="noopener noreferrer"&gt;https://github.com/KMiya84377/copilotkit_a2ui_strands_app/blob/main/agent/strands_agents.py#L113-L125&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with that, A2UI works on an agent built with CopilotKit and Strands Agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;This was my first dive into A2UI with CopilotKit and Strands Agents.&lt;/p&gt;

&lt;p&gt;A2UI gives the AI agent a lot of freedom to combine components however it wants — but it's also constrained to whatever components are predefined in the catalog.&lt;/p&gt;

&lt;p&gt;Honestly, this design balance is the hard part (frontend pros might disagree). If you make each component too big/general, the AI loses freedom and flexibility. If you split things into too many small components, the AI's choices become inconsistent run-to-run, and the user experience suffers.&lt;/p&gt;

&lt;p&gt;Getting this balance right depends not just on component granularity, but also on how smart the LLM is and how you prompt it — so I think it's something you tune iteratively by actually running it. (A2UI is tricky!)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>a2ui</category>
      <category>copilotkit</category>
    </item>
  </channel>
</rss>
