{"id":33321,"date":"2026-05-01T21:24:06","date_gmt":"2026-05-01T19:24:06","guid":{"rendered":"https:\/\/www.angulararchitects.io\/blog\/a2ui-wie-ki-dynamische-uis-zur-laufzeit-erzeugt\/"},"modified":"2026-05-01T22:45:25","modified_gmt":"2026-05-01T20:45:25","slug":"a2ui-how-ai-generates-dynamic-uis-at-runtime","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/","title":{"rendered":"A2UI: How AI Generates Dynamic UIs at Runtime"},"content":{"rendered":"<div class=\"wp-post-series-box series-agentic-angular wp-post-series-box--expandable\">\n\t\t\t<input id=\"collapsible-series-agentic-angular69f91e439fd2b\" class=\"wp-post-series-box__toggle_checkbox\" type=\"checkbox\">\n\t\n\t<label\n\t\tclass=\"wp-post-series-box__label\"\n\t\t\t\t\tfor=\"collapsible-series-agentic-angular69f91e439fd2b\"\n\t\t\ttabindex=\"0\"\n\t\t\t\t>\n\t\t<p class=\"wp-post-series-box__name wp-post-series-name\">\n\t\t\tThis is post 4 of 6 in the series <em>&ldquo;Agentic Angular&rdquo;<\/em>\t\t<\/p>\n\t\t\t<\/label>\n\n\t\t\t<div class=\"wp-post-series-box__posts\">\n\t\t\t<ol>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/understanding-ag-ui-the-standard-for-agentic-user-interfaces\/\">Understanding AG-UI: The Standard for Agentic User Interfaces<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/ag-ui-in-practice-the-sdk-for-typescript\/\">AG-UI in Practice: The SDK for TypeScript<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/implementing-ag-ui-with-angular\/\">Implementing AG-UI with Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><span class=\"wp-post-series-box__current\">A2UI: How AI Generates Dynamic UIs at Runtime<\/span><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\">Integrating A2UI with AG-UI in Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/custom-catalogs-in-a2ui-your-own-components-for-ai-generated-uis\/\">Custom Catalogs in A2UI: Your Own Components for AI-Generated UIs<\/a><\/li>\n\t\t\t\t\t\t\t<\/ol>\n\t\t<\/div>\n\t<\/div>\n<p><em>Language models no longer respond with text alone, but with entire UI structures.<\/em><\/p>\n<p>As soon as a language model is supposed to deliver more than a flowing text in response to a user request \u2013 say, displaying a list of flights, showing an input form, or rendering a chart \u2013 the integration between agent and frontend quickly becomes unwieldy. With <strong>A2UI<\/strong>, Google has introduced a standard that allows a language model to return components and their data instead of plain text \u2013 the frontend then takes care of the presentation.<\/p>\n<p>This first part of the three-part series introduces the A2UI protocol and uses an Angular demo to show how the bundled renderer displays the UI structures described by the model.<\/p>\n<p>\ud83d\udcc2 <a href=\"https:\/\/github.com\/angular-architects\/flights42\/tree\/a2ui-dynamic\">Source Code<\/a> (see branch <code>a2ui-dynamic<\/code>)<\/p>\n<h2>What is A2UI?<\/h2>\n<p><a href=\"https:\/\/a2ui.org\">A2UI<\/a> stands for <em>Agent-to-UI<\/em> and is a standard introduced by Google that closes the gap between an agent and a dynamically generated user interface. At its core, A2UI describes a vocabulary of predefined components along with their properties as well as a message format with which the agent tells the client which components to display and with which data to populate them.<\/p>\n<p>Instead of returning only text, the language model picks from a catalog of predefined components and supplies the corresponding data right along with them. The client only needs to render these components \u2013 and decides on the concrete appearance itself. The agent thus determines the &quot;what&quot;, the client decides the &quot;how&quot;. This way, the dynamically generated UI fragments don't feel like foreign bodies but blend into the application's existing design.<\/p>\n<p>In contrast to approaches like MCP Apps, where the agent ships complete components, A2UI's strict separation between structure and presentation also prevents the client from having to load foreign code at runtime.<\/p>\n<p>When this article was written, two versions of A2UI were available: the stable version 0.8 and the upcoming version 0.9 as a draft. In this article, I am already covering the latter.<\/p>\n<h2>A2UI in Action: Examples of Dynamically Generated UIs<\/h2>\n<p>We can see a dynamic A2UI response in the example of a demo application in which an agent issues a follow-up question in the form of an interactive form:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/solution.png\" alt=\"A2UI example: input form with a confirmation question generated by the agent in a flight booking application\" \/><\/p>\n<p>This makes it possible to extend the UI far beyond classic chat conversations. The LLM provides the components to display in the form of JSON. In this way, you can implement not only dialogs but also interactive lists, charts, or status displays. More examples of responses dynamically defined by the LLM:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/more-a2ui-01.png\" alt=\"A2UI response with booked flights as a table in a sidecar chat\" style=\"max-width: 400px\" \/><br \/>\n<img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/more-a2ui-02.png\" alt=\"A2UI response with an info card and chart for a selected flight, dynamically composed by the language model\" style=\"max-width: 400px\" \/><\/p>\n<h2>What Components Does the A2UI Basic Catalog Contain?<\/h2>\n<p>The central idea of A2UI is what is called a <em>component catalog<\/em>. Such a catalog describes a set of components that both the agent and the client know. The <em>Basic Catalog<\/em> defined by A2UI comprises a whole range of common UI building blocks, which can be divided into the following groups. The following overview is taken from the specification:<\/p>\n<style>\nth, td {\n  text-align: left;\n  vertical-align: top;\n  padding: 5px;\n}\nth, td {\n  border-bottom: 1px solid black;\n}\ntable {\n  margin-left: -10px;\n  margin-bottom: 20px;\n  border-collapse: collapse;\n}\n<\/style>\n<table>\n<thead>\n<tr>\n<th>Category<\/th>\n<th>Component<\/th>\n<th>Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Display<\/td>\n<td>Text<\/td>\n<td>Displays text. Supports basic Markdown.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Image<\/td>\n<td>Displays an image from a URL.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Icon<\/td>\n<td>Displays a system-provided icon from a predefined list.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Video<\/td>\n<td>Displays a video from a URL.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>AudioPlayer<\/td>\n<td>A player for audio content from a URL.<\/td>\n<\/tr>\n<tr>\n<td>Layout<\/td>\n<td>Row<\/td>\n<td>A horizontal layout container.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Column<\/td>\n<td>A vertical layout container.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>List<\/td>\n<td>A scrollable list of components.<\/td>\n<\/tr>\n<tr>\n<td>Container<\/td>\n<td>Card<\/td>\n<td>A card-style container.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Tabs<\/td>\n<td>A series of tabs, each with a title and a child component.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Divider<\/td>\n<td>A horizontal or vertical separator.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Modal<\/td>\n<td>A dialog that appears above the main content and is triggered by a button in the main content.<\/td>\n<\/tr>\n<tr>\n<td>Input<\/td>\n<td>Button<\/td>\n<td>A clickable button that triggers an action. Supports the variants &quot;primary&quot; and &quot;borderless&quot;.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>CheckBox<\/td>\n<td>A checkbox with a label and a boolean value.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>TextField<\/td>\n<td>A field for text input by the user.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>DateTimeInput<\/td>\n<td>An input for date and\/or time.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>ChoicePicker<\/td>\n<td>A component for selecting one or more options.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>Slider<\/td>\n<td>A slider for selecting a numeric value within a range.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>What Functions Does A2UI Provide?<\/h2>\n<p>In addition to the components themselves, A2UI also provides <em>functions<\/em> that the LLM can reference inside component definitions. This way, values that have to be determined or processed at runtime \u2013 for example, formatted numbers and dates \u2013 can be described declaratively without the language model having to execute the concrete logic itself. The Basic Catalog ships with a number of frequently needed functions such as <code>formatNumber<\/code> or <code>formatDate<\/code> out of the box. The following overview is also taken from the specification:<\/p>\n<table>\n<thead>\n<tr>\n<th>Category<\/th>\n<th>Function<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Validation<\/td>\n<td>required<\/td>\n<td>Checks that the value is not null, undefined, or empty.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>regex<\/td>\n<td>Checks that the value matches a regular expression.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>length<\/td>\n<td>Checks constraints on string length.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>numeric<\/td>\n<td>Checks constraints on numeric ranges.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>email<\/td>\n<td>Checks that the value is a valid email address.<\/td>\n<\/tr>\n<tr>\n<td>Formatting<\/td>\n<td>formatString<\/td>\n<td>Performs string interpolation on data model values and registered functions.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>formatNumber<\/td>\n<td>Formats a number with thousands separators and decimal places.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>formatCurrency<\/td>\n<td>Formats a number as a currency string.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>formatDate<\/td>\n<td>Formats a date\/time according to a pattern.<\/td>\n<\/tr>\n<tr>\n<td>Logical<\/td>\n<td>and<\/td>\n<td>Logical AND of a list of boolean values.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>or<\/td>\n<td>Logical OR of a list of boolean values.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>not<\/td>\n<td>Logical NOT of a boolean value.<\/td>\n<\/tr>\n<tr>\n<td>Other<\/td>\n<td>openUrl<\/td>\n<td>Opens a URL in a browser.<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>pluralize<\/td>\n<td>Selects a localized string based on a numeric count.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>How Do A2UI Messages and the Renderer Work?<\/h2>\n<p>The client displays the components via a <em>renderer<\/em>. The renderer is the instance that receives A2UI messages and produces the corresponding UI elements. For the messages exchanged between agent and client, A2UI defines four message types:<\/p>\n<table>\n<thead>\n<tr>\n<th>Message Type<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>createSurface<\/code><\/td>\n<td>Instructs the client to create a new surface.<\/td>\n<\/tr>\n<tr>\n<td><code>updateComponents<\/code><\/td>\n<td>Provides a list of component definitions that are added to or updated on a particular surface.<\/td>\n<\/tr>\n<tr>\n<td><code>updateDataModel<\/code><\/td>\n<td>Provides new data to be inserted into or replace the data model of a surface.<\/td>\n<\/tr>\n<tr>\n<td><code>deleteSurface<\/code><\/td>\n<td>Explicitly removes a surface and its contents from the UI.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>A <em>surface<\/em> is a logical display area in the client that the agent creates with <code>createSurface<\/code>, populates with <code>updateComponents<\/code>, and removes with <code>deleteSurface<\/code> when needed. A2UI manages the data used in the components in a separate data model per surface, which can be updated via <code>updateDataModel<\/code>. Components access values in this data model via data binding, so changes are automatically reflected in the display.<\/p>\n<h2>Integrating the A2UI Renderer in Angular<\/h2>\n<p>So that developers don't have to implement the protocol themselves, the A2UI project already provides renderers for various languages as well as adapters for various frameworks. The renderer for JavaScript can be found in the package <code>@a2ui\/web_core<\/code>, and the adapter for Angular built on top of it in <code>@a2ui\/angular<\/code>. As usual, both packages can be installed via npm:<\/p>\n<pre><code class=\"language-bash\">npm install @a2ui\/angular @a2ui\/web_core<\/code><\/pre>\n<h2>Example: A Passenger Card with A2UI in Angular<\/h2>\n<p>To make how A2UI works tangible, we start with a minimal example located <a href=\"https:\/\/github.com\/angular-architects\/flights42\/tree\/a2ui-dynamic\">in the example project<\/a> under <code>projects\/a2ui-demo<\/code>. Instead of a real language model, our example code initially produces the A2UI messages in a hardcoded fashion. This way we can fully focus on the data format and the client-side processing.<\/p>\n<p>The demo presents a card with a passenger's data along with a button that increases the earned bonus miles:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/passenger-card.png\" alt=\"A2UI demo in Angular: passenger card with name, bonus miles, and a button to increase the miles\" style=\"max-width: 400px\" \/><\/p>\n<p>The passenger card is defined with the function <code>createSimpleCard<\/code>, which produces an array of A2UI messages:<\/p>\n<pre><code class=\"language-typescript\">import type { A2uiMessage } from &#039;@a2ui\/web_core\/v0_9&#039;;\n\nexport function createSimpleCard(\n  surfaceId: string,\n  catalogId: string,\n  passenger: Passenger,\n): A2uiMessage[] {\n  return [\n    {\n      version: &#039;v0.9&#039;,\n      createSurface: {\n        surfaceId,\n        catalogId,\n      },\n    },\n    {\n      version: &#039;v0.9&#039;,\n      updateComponents: {\n        surfaceId,\n        components: [\n          { id: &#039;root&#039;, component: &#039;Card&#039;, child: &#039;content&#039; },\n          {\n            id: &#039;content&#039;,\n            component: &#039;Column&#039;,\n            children: [&#039;headline&#039;, &#039;name-row&#039;, &#039;miles-row&#039;, &#039;button&#039;],\n          },\n          {\n            id: &#039;headline&#039;,\n            component: &#039;Text&#039;,\n            text: &#039;Passenger&#039;,\n            variant: &#039;h2&#039;,\n          },\n          {\n            id: &#039;name-row&#039;,\n            component: &#039;Row&#039;,\n            children: [&#039;first-name&#039;, &#039;last-name&#039;],\n          },\n          {\n            id: &#039;first-name&#039;,\n            component: &#039;Text&#039;,\n            text: { path: &#039;\/passenger\/firstName&#039; },\n            variant: &#039;body&#039;,\n          },\n          {\n            id: &#039;last-name&#039;,\n            component: &#039;Text&#039;,\n            text: { path: &#039;\/passenger\/lastName&#039; },\n            variant: &#039;body&#039;,\n          },\n          {\n            id: &#039;miles-row&#039;,\n            component: &#039;Row&#039;,\n            children: [&#039;miles-label&#039;, &#039;miles-value&#039;],\n          },\n          {\n            id: &#039;miles-label&#039;,\n            component: &#039;Text&#039;,\n            text: &#039;Miles:&#039;,\n            variant: &#039;caption&#039;,\n          },\n          {\n            id: &#039;miles-value&#039;,\n            component: &#039;Text&#039;,\n            text: {\n              call: &#039;formatNumber&#039;,\n              args: {\n                value: { path: &#039;\/passenger\/bonusMiles&#039; },\n                decimals: 0,\n              },\n              returnType: &#039;string&#039;,\n            },\n            variant: &#039;body&#039;,\n          },\n          {\n            id: &#039;button&#039;,\n            component: &#039;Button&#039;,\n            child: &#039;button-label&#039;,\n            action: {\n              event: {\n                name: &#039;increaseMiles&#039;,\n                context: {\n                  passenger: { path: &#039;\/passenger&#039; },\n                },\n              },\n            },\n          },\n          {\n            id: &#039;button-label&#039;,\n            component: &#039;Text&#039;,\n            text: &#039;Increase Miles&#039;,\n            variant: &#039;body&#039;,\n          },\n        ],\n      },\n    },\n    {\n      version: &#039;v0.9&#039;,\n      updateDataModel: {\n        surfaceId,\n        path: &#039;\/passenger&#039;,\n        value: passenger,\n      },\n    },\n  ];\n}<\/code><\/pre>\n<p>The first message of type <code>createSurface<\/code> creates a new surface. The second message uses <code>updateComponents<\/code> to describe the components to be displayed: a <code>Card<\/code> as root, which contains a column with a heading, a row of names, a miles display, and a button. The individual outputs are bound, in part, to values in the data model via the <code>path<\/code> property. This data model is defined by the example in the third message, which has the type <code>updateDataModel<\/code>.<\/p>\n<p>Each component receives its own ID; nested components are referenced via <code>child<\/code> or <code>children<\/code> using these IDs. As a result of this kind of referencing, all nodes of the component tree are at the same level \u2013 A2UI deliberately avoids nesting in the JSON document, since it poses a challenge for language models.<\/p>\n<p>The button declaratively states that an event <code>increaseMiles<\/code> should be triggered on click, with the passenger data as context. Reacting to it is the client's responsibility.<\/p>\n<p>To display the described structure, the example uses the <code>A2uiRendererService<\/code> provided by the Angular adapter:<\/p>\n<pre><code class=\"language-typescript\">import {\n  A2UI_RENDERER_CONFIG,\n  A2uiRendererService,\n  SurfaceComponent,\n} from &#039;@a2ui\/angular\/v0_9&#039;;\n\n[...]\n\n@Component({\n  selector: &#039;app-root&#039;,\n  imports: [SurfaceComponent],\n  template: `\n    &lt;a2ui-v09-surface [surfaceId]=&quot;surfaceId&quot; \/&gt;\n  `,\n  styleUrl: &#039;.\/app.css&#039;,\n})\nexport class App {\n  private readonly renderer = inject(A2uiRendererService);\n  protected readonly config = inject(A2UI_RENDERER_CONFIG);\n  private readonly destroyRef = inject(DestroyRef);\n  protected readonly surfaceId = &#039;passenger-card-surface&#039;;\n\n  constructor() {\n    this.render();\n    this.registerHandler();\n  }\n\n  private render(): void {\n    const passenger: Passenger = {\n      id: 42,\n      firstName: &#039;Anna&#039;,\n      lastName: &#039;Miller&#039;,\n      bonusMiles: 1200,\n    };\n\n    const messages = createSimpleCard(\n      this.surfaceId,\n      this.config.catalogs[0].id,\n      passenger,\n    );\n\n    this.renderer.processMessages(messages);\n  }\n\n  private registerHandler(): void {\n    [...]\n  }\n}<\/code><\/pre>\n<p>The <code>A2uiRendererService<\/code> processes the received A2UI messages with its <code>processMessages<\/code> method. The actual display is handled by the <code>SurfaceComponent<\/code>, which takes the desired <code>surfaceId<\/code>.<\/p>\n<p><div style=\"\nmargin: 8px 0;\npadding: 22px;\nborder: 1px solid #e5e7eb;\nborder-radius: 14px;\nbackground: #f8fafc;\n\">NOTE<\/p>\n<h3 style=\"margin-top:0\">New: Agentic UI with Angular<\/h3>\n<p>If you don\u2019t just want to integrate A2UI but embed it into a scalable architecture:<br \/>\nIn my book Agentic UI with Angular, I cover the underlying patterns and trade-offs in depth.<\/p>\n<p><a href=\"https:\/\/agentic-angular.com\/\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/04\/cover.png\" width=\"400\" alt=\"Cover of the eBook Agentic UI with Angular\" style=\"cursor:pointer !important\"><\/a><\/p>\n<p><a style=\"cursor:pointer !important\" href=\"https:\/\/agentic-angular.com\/\">Learn more about the eBook \u2192<\/a>\n<\/div>\n<\/p>\n<p>Since the button in our card triggers an <code>increaseMiles<\/code> event, the example registers a handler for it on the <code>onAction<\/code> property:<\/p>\n<pre><code class=\"language-typescript\">import type { A2uiClientAction } from &#039;@a2ui\/web_core\/v0_9&#039;;\n\n[...]\n\nprivate registerHandler(): void {\n  const subscription = this.renderer.surfaceGroup.onAction.subscribe(\n    (action: A2uiClientAction) =&gt; {\n      console.log(&#039;[A2UI Event]&#039;, action);\n\n      if (action.name !== &#039;increaseMiles&#039;) {\n        return;\n      }\n\n      const passenger = action.context[&#039;passenger&#039;] as Passenger;\n\n      this.renderer.processMessages([\n        {\n          version: &#039;v0.9&#039;,\n          updateDataModel: {\n            surfaceId: this.surfaceId,\n            path: &#039;\/passenger&#039;,\n            value: {\n              ...passenger,\n              bonusMiles: passenger.bonusMiles + 300,\n            },\n          },\n        },\n      ]);\n    },\n  );\n\n  this.destroyRef.onDestroy(() =&gt; {\n    subscription.unsubscribe();\n  });\n}<\/code><\/pre>\n<p>The handler for <code>increaseMiles<\/code> takes the passenger data passed in the context and updates the bonus miles in the bound data model with an <code>updateDataModel<\/code> message. The renderer notices the change in the data model and automatically updates the bound displays.<\/p>\n<p>Unfortunately, <code>onAction<\/code> is not an RxJS observable. That is why the unsubscribe here is performed programmatically via a <code>DestroyRef<\/code>.<\/p>\n<p>So that the renderer knows which catalogs are available and how any Markdown content is to be converted, the Angular adapter expects a central configuration provided via providers:<\/p>\n<pre><code class=\"language-typescript\">import {\n  A2UI_RENDERER_CONFIG,\n  A2uiRendererService,\n  BasicCatalog,\n  provideMarkdownRenderer,\n} from &#039;@a2ui\/angular\/v0_9&#039;;\nimport {\n  ApplicationConfig,\n  inject,\n  provideBrowserGlobalErrorListeners,\n} from &#039;@angular\/core&#039;;\nimport { marked } from &#039;marked&#039;;\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideBrowserGlobalErrorListeners(),\n    {\n      provide: A2UI_RENDERER_CONFIG,\n      useFactory: () =&gt; ({\n        catalogs: [inject(BasicCatalog)],\n      }),\n    },\n    provideMarkdownRenderer(async (markdown) =&gt;\n      marked.parse(String(markdown ?? &#039;&#039;)),\n    ),\n    A2uiRendererService,\n  ],\n};<\/code><\/pre>\n<p>The shown example configures the Basic Catalog shipped with A2UI, which the adapter exposes as a service. To do so, the catalog is registered for the <code>A2UI_RENDERER_CONFIG<\/code> token. In addition, the implementation of the Basic Catalog provided by the A2UI team requires a Markdown renderer, which has to be wired up via <code>provideMarkdownRenderer<\/code>.<\/p>\n<h2>Summary<\/h2>\n<p>A2UI enables a language model to respond to requests not only with text but with concrete UI structures that the client can render directly at runtime. The model combines existing components into appropriate interfaces \u2013 tailored to the respective context and the current interaction.<\/p>\n<p>A key advantage lies in the separation of structure and presentation: the client decides on the concrete appearance and does not execute any foreign code. As a result, the dynamically generated UI fragments stay consistent with the application and don't feel like foreign bodies.<\/p>\n<h2>The Next Step<\/h2>\n<p>We now know how to render A2UI in Angular. The next part shows how to have the UI generated by an agent and wired up via AG-UI.<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\" class=\"button\" style=\"text-decoration:none !important\"><strong>Next article \u2192<\/strong><\/a><\/p>\n<hr \/>\n<h2>FAQ<\/h2>\n<h3>What is A2UI?<\/h3>\n<p>A2UI (<em>Agent-to-UI<\/em>) is a standard introduced by Google that closes the gap between an agent and a dynamically generated user interface. It defines a vocabulary of predefined components along with their properties as well as a message format with which an agent tells the client which components to display and with which data to populate them.<\/p>\n<h3>What is A2UI used for?<\/h3>\n<p>A2UI enables language models to respond to requests not only with text but also with concrete UI structures such as lists, cards, charts, or input forms. This makes it possible to extend agentic sidecars and assistants far beyond classic chat conversations, without the client having to load any foreign code at runtime.<\/p>\n<h3>What is the Basic Catalog in A2UI?<\/h3>\n<p>The Basic Catalog is the collection of common UI building blocks shipped with A2UI. It includes display, layout, container, and input components such as <code>Text<\/code>, <code>Image<\/code>, <code>Card<\/code>, <code>Column<\/code>, <code>Row<\/code>, <code>Button<\/code>, or <code>TextField<\/code>, and additionally provides standard functions like <code>formatNumber<\/code>, <code>formatDate<\/code>, or typical validations.<\/p>\n<h3>How do you integrate A2UI into an Angular application?<\/h3>\n<p>For Angular, A2UI provides the package <code>@a2ui\/angular<\/code>, which is built on top of the JavaScript renderer <code>@a2ui\/web_core<\/code>. The <code>A2uiRendererService<\/code> processes the A2UI messages, the <code>SurfaceComponent<\/code> displays the rendered surface, and the desired catalog is registered via the <code>A2UI_RENDERER_CONFIG<\/code> token.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is post 4 of 6 in the series &ldquo;Agentic Angular&rdquo; Understanding AG-UI: The Standard for Agentic User Interfaces AG-UI in Practice: The SDK for TypeScript Implementing AG-UI with Angular A2UI: How AI Generates Dynamic UIs at Runtime Integrating A2UI with AG-UI in Angular Custom Catalogs in A2UI: Your Own Components for AI-Generated UIs Language [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":33318,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[18],"tags":[],"class_list":["post-33321","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","post_series-agentic-angular"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A2UI: How AI Generates Dynamic UIs at Runtime - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A2UI: How AI Generates Dynamic UIs at Runtime - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"This is post 4 of 6 in the series &ldquo;Agentic Angular&rdquo; Understanding AG-UI: The Standard for Agentic User Interfaces AG-UI in Practice: The SDK for TypeScript Implementing AG-UI with Angular A2UI: How AI Generates Dynamic UIs at Runtime Integrating A2UI with AG-UI in Angular Custom Catalogs in A2UI: Your Own Components for AI-Generated UIs Language [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-01T19:24:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-01T20:45:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/series-1024x536.png\" \/>\n<meta name=\"author\" content=\"Manfred Steyer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/series-1024x536.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\"},\"author\":{\"name\":\"Manfred Steyer\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\"},\"headline\":\"A2UI: How AI Generates Dynamic UIs at Runtime\",\"datePublished\":\"2026-05-01T19:24:06+00:00\",\"dateModified\":\"2026-05-01T20:45:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\"},\"wordCount\":1920,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\",\"name\":\"A2UI: How AI Generates Dynamic UIs at Runtime - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg\",\"datePublished\":\"2026-05-01T19:24:06+00:00\",\"dateModified\":\"2026-05-01T20:45:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg\",\"width\":1000,\"height\":667},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A2UI: How AI Generates Dynamic UIs at Runtime\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\",\"name\":\"Manfred Steyer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A2UI: How AI Generates Dynamic UIs at Runtime - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/","og_locale":"en_US","og_type":"article","og_title":"A2UI: How AI Generates Dynamic UIs at Runtime - ANGULARarchitects","og_description":"This is post 4 of 6 in the series &ldquo;Agentic Angular&rdquo; Understanding AG-UI: The Standard for Agentic User Interfaces AG-UI in Practice: The SDK for TypeScript Implementing AG-UI with Angular A2UI: How AI Generates Dynamic UIs at Runtime Integrating A2UI with AG-UI in Angular Custom Catalogs in A2UI: Your Own Components for AI-Generated UIs Language [&hellip;]","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/","og_site_name":"ANGULARarchitects","article_published_time":"2026-05-01T19:24:06+00:00","article_modified_time":"2026-05-01T20:45:25+00:00","og_image":[{"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/series-1024x536.png","type":"","width":"","height":""}],"author":"Manfred Steyer","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/series-1024x536.png","twitter_misc":{"Written by":"Manfred Steyer","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/"},"author":{"name":"Manfred Steyer","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a"},"headline":"A2UI: How AI Generates Dynamic UIs at Runtime","datePublished":"2026-05-01T19:24:06+00:00","dateModified":"2026-05-01T20:45:25+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/"},"wordCount":1920,"commentCount":0,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/","name":"A2UI: How AI Generates Dynamic UIs at Runtime - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg","datePublished":"2026-05-01T19:24:06+00:00","dateModified":"2026-05-01T20:45:25+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_2381734561.jpg","width":1000,"height":667},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"A2UI: How AI Generates Dynamic UIs at Runtime"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a","name":"Manfred Steyer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","caption":"Manfred Steyer"}}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/33321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=33321"}],"version-history":[{"count":4,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/33321\/revisions"}],"predecessor-version":[{"id":33380,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/33321\/revisions\/33380"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/33318"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=33321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=33321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=33321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}