Agents via AG-UI und CopilotKit in Angular-Anwendungen nutzen
AG-UI definiert die Kommunikation zwischen Frontend und Agent. Mit @copilotkit/angular steht mittlerweile auch eine Angular-Integration bereit. Sie stammt vom Team hinter CopilotKit, aus dessen Umfeld auch AG-UI selbst hervorgegangen ist.
Genau hier setzt dieser Artikel an. Während der vorige Teil mit dem fertigen Chat-Control rasch zu einem Ergebnis kam, nutzen wir ab hier den flexiblen Headless-Mode von CopilotKit: Er liefert Zustand und Verhalten des Chats, überlässt die Darstellung aber vollständig der Anwendung. Auf dieser Basis zeigt der Artikel, wie sich Agents mit CopilotKit an eine Angular-Anwendung anbinden lassen, wie clientseitige Tools und Widgets definiert werden und wo derzeit noch eine kleine selbstgeschriebene Hilfsfunktion nötig ist.
📂 Source Code (siehe Branch copilotkit)
Die Beispielanwendung
Als durchgängiges Beispiel dient – wie in der ganzen Serie – eine Flight-Booking-Anwendung. Sie lässt sich ganz klassisch bedienen; wer aber feststeckt oder Arbeitsschritte abkürzen möchte, aktiviert ein Sidecar: einen Chat, über den ein serverseitiger Agent aushilft. Er beantwortet Anfragen mit Text, ruft client- und serverseitige Tools auf und blendet interaktive Komponenten wie eine Flugkarte in den Verlauf ein.

