{"id":33324,"date":"2026-05-01T21:28:26","date_gmt":"2026-05-01T19:28:26","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=33324"},"modified":"2026-07-30T08:01:20","modified_gmt":"2026-07-30T06:01:20","slug":"integrating-a2ui-with-ag-ui-in-angular","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/","title":{"rendered":"Integrating A2UI with AG-UI and CopilotKit in Angular"},"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-angular6a77463b05e8d\" 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-angular6a77463b05e8d\"\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 6 of 10 in the series <em>&ldquo;Agentic UI with 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\/ag-ui-in-practice-ag-ui-end-to-end-connecting-server-and-client\/\">AG-UI End to End: Connecting Server and Client<\/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\/\">Agentic UI with Angular, CopilotKit, and AG-UI<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/a2ui-how-ai-generates-dynamic-uis-at-runtime\/\">A2UI: How AI Generates Dynamic UIs at Runtime<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><span class=\"wp-post-series-box__current\">Integrating A2UI with AG-UI and CopilotKit in Angular<\/span><\/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\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/how-i-made-my-a2ui-dashboard-300-times-faster\/\">A2UI with a DSL: Controllable Dashboards Optimized for Performance<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/agentic-ui-with-mcp-apps-tool-results-as-interactive-widgets\/\">Agentic UI with MCP Apps: Tool Results as Interactive Widgets<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/mcp-apps-in-angular-with-copilotkit-rich-chat-interfaces-instead-of-text-responses\/\">MCP Apps in Angular with CopilotKit: Rich Chat Interfaces Instead of Text Responses<\/a><\/li>\n\t\t\t\t\t\t\t<\/ol>\n\t\t<\/div>\n\t<\/div>\n<p><em>From the first example to a real agent connection via AG-UI.<\/em><\/p>\n<p>In practice, A2UI messages don't come from static code, but from the responses of a real language model \u2013 and these first need to be transported from the agent to the client. AG-UI offers the right transport layer for this, but the official specification leaves open how A2UI is to be transmitted over it. This article shows a pragmatic solution and connects the client using the Angular integration of <a href=\"https:\/\/www.copilotkit.ai\">CopilotKit<\/a>.<\/p>\n<p>This second part of the three-part series picks up where the first part left off, where we still ran A2UI and the Angular renderer with hardcoded messages.<\/p>\n<p>\ud83d\udcc2 <a href=\"https:\/\/github.com\/angular-architects\/flights42\/tree\/copilotkit\">Source Code<\/a> (see branch <code>copilotkit<\/code>)<\/p>\n<h2>How Do You Transmit A2UI Messages over AG-UI?<\/h2>\n<p>So far we've looked at A2UI in isolation. In practice, however, the client communicates with the agent via HTTP calls. This is exactly where the protocol <a href=\"https:\/\/docs.ag-ui.com\/\">AG-UI<\/a>, mentioned in the previous article in this series, comes into play, standardizing the communication between frontend and agent.<\/p>\n<p>We can elegantly embed A2UI into this world by transmitting the A2UI messages inside an AG-UI message of type <code>ACTIVITY_SNAPSHOT<\/code>. The browser's developer tools show such a snapshot:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/ag-ui-trace.png\" alt=\"Browser devtools trace: A2UI operations createSurface, updateComponents, and updateDataModel embedded in an AG-UI ACTIVITY_SNAPSHOT\" \/><\/p>\n<p>In textual form, the snapshot looks like this:<\/p>\n<pre><code class=\"language-json\">{\n  &quot;type&quot;: &quot;ACTIVITY_SNAPSHOT&quot;,\n  &quot;messageId&quot;: &quot;srf-france-confirm&quot;,\n  &quot;activityType&quot;: &quot;a2ui-surface&quot;,\n  &quot;content&quot;: {\n    &quot;operations&quot;: [\n      {\n        &quot;version&quot;: &quot;v0.9&quot;,\n        &quot;createSurface&quot;: {\n          &quot;surfaceId&quot;: &quot;srf-france-confirm&quot;,\n          &quot;catalogId&quot;: &quot;https:\/\/a2ui.org\/specification\/v0_9\/basic_catalog.json&quot;\n        }\n      },\n      {\n        &quot;version&quot;: &quot;v0.9&quot;,\n        &quot;updateComponents&quot;: {\n          [...]\n        }\n      },\n      {\n        &quot;version&quot;: &quot;v0.9&quot;,\n        &quot;updateDataModel&quot;: {\n          &quot;surfaceId&quot;: &quot;srf-france-confirm&quot;,\n          &quot;path&quot;: &quot;\/dummy&quot;,\n          &quot;value&quot;: &quot;&quot;\n        }\n      }\n    ]\n  }\n}<\/code><\/pre>\n<p>Unfortunately, there is no official definition for how A2UI messages are to be transmitted over AG-UI. The solution shown here, an <code>ACTIVITY_SNAPSHOT<\/code> with a corresponding <code>activityType<\/code>, fits well with the semantics of AG-UI, however, and matches exactly the interpretation of <a href=\"https:\/\/www.copilotkit.ai\">CopilotKit<\/a>, whose Angular integration we also use on the client side below. Since the makers of CopilotKit are among the initiators of AG-UI, their interpretation of the standard naturally carries significant weight.<\/p>\n<p>As an alternative to an <code>ACTIVITY_SNAPSHOT<\/code>, a server-side tool call would also be conceivable, especially since AG-UI informs the client about tool calls and their results. In this case, however, the client and agent would have to agree on the name of such a tool that delivers A2UI as its result.<\/p>\n<h2>The Building Blocks: A2UI Renderer, CopilotKit, and a Server-Side Layer<\/h2>\n<p>For the implementation, we rely on two building blocks: the Angular renderer for A2UI discussed in the first part, and the Angular integration of CopilotKit (<code>@copilotkit\/angular<\/code>), which takes care of the AG-UI communication.<\/p>\n<p>The <a href=\"https:\/\/github.com\/angular-architects\/flights42\/blob\/copilotkit\/ai-server\/src\/mastra\/agents\/ticketing-agent.ts\">server-side agent<\/a>, which we won't look at in detail here, guides the language model via prompting to produce A2UI structures \u2013 not directly for the client, however, but as input for a server-side tool. This tool plays a central role: it validates the A2UI messages generated by the LLM and ensures that only consistent and executable structures are processed further.<\/p>\n<p>The prompt does not limit itself to the request to produce A2UI. In addition, it contains a few complete example surfaces the model can orient itself on, as well as a reference to the schema of the Basic Catalog, which the agent can retrieve when needed. This way, the model doesn't just know the rough structure of an A2UI response, but can also look up the details of the individual components.<\/p>\n<p>This is crucial, because LLMs are not guaranteed to deliver valid results. If validation fails, the feedback is sent back to the model so that it can try again. Only when a valid structure is available is it forwarded.<\/p>\n<p>The <a href=\"https:\/\/github.com\/angular-architects\/flights42\/blob\/copilotkit\/libs\/ag-ui-server\/extended-mastra-agent.ts\">server-side implementation<\/a> then transforms the validated A2UI messages into an <code>ACTIVITY_SNAPSHOT<\/code>. This becomes part of the regular AG-UI stream and can therefore be processed uniformly by CopilotKit on the client side.<\/p>\n<h2>Client-Side Integration with CopilotKit<\/h2>\n<p>On the client side, CopilotKit takes care of the connection to the agent. The central construct here is an agent store: a signal-based object that manages the chat history, executes client-side tool calls, and provides the received messages.<\/p>\n<p>This store is initialized in the function <code>injectTicketingAgentStore<\/code>. It registers the agent with its URL and the offered client tools, among other things, and then returns the store (slightly simplified):<\/p>\n<pre><code class=\"language-typescript\">import { inject } from &#039;@angular\/core&#039;;\nimport { injectAgentStore } from &#039;@copilotkit\/angular&#039;;\n\nimport { initAgentStore } from &#039;..\/..\/shared\/util-copilotkit\/init-agent-store&#039;;\n\n[...]\n\nexport const TICKETING_AGENT_ID = &#039;ticketingAgent&#039;;\n\nexport function injectTicketingAgentStore() {\n  initAgentStore({\n    agentId: TICKETING_AGENT_ID,\n    url: inject(ConfigService).agUiUrl,\n    useServerMemory: true,\n    frontendTools: [\n      findFlightsTool,\n      getLoadedFlightsTool,\n      toggleFlightSelectionTool,\n      getCurrentBasketTool,\n      displayFlightDetailTool,\n    ],\n  });\n\n  return injectAgentStore(TICKETING_AGENT_ID);\n}<\/code><\/pre>\n<p>The helper function <a href=\"https:\/\/github.com\/angular-architects\/flights42\/blob\/copilotkit\/src\/app\/domains\/shared\/util-copilotkit\/init-agent-store.ts\"><code>initAgentStore<\/code><\/a> belongs to a lean glue layer of the example project (folder <code>util-copilotkit<\/code>). For the given URL, it creates an agent derived from the AG-UI SDK's <code>HttpAgent<\/code>, registers it in the CopilotKit runtime as a so-called self-managed agent, and announces the passed client tools via CopilotKit's <code>registerFrontendTool<\/code>. The flag <code>useServerMemory<\/code> ensures that only new messages are transmitted to the server, because the server stores the history itself.<\/p>\n<p>The actual centerpiece, however, comes directly from CopilotKit: <code>injectAgentStore<\/code> provides the signal-based <code>AgentStore<\/code>, through which the application accesses the chat history (<code>messages<\/code>), the execution status (<code>isRunning<\/code>), and the agent itself.<\/p>\n<p>A service of the ticketing domain uses this function and additionally registers the event handlers for the A2UI surfaces:<\/p>\n<pre><code class=\"language-typescript\">import { inject, Injectable } from &#039;@angular\/core&#039;;\nimport { CopilotKit, injectInterrupt } from &#039;@copilotkit\/angular&#039;;\n\n[...]\n\n@Injectable({ providedIn: &#039;root&#039; })\nexport class TicketingChatService {\n  private readonly chatRegistry = inject(ChatRegistry);\n  private readonly copilotKit = inject(CopilotKit);\n  private readonly store = injectTicketingAgentStore();\n  [...]\n\n  constructor() {\n    registerHandlers({\n      checkIn: (action) =&gt; checkInAction(action),\n      submitAnswer: (action) =&gt;\n        submitAnswerAction(action, this.copilotKit, this.store),\n    });\n  }\n\n  public init(): void {\n    this.chatRegistry.setChat({\n      store: this.store,\n      [...],\n    });\n  }\n}<\/code><\/pre>\n<p>The helper function <code>registerHandlers<\/code> defines the event handlers and internally delegates to the <code>onAction<\/code> property of the A2UI renderer discussed in the first part. To send a message, the function <code>sendMessage<\/code> comes into play:<\/p>\n<pre><code class=\"language-typescript\">await sendMessage(\n  this.copilotKit,\n  this.store,\n  &#039;Did I book my flight to France?&#039;,\n);<\/code><\/pre>\n<p>It appends the message to the agent and triggers a new run via the CopilotKit runtime:<\/p>\n<pre><code class=\"language-typescript\">export async function sendMessage(\n  copilotKit: CopilotKit,\n  store: Signal&lt;AgentStore&gt;,\n  input: SendMessageInput,\n): Promise&lt;void&gt; {\n  const agent = store().agent;\n  agent.addMessage({ id: randomUUID(), role: &#039;user&#039;, content: input });\n  await copilotKit.core.runAgent({ agent });\n}<\/code><\/pre>\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<h3>Providing an A2UI Activity Renderer<\/h3>\n<p>For messages with the role <code>activity<\/code>, CopilotKit provides so-called activity renderers: Angular components that define, per <code>activityType<\/code>, how the content of a snapshot is to be displayed.<\/p>\n<p>CopilotKit does already come with its own A2UI support. At the time this article was written, however, it was built on a renderer for web components, so custom catalogs could only be implemented with web components. Instead, we want to plug in the Angular renderer from the first part \u2013 and that turns out to be pleasantly little work, since the actual rendering is still handled by that renderer.<\/p>\n<p>Let's start with the <code>content<\/code> of the <code>ACTIVITY_SNAPSHOT<\/code>. CopilotKit requires a schema for it and uses that to check the received content before it is displayed. We implement this schema here with <a href=\"https:\/\/zod.dev\/\">Zod<\/a> \u2013 in the case of A2UI, the content consists merely of the list of operations:<\/p>\n<pre><code class=\"language-typescript\">import { z } from &#039;zod&#039;;\n\nexport const a2uiSurfaceContentSchema = z.object({\n  operations: z.array(z.custom&lt;A2uiMessage&gt;()),\n});\n\nexport type A2uiSurfaceContent = z.infer&lt;typeof a2uiSurfaceContentSchema&gt;;<\/code><\/pre>\n<p>The schema is deliberately compact: it makes sure that <code>operations<\/code> is an array at all, but doesn't check the individual operations any further. The <code>z.custom&lt;A2uiMessage&gt;()<\/code> merely specifies the TypeScript type without validating at runtime. This satisfies CopilotKit's requirement for now; the content-level checking of the operations is handled by the A2UI renderer anyway. If you like, you can of course provide a stricter schema here.<\/p>\n<p>Conveniently, <code>z.infer<\/code> also gives us the matching TypeScript type <code>A2uiSurfaceContent<\/code>.<\/p>\n<p>With that, we can now implement the actual activity renderer. It passes the received A2UI operations to the <code>A2uiRendererService<\/code>, displays the resulting surface via the <code>SurfaceComponent<\/code> discussed in the first part, and manages its lifecycle (abridged):<\/p>\n<pre><code class=\"language-typescript\">import { A2uiRendererService, SurfaceComponent } from &#039;@a2ui\/angular\/v0_9&#039;;\n\n[...]\n\n@Component({\n  selector: &#039;app-a2ui-activity-renderer&#039;,\n  imports: [SurfaceComponent],\n  host: { class: &#039;a2ui-surface&#039; },\n  template: `\n    @let surface = surfaceId();\n    @if (surface) {\n      &lt;a2ui-v09-surface [surfaceId]=&quot;surface&quot; \/&gt;\n    }\n  `,\n})\nexport class A2uiActivityRenderer\n  implements ActivityRenderer&lt;A2uiSurfaceContent&gt;\n{\n  readonly activityType = input.required&lt;string&gt;();\n  readonly content = input.required&lt;A2uiSurfaceContent&gt;();\n  readonly message = input.required&lt;ActivityMessage&gt;();\n  readonly agent = input.required&lt;AbstractAgent | undefined&gt;();\n\n  private readonly renderer = inject(A2uiRendererService);\n  private renderedSurfaceId: string | null = null;\n\n  constructor() {\n    effect(() =&gt; {\n      const operations = this.content().operations;\n      const surfaceId = getRenderedSurfaceId(operations);\n      if (!surfaceId || surfaceId === this.renderedSurfaceId) {\n        return;\n      }\n\n      this.releaseSurface();\n      this.renderedSurfaceId = surfaceId;\n      this.renderer.processMessages(operations);\n    });\n\n    inject(DestroyRef).onDestroy(() =&gt; {\n      this.releaseSurface();\n    });\n  }\n\n  private releaseSurface(): void {\n    if (this.renderedSurfaceId) {\n      this.renderer.surfaceGroup.deleteSurface(this.renderedSurfaceId);\n      this.renderedSurfaceId = null;\n    }\n  }\n\n  protected readonly surfaceId = computed(() =&gt;\n    getRenderedSurfaceId(this.content().operations),\n  );\n}<\/code><\/pre>\n<p>So that CopilotKit can address this component as an activity renderer, it implements the interface <code>ActivityRenderer<\/code> coming from <code>@copilotkit\/angular<\/code>. The type parameter determines the structure of the snapshot content \u2013 in our case, <code>A2uiSurfaceContent<\/code>. The interface prescribes four inputs:<\/p>\n<ul>\n<li><code>content<\/code>: the checked content of the snapshot, in the case of A2UI the list of operations<\/li>\n<li><code>activityType<\/code>: the type of the activity, here <code>a2ui-surface<\/code><\/li>\n<li><code>message<\/code>: the entire AG-UI message<\/li>\n<li><code>agent<\/code>: the associated agent, through which follow-up actions can be triggered, for instance<\/li>\n<\/ul>\n<p>The <code>effect<\/code> in the constructor builds the surface exactly once: it derives the surface id from the operations via <code>getRenderedSurfaceId<\/code>, passes the operations on to <code>processMessages<\/code> the first time a new id appears, and skips further runs as long as the id stays the same.<\/p>\n<p>The component owns the surface's lifetime: when the component is destroyed \u2013 and when it switches to a different surface id \u2013 <code>releaseSurface<\/code> removes the surface from the renderer again via <code>surfaceGroup.deleteSurface<\/code>. The same surface id can therefore be built again later without the screen hosting the chat having to clean up \u2013 the surface's lifetime belongs to the renderer component.<\/p>\n<p>There is a good reason why the handoff to the renderer happens in the effect and not in the <code>computed<\/code>: <code>processMessages<\/code> updates the state of the renderer and writes signals itself while doing so. Such side effects have no place in a <code>computed<\/code>.<\/p>\n<p>That leaves the question of where the <code>surfaceId<\/code> for the <code>SurfaceComponent<\/code> comes from. The answer is provided by the helper function <code>getRenderedSurfaceId<\/code>: it searches the operations of the snapshot for the first surface id it can find:<\/p>\n<pre><code class=\"language-typescript\">function getRenderedSurfaceId(operations: A2uiMessage[]): string | null {\n  for (const operation of operations) {\n    if (&#039;createSurface&#039; in operation &amp;&amp; operation.createSurface.surfaceId) {\n      return operation.createSurface.surfaceId;\n    }\n\n    if (\n      &#039;updateComponents&#039; in operation &amp;&amp;\n      operation.updateComponents.surfaceId\n    ) {\n      return operation.updateComponents.surfaceId;\n    }\n\n    if (&#039;updateDataModel&#039; in operation &amp;&amp; operation.updateDataModel.surfaceId) {\n      return operation.updateDataModel.surfaceId;\n    }\n  }\n\n  return null;\n}<\/code><\/pre>\n<p>The reason for this search lies in the structure of the A2UI messages: the <code>surfaceId<\/code> isn't attached to the snapshot itself, but sits inside the individual operations \u2013 in a different place depending on the operation type. Usually, the very first operation of a snapshot already delivers a <code>createSurface<\/code> with the id we're looking for. When streaming step by step, however, a snapshot can also start with an <code>updateComponents<\/code> or <code>updateDataModel<\/code> for an already existing surface. If no id can be found at all, the function returns <code>null<\/code> and the template shows nothing for the time being.<\/p>\n<p>So that CopilotKit knows which component is responsible for which <code>activityType<\/code>, a configuration object comes into play:<\/p>\n<pre><code class=\"language-typescript\">export const a2uiActivityRendererConfig: RenderActivityMessageConfig&lt;A2uiSurfaceContent&gt; =\n  {\n    activityType: &#039;a2ui-surface&#039;,\n    content: a2uiSurfaceContentSchema,\n    component: A2uiActivityRenderer,\n  };<\/code><\/pre>\n<p>Besides mapping <code>activityType<\/code> and component, the Zod schema defined further above is used here. CopilotKit uses it to check the content of the snapshot before it reaches the component. The activity renderer therefore only ever receives content in the expected structure.<\/p>\n<h3>Displaying the Chat History and A2UI Surfaces in the Template<\/h3>\n<p>The entire chat history is located in the <code>messages<\/code> signal of the agent store. When CopilotKit receives an <code>ACTIVITY_SNAPSHOT<\/code>, it shows up there as a message with the role <code>activity<\/code> and the respective <code>activityType<\/code>. The template of the chat component iterates over the messages and distinguishes between text contents, tool calls, and activities (slightly simplified):<\/p>\n<pre><code class=\"language-html\">@for (message of messages(); track message.id) {\n\n  @if (message.content) {\n    &lt;div&gt;{{ message.content }}&lt;\/div&gt;\n  }\n\n  @for (toolCall of message.toolCalls; track toolCall.id) {\n    &lt;copilot-render-tool-calls\n      [message]=&quot;message&quot;\n      [messages]=&quot;messages()&quot;\n      [agentId]=&quot;agentId()&quot; \/&gt;\n  }\n\n  @if (message.role === &#039;activity&#039;) {\n    &lt;app-copilot-activity\n      [message]=&quot;message&quot;\n      [agentId]=&quot;agentId()&quot; \/&gt;\n  }\n\n}<\/code><\/pre>\n<p>Tool calls are handled by the component <code>copilot-render-tool-calls<\/code> that ships with CopilotKit. For activities, the example uses the small component <code>CopilotActivity<\/code>, which determines the matching activity renderer registered with CopilotKit based on the <code>activityType<\/code> and displays it.<\/p>\n<p>This is exactly where the circle closes back to A2UI: for the <code>activityType<\/code> <code>a2ui-surface<\/code>, CopilotKit finds the activity renderer shown above. It is made known via <code>provideCopilotKit<\/code> in the <code>appConfig<\/code>. That's also where we find the A2UI configuration known from the first part: the Basic Catalog at the token <code>A2UI_RENDERER_CONFIG<\/code>, the <code>A2uiRendererService<\/code>, as well as the Markdown renderer wired up via <code>provideMarkdownRenderer<\/code>:<\/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 { provideCopilotKit } from &#039;@copilotkit\/angular&#039;;\n\n[...]\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideCopilotKit({\n      renderActivityMessages: [a2uiActivityRendererConfig],\n    }),\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 only new thing here is the call to <code>provideCopilotKit<\/code>, which receives the <code>a2uiActivityRendererConfig<\/code> discussed above. For better readability, the example project bundles the providers for the catalog configuration and the <code>A2uiRendererService<\/code> into a dedicated function <code>provideA2uiCatalog<\/code>, which in the third part additionally accepts a custom catalog.<\/p>\n<p>This bridges the gap between agent and A2UI renderer: the agent delivers its A2UI messages via AG-UI <code>ACTIVITY_SNAPSHOT<\/code>s, CopilotKit receives them and provides them as activity messages in the agent store, and the registered activity renderer delegates the contained operations to the A2UI renderer. The individual components of our application don't need to know either the AG-UI or the A2UI protocol in detail.<\/p>\n<h2>Summary<\/h2>\n<p>In combination with AG-UI, A2UI fits seamlessly into an existing agentic architecture. AG-UI handles the structured communication between client and agent, while A2UI transports the UI-specific content. With CopilotKit's Angular integration, this combination can be used simply and idiomatically in Angular: the agent store provides the chat history as a signal, and activity renderers connect the received <code>ACTIVITY_SNAPSHOT<\/code>s with the A2UI renderer.<\/p>\n<p>A not-to-be-underestimated advantage of this architecture lies in the validation on the server side: it shields the client from inconsistent responses of the language model and ensures that only verified structures end up in the browser. The optional DSL variant additionally shows that the same mechanism can be balanced for differently powerful models.<\/p>\n<h2>The Next Step<\/h2>\n<p>So far we have relied on the Basic Catalog \u2013 the next part shows how to extend it with your own domain-specific components as a Custom Catalog.<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/custom-catalogs-in-a2ui-your-own-components-for-ai-generated-uis\/\" class=\"button\" style=\"text-decoration:none !important\"><strong>Next article \u2192<\/strong><\/a><\/p>\n<hr \/>\n<p><div style=\"\nmargin: 8px 0;\npadding: 22px;\nborder: 1px solid #e5e7eb;\nborder-radius: 14px;\nbackground: #f8fafc;\n\"><\/p>\n<h3 style=\"margin-top:0\">Interested in production-ready Agentic UI architectures?<\/h3>\n<p>In my workshop, we dig into AG-UI, A2UI, MCP Apps, HITL patterns, and modern Angular architectures for real-world agentic systems.<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/training\/agentic-ai-with-angular-architecture-patterns\/\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/sujet-workshop-en.png\" width=\"400\" alt=\"Workshop: Agentic AI with Angular \u2013 AG-UI, A2UI, MCP Apps & HITL patterns\" style=\"cursor:pointer !important\"><\/a><\/p>\n<p><a style=\"cursor:pointer !important\" href=\"https:\/\/www.angulararchitects.io\/en\/training\/agentic-ai-with-angular-architecture-patterns\/\">See all details \u2192<\/a>\n<\/div>\n<\/p>\n<h2>FAQ<\/h2>\n<h3>How do you transmit A2UI messages over AG-UI?<\/h3>\n<p>There is no official definition. In practice, it has proven effective to transport the A2UI operations inside an AG-UI message of type <code>ACTIVITY_SNAPSHOT<\/code> with its own <code>activityType<\/code> (for example, <code>a2ui-surface<\/code>). This variant fits the semantics of AG-UI and matches the interpretation of <a href=\"https:\/\/www.copilotkit.ai\">CopilotKit<\/a>.<\/p>\n<h3>Why is server-side validation part of this?<\/h3>\n<p>Language models are not guaranteed to deliver valid A2UI structures. Server-side validation \u2013 for example, in a tool \u2013 catches faulty responses, returns feedback to the model, and ensures that only consistent and executable structures reach the client.<\/p>\n<h3>What role does CopilotKit play on the client side?<\/h3>\n<p>CopilotKit's Angular integration (<code>@copilotkit\/angular<\/code>) manages the connection to the agent via AG-UI. The agent store provided by <code>injectAgentStore<\/code> delivers the chat history as a signal, executes client-side tools, and makes received <code>ACTIVITY_SNAPSHOT<\/code>s available as activity messages. Registered activity renderers \u2013 for A2UI, for instance \u2013 display their content. As a result, individual components don't need to know either AG-UI or A2UI in detail.<\/p>\n<h3>When does a custom DSL make sense instead of direct A2UI?<\/h3>\n<p>A reduced, application-specific DSL can make generation considerably more robust for weaker or more cost-effective models. The server centrally translates it into A2UI. The price for this is an additional transformation layer and somewhat less expressiveness compared to direct A2UI.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is post 6 of 10 in the series &ldquo;Agentic UI with Angular&rdquo; Understanding AG-UI: The Standard for Agentic User Interfaces AG-UI in Practice: The SDK for TypeScript AG-UI End to End: Connecting Server and Client Agentic UI with Angular, CopilotKit, and AG-UI A2UI: How AI Generates Dynamic UIs at Runtime Integrating A2UI with AG-UI [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":33326,"comment_status":"open","ping_status":"open","sticky":true,"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-33324","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>Integrating A2UI with AG-UI and CopilotKit in Angular - 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\/integrating-a2ui-with-ag-ui-in-angular\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Integrating A2UI with AG-UI and CopilotKit in Angular - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"This is post 6 of 10 in the series &ldquo;Agentic UI with Angular&rdquo; Understanding AG-UI: The Standard for Agentic User Interfaces AG-UI in Practice: The SDK for TypeScript AG-UI End to End: Connecting Server and Client Agentic UI with Angular, CopilotKit, and AG-UI A2UI: How AI Generates Dynamic UIs at Runtime Integrating A2UI with AG-UI [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-01T19:28:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-30T06:01:20+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=\"14 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\/integrating-a2ui-with-ag-ui-in-angular\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\"},\"author\":{\"name\":\"Manfred Steyer\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\"},\"headline\":\"Integrating A2UI with AG-UI and CopilotKit in Angular\",\"datePublished\":\"2026-05-01T19:28:26+00:00\",\"dateModified\":\"2026-07-30T06:01:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\"},\"wordCount\":2187,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\",\"name\":\"Integrating A2UI with AG-UI and CopilotKit in Angular - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg\",\"datePublished\":\"2026-05-01T19:28:26+00:00\",\"dateModified\":\"2026-07-30T06:01:20+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg\",\"width\":1000,\"height\":855},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Integrating A2UI with AG-UI and CopilotKit in Angular\"}]},{\"@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":"Integrating A2UI with AG-UI and CopilotKit in Angular - 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\/integrating-a2ui-with-ag-ui-in-angular\/","og_locale":"en_US","og_type":"article","og_title":"Integrating A2UI with AG-UI and CopilotKit in Angular - ANGULARarchitects","og_description":"This is post 6 of 10 in the series &ldquo;Agentic UI with Angular&rdquo; Understanding AG-UI: The Standard for Agentic User Interfaces AG-UI in Practice: The SDK for TypeScript AG-UI End to End: Connecting Server and Client Agentic UI with Angular, CopilotKit, and AG-UI A2UI: How AI Generates Dynamic UIs at Runtime Integrating A2UI with AG-UI [&hellip;]","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/","og_site_name":"ANGULARarchitects","article_published_time":"2026-05-01T19:28:26+00:00","article_modified_time":"2026-07-30T06:01:20+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":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/"},"author":{"name":"Manfred Steyer","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a"},"headline":"Integrating A2UI with AG-UI and CopilotKit in Angular","datePublished":"2026-05-01T19:28:26+00:00","dateModified":"2026-07-30T06:01:20+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/"},"wordCount":2187,"commentCount":0,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/","name":"Integrating A2UI with AG-UI and CopilotKit in Angular - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg","datePublished":"2026-05-01T19:28:26+00:00","dateModified":"2026-07-30T06:01:20+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/05\/shutterstock_293951399.jpg","width":1000,"height":855},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/integrating-a2ui-with-ag-ui-in-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Integrating A2UI with AG-UI and CopilotKit in Angular"}]},{"@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\/33324","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=33324"}],"version-history":[{"count":8,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/33324\/revisions"}],"predecessor-version":[{"id":34535,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/33324\/revisions\/34535"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/33326"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=33324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=33324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=33324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}