CopilotKit in Angular integrieren
CopilotKit setzt direkt auf dem besprochenen AG-UI SDK auf: Der Agent wird clientseitig durch einen HttpAgent aus @ag-ui/client repräsentiert, den CopilotKit verwaltet und dessen gestreamte AG-UI-Events es in einesn Signal-basierten Chatverlauf übersetzt. Die serverseitige Implementierung bleibt davon unberührt – wer bereits einen AG-UI-Endpunkt hat, kann ihn unverändert weiterverwenden.
Die Einbindung in die Anwendung erfolgt wie üblich über einen Provider in der app.config.ts:
// src/app/app.config.ts
import { provideCopilotKit } from '@copilotkit/angular';
export const appConfig: ApplicationConfig = {
providers: [
[...]
provideCopilotKit({}),
],
};
Durch den Einsatz von AG-UI ist das Angular-Beispiel unabhängig von serverseitigen Technologien und Modellen. Um eine möglichst einfache Ausführung zu ermöglichen, enthält die Demo-Anwendung einen Agent, der das äußerst komfortable und auf TypeScript basierende Agent-Framework Mastra nutzt. Da das AG-UI SDK für Mastra einen Adapter bereitstellt, lassen sich damit entwickelte Agents einfach über AG-UI anbinden.
Der Client wurde sowohl mit OpenAIs GPT 5 als auch mit Googles Gemini 3 getestet. Details für das Einrichten und Starten der Demo finden sich in der Readme.
Agents über einen Agent Store anbinden
Dreh- und Angelpunkt der Angular-Integration von CopilotKit ist der sogenannte Agent Store. Er repräsentiert einen konkreten Agent samt Chatverlauf und Ausführungszustand. Das Demo-Projekt kapselt die Einrichtung des Ticketing-Agents in einer Funktion injectTicketingAgentStore:
// src/app/domains/ticketing/ai/ticketing-agent-store.ts
import { injectAgentStore } from '@copilotkit/angular';
import { initAgentStore } from '../../shared/util-copilotkit/init-agent-store';
[...]
const AGENT_ID = 'ticketingAgent';
export function injectTicketingAgentStore() {
initAgentStore({
agentId: AGENT_ID,
url: 'http://localhost:3001/ag-ui/ticketingAgent',
useServerMemory: true,
frontendTools: [
findFlightsTool,
getLoadedFlightsTool,
toggleFlightSelectionTool,
getCurrentBasketTool,
displayFlightDetailTool,
flightWidget,
],
});
return injectAgentStore(AGENT_ID);
}
Die Hilfsfunktion initAgentStore registriert den Agent samt seiner clientseitigen Tools bei CopilotKit; ihr Aufbau wird im nächsten Abschnitt besprochen. Danach liefert das von CopilotKit angebotene injectAgentStore den eigentlichen Agent Store zurück – ein Signal<AgentStore>, das unter anderem den Chatverlauf (messages) und den Ausführungszustand (isRunning) als Signals bereitstellt.
Die Konfiguration verweist auf die URL des Agents. Dahinter steht ein serverseitig implementierter Ticketing-Agent, der Reisende rund um ihre Flugbuchungen unterstützt. Dafür verfügt er über Tools zum Nachschlagen gebuchter Flüge sowie zum Buchen und Stornieren (findBookedFlights, bookFlight, cancelFlight). Umgesetzt ist er in unserem Fall mit dem TypeScript-Framework Mastra; für die hier gezeigte Anbindung spielt das jedoch keine Rolle – entscheidend ist lediglich, dass der Agent AG-UI unterstützt.
Mit useServerMemory gibt der Aufrufer an, ob der Agent den Chatverlauf speichert. Ist dem nicht so, muss der Client den gesamten Chatverlauf in jeden Aufruf wiederholen.
In der Auflistung frontendTools registriert der Konsument sämtliche clientseitigen Tools, deren Aufruf der Agent anfordern darf. Interessanterweise findet sich darunter auch das Widget flightWidget – die eingangs gezeigte Flugkarte. Das ist kein Zufall: In CopilotKit sind Widgets nichts anderes als Frontend-Tools, denen eine Angular-Komponente für die Darstellung zugeordnet wurde.
Agentic UI with Angular
Wenn du AG-UI nicht nur integrieren, sondern sauber in größere Architekturen einbetten willst:
In meinem Buch Agentic UI mit Angular gehe ich genau auf diese Patterns und Trade-offs im Detail ein.
Die Hilfsfunktion initAgentStore
CopilotKit sieht derzeit vor, dass Agents beim Aufruf von provideCopilotKit während des Anwendungsstarts konfiguriert und damit registriert werden. Für lazy geladene Feature-Bereiche ist das unpraktisch: Deren Tools und Widgets sollen erst mit dem jeweiligen Bundle in den Browser wandern und nicht schon im Hauptbundle landen.
Genau diese Lücke schließt initAgentStore. Sie läuft in einem Injection Context und erledigt im Kern zwei Dinge: Sie registriert den Agent zur Laufzeit als sogenannten self-managed Agent bei CopilotKit und meldet anschließend sämtliche Frontend-Tools für dessen agentId an (leicht verkürzt):
// src/app/domains/shared/util-copilotkit/init-agent-store.ts
import { randomUUID } from '@ag-ui/client';
import { inject } from '@angular/core';
import { CopilotKit, registerFrontendTool } from '@copilotkit/angular';
[...]
export function initAgentStore(config: InitAgentStoreConfig): void {
const copilotKit = inject(CopilotKit);
const httpAgent = new AppHttpAgent(
{
agentId: config.agentId,
url: config.url,
threadId: randomUUID(),
},
{ useServerMemory: config.useServerMemory },
);
copilotKit.updateRuntime({
selfManagedAgents: {
...copilotKit.agents(),
[config.agentId]: httpAgent,
},
});
for (const tool of config.frontendTools ?? []) {
registerFrontendTool({
...tool,
component: tool.component || FallbackToolCard,
agentId: config.agentId,
});
}
[...]
}
Der Aufruf von updateRuntime ergänzt die bei CopilotKit hinterlegten Agents um einen neuen Eintrag. Bei AppHttpAgent handelt es sich um eine schlanke Ableitung des HttpAgent aus dem AG-UI SDK. Sie implementiert unter anderem die Option useServerMemory: Merkt sich der Server den Chatverlauf, filtert der AppHttpAgent bereits übertragene Nachrichten aus den Requests heraus.
Die anschließende Schleife registriert die übergebenen Tools mit registerFrontendTool bei CopilotKit. Dabei bindet sie jedes Tool an die agentId – die Tool-Definitionen selbst bleiben dadurch agnostisch und wiederverwendbar. Die dabei als Default gesetzte FallbackToolCard besprechen wir weiter unten.
Ein angenehmer Nebeneffekt: registerFrontendTool merkt sich den aktuellen Injection Context und führt die Tool-Handler später darin aus. Deshalb dürfen die Handler, wie im nächsten Abschnitt zu sehen, Angulars inject verwenden.
Der durch [...] angedeutete Rest der Funktion kümmert sich um die Darstellung von Tool-Aufrufen, die der Client nicht selbst ausführt – allen voran die serverseitigen Tools des Agents. Ihn beleuchten wir weiter unten.
Clientseitige Tools definieren
Die einzelnen Tools beschreibt das Demo-Projekt mit der Hilfsfunktion createFrontendTool:
// src/app/domains/ticketing/ai/tools/find-flights.tool.ts
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { z } from 'zod';
import { createFrontendTool } from '../../../shared/util-copilotkit/tool-definition';
[...]
export const findFlightsTool = createFrontendTool({
name: 'findFlights',
description: `Searches for flights and redirects the user to the result`,
parameters: z.object({
from: z.string().describe('airport of departure'),
to: z.string().describe('airport of destination'),
}),
handler: async ({ from, to }) => {
const store = inject(FlightStore);
const router = inject(Router);
store.updateFilter(from, to);
await router.navigate(['/ticketing/booking/flight-search']);
return { ok: true };
},
});
Neben einem Namen, einer Beschreibung und Parameterdefinitionen, die auf Zod basieren, enthält die Tooldefinition auch einen handler. Fordert der Agent das Tool an, führt CopilotKit diesen Handler aus – dank des zuvor erwähnten Injection Contexts inklusive funktionierendem inject.
Das Parameter-Objekt unterliegt jenem TypeScript-Typ, der aus dem Zod-Schema hervorgeht. In unserem Fall handelt es sich dabei um ein Objekt mit den Eigenschaften from und to. Die gezeigte Implementierung triggert eine Flugsuche, indem sie diese Suchkriterien an den FlightStore übergibt und navigiert den Benutzer danach auf die Ergebnisseite.
Tools, die Daten in Erfahrung bringen, zum Beispiel lokal vorliegende Zustände oder Antworten des Benutzers, können diese über den Rückgabewert ans Modell zurückmelden. Ein Beispiel dafür ist das getLoadedFlightsTool, das den Agent über jene Flüge informiert, die die Anwendung dem Benutzer gerade anzeigt:
// src/app/domains/ticketing/ai/tools/get-loaded-flights.tool.ts
export const getLoadedFlightsTool = createFrontendTool({
name: 'getLoadedFlights',
description: `Returns the currently loaded/displayed flights`,
parameters: z.object({}),
handler: async () => {
const store = inject(FlightStore);
return store.flightsValue().map(toFlightInfo);
},
});
Das Innenleben von createFrontendTool
Ein Blick hinter die Kulissen zeigt: createFrontendTool ist zur Laufzeit eine reine Identitätsfunktion. Sie nimmt die Tool-Definition entgegen und gibt sie unverändert zurück – sie registriert nichts und injiziert nichts:
// src/app/domains/shared/util-copilotkit/tool-definition.ts
import { type FrontendToolConfig } from '@copilotkit/angular';
export function createFrontendTool<Args extends Record<string, unknown>>(
tool: FrontendToolConfig<Args>,
): FrontendToolConfig<Args> {
return tool;
}
Der Sinn dieses Durchreichens liegt in der Type Inference: TypeScript leitet den generischen Typparameter Args aus dem übergebenen Zod-Schema in parameters ab und wendet ihn auf die gesamte Definition an. Dadurch kennt der handler die Typen seiner Parameter – im Fall von findFlights also from und to als string –, ohne dass die Tool-Definition sie explizit annotieren müsste.
Ohne die Hilfsfunktion gäbe es nur unbequemere Alternativen: die Definition von Hand als FrontendToolConfig<...> zu typisieren und damit die Parametertypen redundant zum Schema zu pflegen, oder auf die Typisierung zu verzichten und Tippfehler im Handler erst zur Laufzeit zu bemerken.
Widgets sind Tools mit Komponente
Für Widgets wie die Flugkarte sieht CopilotKit kein eigenes Konzept vor – und braucht auch keines. Ein Widget ist schlicht ein Frontend-Tool, dem über die Eigenschaft component eine Angular-Komponente zugeordnet wurde. Ruft der Agent das Tool auf, rendert CopilotKit diese Komponente im Chatverlauf und übergibt ihr die vom LLM gelieferten Parameter:
// src/app/domains/ticketing/ui/flight-widget.ts
const flightSchema = z.object({
id: z.number().describe('The flight id'),
from: z.string().describe('Departure city'),
to: z.string().describe('Arrival city'),
date: z.string().describe('Departure date in ISO format'),
delay: z.number().describe('Delay in minutes'),
});
const flightWidgetSchema = z.object({
flight: flightSchema,
status: z.enum(['booked', 'other']).describe('Status of the flight'),
});
export const flightWidget = createFrontendTool({
name: 'flightWidget',
description: `Displays a concrete flight as an interactive card.
Use it when referring to one or more specific flights.`,
parameters: flightWidgetSchema,
component: FlightWidget,
followUp: false,
handler: async () => ({ shown: true }),
});
Das Schema beschreibt hier also nicht nur die Parameter eines Funktionsaufrufs, sondern zugleich die Daten, mit denen die Komponente versorgt wird. Die Option followUp: false teilt CopilotKit mit, dass nach dem Anzeigen des Widgets kein weiterer Roundtrip zum Agent nötig ist – das Widget bildet den Abschluss der Antwort.
Wichtig dabei: followUp: false steuert nur den Client – damit auch das Modell solche Aufrufe als Abschluss seines Zugs behandelt, hängt createFrontendTool im Demo-Projekt automatisch einen entsprechenden Hinweis an die Tool-Beschreibung und damit an den Prompt an.
Die zugeordnete Komponente implementiert das Interface ToolRenderer und nimmt den Tool-Aufruf als Input entgegen. Über toolCall().args gelangt sie an die vom LLM übergebenen und gegen das Schema validierten Werte:
// src/app/domains/ticketing/ui/flight-widget.ts
import { type AngularToolCall, type ToolRenderer } from '@copilotkit/angular';
@Component({
selector: 'app-flight-widget',
imports: [FlightCard, RouterLink],
template: `
@let flight = toolCall().args.flight;
@if (flight) {
<app-flight-card [item]="flight" [readonly]="true">
[...]
</app-flight-card>
}
`,
})
export class FlightWidget implements ToolRenderer<FlightWidgetArgs> {
readonly toolCall = input.required<AngularToolCall<FlightWidgetArgs>>();
[...]
}
Anfragen an den Agent senden
Die Chat-Komponente der Anwendung – im Demo-Projekt AssistantChat – besorgt sich den Agent Store über die eingangs gezeigte Funktion und leitet daraus ihren Zustand ab:
// src/app/domains/shared/ui-assistant/assistant-chat/assistant-chat.ts
import { CopilotKit } from '@copilotkit/angular';
[...]
export class AssistantChat {
private readonly copilotKit = inject(CopilotKit);
protected readonly store = injectTicketingAgentStore();
protected readonly messages = computed(() => this.store().messages());
protected readonly isRunning = computed(() => this.store().isRunning());
protected submit(): void {
void sendMessage(this.copilotKit, this.store, this.message());
}
}
Das Senden übernimmt die Funktion sendMessage. Sie fügt die Benutzernachricht dem Agent hinzu und stößt danach über CopilotKit einen Run an:
// src/app/domains/shared/util-copilotkit/agent-store-helper.ts
export async function sendMessage(
copilotKit: CopilotKit,
store: Signal<AgentStore>,
content: string,
): Promise<void> {
const agent = store().agent;
agent.addMessage({ id: randomUUID(), role: 'user', content });
await copilotKit.core.runAgent({ agent });
}
Der Umweg über copilotKit.core.runAgent ist wichtig: Nur so nehmen die zuvor registrierten Frontend-Tools am Run teil. Nun muss der Client nur noch die vom Agent via AG-UI retournierten Antwortnachrichten im Chatverlauf anzeigen.
Chatverlauf in Angular-Templates präsentieren
Der gesamte Chatverlauf befindet sich im Signal messages des Agent Stores. Das Template iteriert die Nachrichten und gibt neben der textuellen Antwort (content) auch die angeforderten Tool-Aufrufe aus. Letzteres übernimmt die von CopilotKit bereitgestellte Komponente RenderToolCalls:
<!-- src/app/domains/shared/ui-assistant/chat-messages/chat-messages.html -->
@for (message of messages(); track message.id) {
@if (message.content) {
<div>{{ message.content }}</div>
}
@if (message.role === 'assistant' && message.toolCalls?.length) {
<copilot-render-tool-calls
[message]="message"
[messages]="messages()"
[agentId]="'ticketingAgent'" />
}
}
RenderToolCalls schlägt für jeden Tool-Aufruf die registrierte Darstellungskomponente nach – für das flightWidget erscheint so die interaktive Flugkarte. Um die Ausführung clientseitiger Tools müssen wir uns hingegen nicht kümmern, denn diese Aufgabe übernimmt CopilotKit ohne weiteres Zutun.
Die gestreamten AG-UI-Nachrichten lassen sich über die Developer Tools des Browsers nachvollziehen:

Diese Informationen machen zum einen das Protokoll greifbar und helfen zum anderen beim Troubleshooting.
Zeit für einen ersten Test
Damit ist alles beisammen, um die Lösung auszuprobieren; Details zum Starten von Client und Agent finden sich in der Readme des Demo-Projekts. Bitten wir den Assistenten etwa um Flüge von Graz nach Hamburg, fordert der Agent das Frontend-Tool findFlights an, und die Anwendung navigiert zur Ergebnisliste. Fragen zu konkreten Flügen beantwortet er mit der als Widget registrierten Flugkarte direkt im Chatverlauf:

Auch das Nachschlagen gebuchter Flüge sowie Buchungen und Stornierungen beherrscht der Agent bereits – dahinter stehen seine serverseitigen Tools. Wie der Chat solche Aufrufe darstellt, klärt der nächste Abschnitt.
Serverseitige Tool-Aufrufe darstellen
Frontend-Tools führt der Client aus. Die serverseitigen Tools des Agents – etwa bookFlight und cancelFlight – erscheinen jedoch ebenfalls als Tool-Aufrufe im Chatverlauf. Auszuführen gibt es hier clientseitig nichts, wohl aber darzustellen. Diese Aufgabe übernimmt im Demo-Projekt die FallbackToolCard – jene Komponente, die initAgentStore weiter oben bereits als Default für Frontend-Tools ohne eigene Darstellung eingesetzt hat (component: tool.component || FallbackToolCard). Hier übernimmt sie nun zusätzlich die Rolle eines Wildcard-Renderers für alle übrigen Tool-Aufrufe.
Da der Fallback mit jedem beliebigen Tool zurechtkommen muss, fällt das Zod-Schema für dessen Argumente entsprechend generisch aus – ein Record mit beliebigen Schlüsseln und Werten:
// src/app/domains/shared/util-copilotkit/fallback-tool-card.ts
const fallbackToolArgsSchema = z.record(z.string(), z.unknown());
export type FallbackToolArgs = z.infer<typeof fallbackToolArgsSchema>;
Die Darstellungskomponente implementiert wie gehabt das Interface ToolRenderer. Sie zeigt den Namen des Aufrufs an; auf Klick blendet sie die übergebenen Parameter ein:
@Component({
selector: 'app-fallback-tool-card',
template: `
<button type="button" class="tool-call" (click)="toggle()">
<span class="tool-call-label">Tool Call: {{ toolName() }}</span>
<span class="tool-call-caret">{{ expanded() ? '▾' : '▸' }}</span>
</button>
@if (expanded()) {
<pre class="tool-call-args">{{ prettyArgs() }}</pre>
}
`,
})
export class FallbackToolCard implements ToolRenderer<FallbackToolArgs> {
readonly toolCall = input.required<AngularToolCall<FallbackToolArgs>>();
protected readonly expanded = signal(false);
protected readonly toolName = computed(
() => this.toolCall().name ?? 'unknown',
);
protected readonly prettyArgs = computed(() =>
JSON.stringify(this.toolCall().args ?? {}, null, 2),
);
protected toggle(): void {
this.expanded.update((value) => !value);
}
}
Schema und Komponente fasst die Hilfsfunktion createRenderToolCall zu einem Registrierungsobjekt zusammen – wie createFrontendTool eine Identitätsfunktion, die lediglich für Typsicherheit sorgt. Ein handler fehlt bewusst: Die Ausführung übernimmt der Server, die Komponente ist reine Darstellung. Der Name '*' markiert den Renderer als Wildcard und damit als Fallback:
export const fallbackToolCard = createRenderToolCall({
name: '*',
args: fallbackToolArgsSchema,
component: FallbackToolCard,
});
Die Registrierung übernimmt jener Teil von initAgentStore, der weiter oben hinter [...] verborgen blieb:
// src/app/domains/shared/util-copilotkit/init-agent-store.ts
import { registerRenderToolCall } from '@copilotkit/angular';
[...]
export function initAgentStore(config: InitAgentStoreConfig): void {
[...]
const registeredFallback = copilotKit
.toolCallRenderConfigs()
.find((renderer) => renderer.name === '*');
if (!registeredFallback) {
registerRenderToolCall(fallbackToolCard);
}
for (const toolCall of config.toolCallRenderer ?? []) {
registerRenderToolCall({ ...toolCall, agentId: config.agentId });
}
}
Die Funktion prüft zunächst, ob bereits ein Wildcard-Renderer registriert ist, und meldet andernfalls die fallbackToolCard an. Anschließend registriert sie die über die Eigenschaft toolCallRenderer übergebenen Darstellungskomponenten und bindet sie – wie schon die Frontend-Tools – an die agentId.
Noch ein Test: Serverseitige Tools in Aktion
Damit lohnt sich ein zweiter Blick in die Anwendung: Fragen wir den Assistenten, ob wir bereits einen Flug nach Paris gebucht haben, greift der Agent zu findBookedFlightsTool – einem serverseitigen Tool. Dessen Ausführung findet vollständig am Server statt; der Client visualisiert den Aufruf lediglich über den registrierten toolCallRenderer als aufklappbare Karte samt Parametern. Die Antwort präsentiert der Agent anschließend mit dem bekannten Flug-Widget:

Auf diese Weise bleibt jeder serverseitige Tool-Aufruf für die Benutzer transparent nachvollziehbar.
Zusammenfassung
Mit @copilotkit/angular lässt sich AG-UI einfach in Angular integrieren. Clientseitige Tools und Widgets sind einheitlich als Frontend-Tools beschrieben, wobei Widgets lediglich eine zusätzliche Darstellungskomponente mitbringen. Auch serverseitige Tool-Aufrufe erscheinen im Chatverlauf – dargestellt durch einen als Wildcard registrierten Standard-Renderer. Der Agent Store stellt den Chatverlauf als Signal bereit, und die im Lieferumfang enthaltene Komponente RenderToolCalls bringt die registrierten Komponenten im Chat zur Anzeige.
Der nächste Schritt
Mit AG-UI ist die Kommunikation zwischen Frontend und Agent geklärt – die nächste Serie zeigt, wie das LLM die UI selbst aus Layouts, Anzeigen und Eingaben zusammenbauen kann, ohne neuen Frontend-Code für jeden Use Case.
Interesse an produktionsreifen Agentic-UI-Architekturen?
In meinem Workshop beschäftigen wir uns mit AG-UI, A2UI, MCP Apps, HITL-Patterns und modernen Angular-Architekturen für reale agentische Systeme.
FAQ
Wie lässt sich AG-UI in Angular integrieren?
Mit @copilotkit/angular steht eine Angular-Integration bereit, die direkt auf dem AG-UI SDK aufsetzt. Sie verwaltet den Agent, führt clientseitige Tools aus und stellt den Chatverlauf als Signal-basierten Agent Store bereit.
Was ist ein Agent Store?
Der Agent Store repräsentiert einen konkreten Agent samt Zustand. injectAgentStore liefert ihn als Signal<AgentStore>, das unter anderem den Chatverlauf (messages) und den Ausführungszustand (isRunning) als Signals anbietet.
Wozu dient die Hilfsfunktion initAgentStore?
CopilotKit bietet derzeit keine Möglichkeit, Agent Stores für lazy geladene Feature-Bereiche nachträglich zu initialisieren. initAgentStore schließt diese Lücke: Sie registriert den Agent zur Laufzeit als self-managed Agent und meldet die Frontend-Tools für dessen agentId an.
Wie gelangen Widgets in den Chatverlauf?
Widgets sind Frontend-Tools mit einer zugeordneten Angular-Komponente. Fordert der Agent solch ein Tool an, rendert die CopilotKit-Komponente RenderToolCalls die hinterlegte Komponente im Chatverlauf und versorgt sie mit den vom LLM übergebenen, gegen das Zod-Schema validierten Parametern.
Wie lassen sich serverseitige Tool-Aufrufe visualisieren?
Serverseitige Tool-Aufrufe erscheinen ebenfalls im Chatverlauf, auch wenn der Client sie nicht ausführt. Ein mit createRenderToolCall beschriebener Wildcard-Renderer (name: '*') stellt sie standardmäßig als aufklappbare Karte samt Parametern dar; weitere Darstellungskomponenten nimmt die Eigenschaft toolCallRenderer von initAgentStore entgegen.

