AI Agent Observability: Warum hat er das getan?
.png)
Auf Geschwindigkeit ausgelegt: ~ 10 ms Latenz, auch unter Last
Unglaublich schnelle Methode zum Erstellen, Verfolgen und Bereitstellen Ihrer Modelle!
- Verarbeitet mehr als 350 RPS auf nur 1 vCPU — kein Tuning erforderlich
- Produktionsbereit mit vollem Unternehmenssupport
Verfügbarkeit ist die falsche Frage
Eine Zahlungs-API lässt sich leicht beobachten, weil sie vorhersehbar ist. Dieselbe Eingabe führt zum selben Codepfad. Drei Kennzahlen – Anfragerate, Fehlerrate, Dauer – verraten fast alles. Geht etwas schief, liest man einen Stack-Trace. Ein Stack-Trace ist eine Tatsache über das Programm, keine Vermutung über eine Absicht.
Ein Agent bricht mit jeder Annahme dieses Prinzips. Das Modell wählt den Pfad zur Laufzeit, sodass dieselbe Eingabe keineswegs denselben Codepfad erzeugt. Oft gibt es gar keinen Fehler: Der Agent schließt ab, gibt Text zurück, und jeder getätigte HTTP-Aufruf lieferte den Statuscode 200. Was schiefgelaufen ist, ist meist kein Absturz, sondern eine falsche Entscheidung – der Agent hat das falsche Tool gewählt, eine bereits vorhandene Datei erneut gelesen oder eine Suche endlos wiederholt, die niemals ein Ergebnis liefern konnte.
Die Fragestellung verschiebt sich also: Nicht war das System verfügbar, sondern warum hat der Agent so gehandelt. Dieses „Warum“ ist eine Eigenschaft der gesamten Sequenz, nicht eines einzelnen Requests. Deshalb kann ein Dashboard vollkommen grün anzeigen, während Ihr Agent inhaltlich fehlschlägt. Eine P99-Latenz von 900 ms über alle Model-Aufrufe hinweg sagt nichts über einen Durchlauf aus, der 140 solcher Aufrufe benötigt hat.
Die Beobachtungseinheit ist eine Trajektorie
Die Daten gliedern sich in vier verschachtelte Ebenen, von denen nur die untersten beiden wie ein herkömmlicher Request aussehen.
Der eigentliche Wert liegt in den beiden mittleren Ebenen – und genau diese werden von einem konventionellen, request-basierten Tracer nicht abgebildet. Er sieht lediglich eine Ansammlung ausgehender Aufrufe ohne logischen Zusammenhang und kann nicht erkennen, dass die Aufrufe 11 bis 27 zu einem einzigen Turn gehörten, der siebenmal denselben Ansatz versucht hat.
Eine Eigenschaft unterscheidet dies grundlegend von herkömmlichem distributed Tracing: Jede Ebene kann Schleifen bilden (Looping). In einem normalen Service-Graph gibt es dafür kein Äquivalent – A ruft B auf, B ruft C auf. Wenn A sich selbst aufruft, liegt ein Bug vor. Bei einem Agenten ist ein Schritt, der entscheidet, sich selbst erneut aufzurufen, der Normalfall. Die einzige Möglichkeit, eine produktive Schleife von einer festgefahrenen zu unterscheiden, besteht darin, die gesamte Sequenz zu analysieren.
Was auf jeder Ebene instrumentiert werden sollte
Jede Ebene benötigt ihre eigenen Signale. Unselektierte Datenerfassung führt nur zu Datenmengen ohne Erkenntnisgewinn. Dies ist das Minimum, das tatsächlichen Mehrwert bringt:
Das letzte Feld der Tabelle ist das aufschlussreichste Signal in der AI Agent Observability, das jedoch kaum erfasst wird: Wird dasselbe Tool innerhalb eines Turns zweimal mit denselben Argumenten aufgerufen, handelt es sich um eine Schleife. Das ist offensichtlich, sobald die Argumente im Span enthalten sind – aus aggregierten Metriken lässt sich dies jedoch nicht ablesen.
Drei Fehlermuster, die nur auf Trajektorienebene sichtbar werden
Diese drei Muster decken einen Großteil aller Vorfälle in Produktionsumgebungen ab.
1. Die stille Retry-Schleife. Ein Agent durchsucht eine Knowledge Base, erhält keine brauchbaren Informationen, formuliert die Anfrage um und sucht erneut – zwanzig Mal. Jeder Suchlauf liefert HTTP 200 in 300 ms. Die Dashboards für Anfragerate und Fehlerrate zeigen lediglich einen unbedeutenden Anstieg des Datenverkehrs. Auf Session-Ebene ist das Problem sofort sichtbar: Ein einzelner Turn mit zwanzig Tool-Aufrufen und zwei Minuten Laufzeit. Die Ursache liegt nicht in einem einzelnen Span, sondern in der ständigen Wiederholung.
2. Das Tool, das erfolgreich ist, aber unbrauchbare Daten liefert. Ein Tool zum Abrufen von Dokumenten stößt auf eine Berechtigungs-Sperre und gibt eine HTTP-200-Antwort zurück, deren Inhalt eine HTML-Login-Seite ist. Das Modell liest diese Seite und antwortet dem Benutzer, dass keine entsprechende Richtlinie existiere. Es tritt kein technischer Fehler auf. Die einzige Möglichkeit, diesen Fall aufzudecken, besteht darin, das Roh-Ergebnis zu erfassen. Die Erfassung von Rückgabewerten – nicht nur von Statuscodes – ist daher essenziell.
3. Der 40x-Run. Die durchschnittlichen Session-Kosten liegen bei $0,04. Eine einzelne Session kostet jedoch $1,60, ohne dass ein Fehler aufgetreten ist. Ein einziger Schritt hat eine große Datei erneut in den Kontext geladen. Diese Datei wurde in jedem folgenden Turn mitgeschleppt, wodurch sich die Input-Tokens für den Rest des Durchlaufs potenzierten. Solche Fälle lassen sich identifizieren, indem man Sessions nach Kosten sortiert und die Token-Anzahl pro Turn der Ausreißer analysiert. In Durchschnittswerten tauchen diese Probleme nicht auf.
Das gemeinsame Muster aller drei Fälle: Die Anomalie besteht in der Beziehung zwischen den einzelnen Schritten. Wenn ein Tool Schritte isoliert voneinander speichert, gehen genau die entscheidenden Informationen verloren.
Funktionsweise in TrueFoundry
Diese Daten lassen sich erfassen, ohne dass Änderungen am Code des Agenten erforderlich sind, da Ausführung und Überwachung an zentraler Stelle zusammenlaufen. Jeder Model- und Tool-Aufruf läuft über ein Gateway. Die Trajektorie wird somit automatisch bei der Bereitstellung aufgezeichnet – ohne manuelle Rekonstruktion aus verteilten Logs und ohne Lücken.
Sessions: Die oberste Ebene der Hierarchie
Für Agenten auf dem TrueFoundry Agent Harness zeigt die Sessions-Übersicht alle Konversationen über alle Agenten hinweg an – inklusive Startnachricht, Agent, Turn-Anzahl, Kosten und Dauer. Dies reicht aus, um kostenintensive oder ungewöhnlich lange Läufe direkt zu erkennen, ohne Details öffnen zu müssen – genau das, was zur Analyse von Fehlermuster 3 benötigt wird.

Session-Details: Turns, Timeline und Transkript
Beim Öffnen einer Session stehen alle drei Ebenen der Hierarchie zur Verfügung. Aggregierte Metriken umfassen Turns, Dauer, Kosten, Tokens, Context, Tool-Aufrufe, Sub-Agenten und Fehler. Eine nach Ereignistypen gegliederte Timeline unterteilt den Durchlauf pro Turn in Segmente für System, User, Model und Tool-Aufrufe. Ein Turn mit hohem Tool-Anteil ist tool-bound, ein Turn mit hohem Model-Anteil ist model-bound – visuell auf einen Blick erkennbar, ohne dass manuelle Berechnungen nötig sind. Darunter befindet sich das Transkript mit Tokens, Dauer und Kosten pro Turn sowie ein ausklappbares Panel für Agent Steps, das alle Tool-Aufrufe in zeitlicher Reihenfolge mit ihren Ergebnissen auflistet.

Diese chronologische Schrittliste macht abgebrochene Turns, fehlerhafte MCP-Server oder leere Tool-Ergebnisse sofort sichtbar. Eine Session kann direkt aus dieser Ansicht heraus als Live-Chat fortgeführt werden – ideal, um Fehlerbehebungen unmittelbar zu überprüfen.
Spans: Details eines einzelnen Aufrufs
Eine Ebene tiefer zeigt der Trace eine echte Span-Hierarchie anstelle eines flachen Logs. Eine einzelne Chat-Completion mit eingebundenem PII-Guardrail erzeugt beispielsweise fünf Spans: Einen ChatCompletion-Root-Span ohne Parent, einen untergeordneten Guardrail-Span, den darin enthaltenen ausgehenden Aufruf des Guardrails, einen Model-Span sowie dessen ausgehenden Aufruf.

Span-Attribute ermöglichen eine exakte Zuordnung von Kosten und Latenzzeiten anstelle von Näherungswerten. Der Root-Span enthält Attribute wie tfy.model.metric.cost_in_usd, input_tokens, output_tokens, latency_in_ms, time_to_first_token_in_ms und inter_token_latency_in_ms, zusammen mit tfy.input, tfy.output und tfy.triggered_guardrail_fqns. Jeder Span erfasst zudem das erstellende Subjekt. Spans können präzise abgefragt werden: client.traces.query_spans(...) mit einem trace_ids-Filter und einem Zeitfenster liefert die gesamte Hierarchie paginiert zurück. So gelangt man schnell von der Erkenntnis „Diese Session war teuer“ zu „Dieser spezifische Span hat die Kosten verursacht“.
Die Guardrail-Ausführung wird als eigener Span mit Ergebnis, Latenz und Befunden dargestellt. Auch blockierte Anfragen werden getrackt – ein abgewiesener Aufruf liefert wertvolle Erkenntnisse und erzeugt keine Lücke in den Daten.

Die Ebene der Model-Aufrufe
Aggregierte Daten werden im Metrics Dashboard dargestellt. Die Model Metrics umfassen Input- und Output-Tokens, Anzahl der Requests und Gesamtkosten sowie Durchsatz, Fehlerraten und eine detaillierte Fehleraufschlüsselung nach Fehlertyp. Die Latenz wird für P50, P75, P90 und P99 über vier Kennzahlen hinweg erfasst – End-to-End-Latenz, Time to First Token, Inter-Token-Latenz und Zeit pro Output-Token. Diese Unterscheidung ist wichtig, da eine verzögerte erste Antwort und ein verlangsamter Token-Stream unterschiedliche technische Ursachen haben.

Jedes Diagramm lässt sich über ein View by-Auswahlfeld dynamisch anpassen – nach Modellen, virtuellen Modellen, Benutzern, virtuellen Accounts, Teams oder benutzerdefinierten Metadaten-Schlüsseln, die als Request-Header übergeben werden. Eine frühzeitige Konfiguration von Metadaten zahlt sich aus: Werden Agenten-Namen oder Run-IDs mitgesendet, stehen sofort Kosten- und Latenzansichten pro Agent zur Verfügung, ohne dass zusätzlicher Entwicklungsaufwand entsteht.
Die Ebene der Tool-Aufrufe
Tool-Aufrufe werden über MCP-Metriken mit der gleichen Detailtiefe erfasst – ein Bereich, der in vielen rein LLM-fokussierten Setups vernachlässigt wird. Die Server-Ansicht bietet Durchsatz pro Server, Latenz-Perzentile, Fehlerraten und Fehleraufschlüsselungen sowie eine Methodenaufruf-Aufschlüsselung nach tools/list, tools/call, resources/list und weiteren Methoden. Ein Agent, der Ressourcen durch wiederholte Aufrufe von tools/list verbraucht, hat ein Problem bei der Service-Discovery, nicht bei der Aufgabenausführung.

Die Tools-Ansicht ermöglicht die Detailanalyse einzelner Tools über alle Server hinweg: Anfragen pro Sekunde, Latenz-Perzentile, Fehlerraten nach Fehlertyp, eine vergleichende Latenzübersicht sowie eine Rangliste der Tools nach Anfragenzahl. Diese Rangliste ist der schnellste Weg, um Tools zu identifizieren, die vom Agenten häufiger als erwartet aufgerufen werden.

Filter bleiben beim Wechsel zwischen den Tabs erhalten. Wird die Ansicht im Model-Tab auf einen bestimmten Benutzer eingeschränkt, bleibt dieser Filter beim Wechsel zu den MCP-Metriken aktiv. So lässt sich ohne erneute Abfrage feststellen, ob verzögerte Sessions durch das Modell oder durch aufgerufene Tools verursacht werden.

Ansichten pro Agent und Hop
Registrierte Agenten erhalten ein dediziertes Dashboard, das Anfragemengen, Latenz-Perzentile, Fehlerraten und die Nutzung im Zeitverlauf übersichtlich zusammenfasst – unabhängig davon, ob der Agent auf Bedrock, LangGraph oder einem benutzerdefinierten Dienst läuft.

Dieselben Daten lassen sich auch programmgesteuert abfragen: Die Metrics-API stellt eine agentMetrics-Datenquelle bereit, die Verteilungs- oder Zeitreihenergebnisse gruppiert nach agentName, agentFramework oder agentServerType mit Perzentil-Aggregationen für latencyMs zurückgibt. In Multi-Agenten-Systemen erfasst Request Traces exakt, welcher Agent jeden Aufruf getätigt hat und für welchen Benutzer er ausgeführt wurde – diese Zuordnung macht Tool-Aufrufe von Sub-Agenten bis zum ursprünglichen Benutzer rückverfolgbar.

Eine Einschränkung der aktuellen Version: Eine vollständige Actor-Chain-Ansicht, die die Kette Benutzer → Agent → Sub-Agent → Tool in einem einzigen visuellen Trace zusammenhängend darstellt, befindet sich derzeit in Entwicklung – ebenso wie Drift-Erkennung, Anomalie-Benachrichtigungen und eine Funktion zum temporären Stoppen von Agenten per Klick. Derzeit erfolgt die Zuordnung auf Trace-Ebene pro Hop, noch nicht als durchgehender Gesamt-Graph.
Qualitätsmessung: Feedback direkt am Trace
Latenz und Kosten lassen sich präzise messen, die Antwortqualität hingegen nicht. Deshalb wird Feedback direkt am Trace erfasst und nicht in einer separierten Tabelle gespeichert. Jede Antwort des Gateways enthält einen x-tfy-feedback-target-id-Header. Wird an /api/svc/v1/gateway-feedback eine Bewertung von 1 bis 5 mit einem optionalen Kommentar gesendet, erscheint diese Bewertung direkt am Span sowie in den Rohdaten unter tfyGatewayFeedbacks. Über die zurückgegebene ID kann das Feedback jederzeit aktualisiert oder gelöscht werden. Die Target-ID bezieht sich aktuell auf den Root-Span, sodass das Feedback der gesamten Anfrage zugeordnet wird.

Wird diese Funktion mit einer Bewertungsschaltfläche (z. B. Thumbs-up/down) in Ihrer Anwendung verknüpft, erhalten auffällige Sessions eine qualitative Kennzeichnung. Aus der reinen Information „Dieser Run kostete das 40-fache“ wird so die konkrete Erkenntnis „Dieser Run kostete das 40-fache und wurde vom Benutzer mit 2 von 5 Sternen bewertet“.
Export: Bestehende Systeme nahtlos einbinden
Die Nutzung dieser Funktionen erfordert keinen Wechsel Ihrer bestehenden Infrastruktur. Das Gateway ist OpenTelemetry-konform. Traces und Metriken können unabhängig voneinander exportiert werden – die Konfiguration erfolgt unter AI Gateway → Controls → Settings → OTEL Config über HTTP oder gRPC, mit Proto- oder JSON-Codierung sowie individuellen Authentifizierungs-Headern. Systeme, die delta-codierte Metriken erwarten (wie Datadog oder CloudWatch), benötigen die Option Export Delta Metrics sowie eine entsprechende Temporalitats-Umgebungsvariable im Gateway-Deployment. Prometheus kann den Endpunkt /metrics auf selbstgehosteten Gateways direkt scrapen.

OpenTelemetry Trace-Fluss: Traces werden in TrueFoundry gespeichert und parallel an ein externes Backend exportiert
Der Export arbeitet additiv und ersetzt die interne Speicherung nicht: TrueFoundry speichert Traces in jedem Fall weiter. So bleiben die Session- und Span-Ansichten in der Plattform voll nutzbar, während Systeme wie Grafana oder Datadog zeitgleich mit denselben Daten versorgt werden.

Praxisbeispiel: Den 40x-Run identifizieren
Szenario: Ein Support-Copilot ist seit einer Woche in Produktion. Die Finanzabteilung meldet, dass sich die Gesamtkosten verdreifacht haben.
1. Analyse auf Session-Ebene: Sortieren Sie die Sessions nach Kosten. Der Median liegt bei wenigen Cents. Vier Sessions liegen jedoch über einem Dollar, alle mit einer einstelligen Turn-Anzahl. Es handelt sich also nicht um lange Konversationen, sondern um einzelne Turns mit übermäßig hohem Ressourcenverbrauch.
2. Timeline einer betroffenen Session prüfen: Turn 3 besteht fast ausschließlich aus Tool-Aufrufen. Statistik: 31 Tool-Aufrufe, 0 Fehler. Da kein technischer Fehler aufgetreten ist, wurde kein automatischer Alarm ausgelöst.
3. Agent Steps für Turn 3 aufklappen: Die chronologische Liste zeigt, dass ein spezifisches Tool zum Abrufen von Dokumenten wiederholt aufgerufen wurde. Die Token-Anzahl pro Turn steigt ab Turn 3 drastisch an und fällt nicht mehr ab – ein großes Dokument wurde in den Kontext geladen und verblieb dort für alle weiteren Schritte.
4. Gegenprüfung auf Tool-Ebene: In den MCP-Metriken (Tools-Ansicht) führt dieses spezifische Tool die Rangliste der Anfragemengen mit großem Abstand an und weist zudem den schlechtesten P90-Latenzwert auf.
5. Fehler beheben und Verifizierung durchführen: Unabhängig davon, ob die Lösung in einer spezifischeren Tool-Logik, Pagination oder einer Prompt-Anpassung besteht (die dem Agenten mitteilt, dass das Dokument bereits vorliegt) – die Überprüfung bleibt gleich: Filtern Sie die Sessions dieses Agenten für den Folgetag und prüfen Sie, ob sich die Kostenverteilung normalisiert hat. Falls Feedback-Erfassung integriert ist, prüfen Sie, ob die Kostenausreißer auch schlechte Bewertungen erhalten haben – dies ist meist der Fall.

Fünf Analyseschritte ohne manuelle Custom-Instrumentierung – jeder Schritt beantwortet eine gezielte Frage zur Trajektorie.
Wichtige Details für die Praxis
Agenten-Metriken enthalten standardmäßig jeden Gateway-Request. Anfragen, die nicht über einen Agenten liefen, geben null für agentName, agentFramework und agentServerType zurück und werden in groupBy-Ausgaben als null-Kategorien geführt. Da IS_NULL für diese drei Felder nicht unterstützt wird, grenzen Sie Abfragen gezielt mit agentName IN [...] oder einem STRING_*-Operator ein.
Trace- und Metrik-Exporte werden getrennt konfiguriert. Der Traces-Exporter überträgt ausschließlich Traces, der Metrics-Exporter ausschließlich Metriken. Die Aktivierung nur eines Exporters führt dazu, dass das externe System unvollständige Daten erhält.
Metadaten frühzeitig planen. Benutzerdefinierte Metadaten-Schlüssel, die als Request-Header übergeben werden, stehen im gesamten Dashboard als View by-Dimension zur Verfügung. Das Mitesenden von Agenten-Namen, Umgebungskennzeichnungen oder Run-IDs erfordert kaum Aufwand. Eine nachträgliche Ergänzung führt jedoch dazu, dass historische Daten nicht mehr nach diesen Dimensionen gefiltert werden können.
Weiterführende Themen
- AI Agent Observability Tools – Die Tool-Landschaft und eine Evaluierungscheckliste
- LLM Observability Tools – Die Ebene der Model-Aufrufe unterhalb der Trajektorie
- Graph Engineering for AI Agents – Knoten evaluieren vs. Kanten steuern
- Governing AI Agents Across Multiple Platforms – Wenn die Sichtbarkeit an Plattformgrenzen endet
- What Is an MCP Gateway? – Der Erfassungspunkt für jeden Tool-Aufruf
Fazit
Die Versuchung beim Agent Monitoring besteht oft darin, Agenten in bestehende Dashboards einzubinden, P99-Latenzen sowie Fehlerraten zu überwachen und das Thema Observability damit als erledigt zu betrachten. Dieser Ansatz scheitert beim ersten Vorfall in der Praxis: Der Ausreißer-Run, der das Budget belastet hat, lieferte auf jedem Hop den Statuscode 200 und taucht in keinem herkömmlichen Fehler-Chart auf.
Die Lösung besteht nicht in einer größeren Menge an Metriken, sondern in einer angepassten Beobachtungseinheit. Erfassen Sie die vollständige Trajektorie – Session, Turn, Model-Aufruf, Tool-Aufruf mit Argumenten und Ergebnissen direkt an den Spans. Dadurch werden die typischen Fehlermuster transparent analysierbar: Eine Schleife zeigt sich als wiederholter Aufruf mit identischen Argumenten, ein fehlerhaftes Tool-Ergebnis wird durch die Speicherung des Rückgabewerts sichtbar, und ein teurer Ausreißer-Run lässt sich durch gezieltes Sortieren sofort identifizieren.
TrueFoundry AI Gateway bietet eine Latenz von ~3—4 ms, verarbeitet mehr als 350 RPS auf einer vCPU, skaliert problemlos horizontal und ist produktionsbereit, während LiteLM unter einer hohen Latenz leidet, mit moderaten RPS zu kämpfen hat, keine integrierte Skalierung hat und sich am besten für leichte Workloads oder Prototyp-Workloads eignet.



Steuern, implementieren und verfolgen Sie KI in Ihrer eigenen Infrastruktur
Aktuelle Blogs
Häufig gestellte Fragen
Was ist AI Agent Observability?
Das Aufzeichnen der vollständigen Ausführungstrajektorie eines Agenten – Sitzungen, Turns, Modellaufrufe und Tool-Aufrufe mit Argumenten, Ergebnissen, Tokens, Kosten und Latenz –, damit Sie beantworten können, warum er sich so verhalten hat. Vom Application Monitoring unterscheidet es sich in der Beobachtungseinheit: Eine Anfrage hat einen Anfang und ein Ende, während eine Trajektorie eine verschachtelte Sequenz ist, in der jede Ebene in eine Schleife geraten kann.
Worin unterscheidet sich Agent Observability von LLM Observability?
LLM Observability ist eine Teilmenge, die den Modellaufruf abdeckt: Prompt, Completion, Tokens, Latenz, Kosten. Agent Observability ergänzt alles darum herum – welche Tools liefen, in welcher Reihenfolge, mit welchen Argumenten und Ergebnissen, und wie viele Durchläufe ein Turn brauchte, bevor er stoppte. Die meisten echten Fehler stecken in dieser Struktur, nicht in einer einzelnen Completion.
Muss ich meinen Agenten-Code für das Agenten-Tracing instrumentieren?
Nicht, wenn Modell- und Tool-Traffic bereits über ein Gateway läuft, denn es zeichnet jeden Hop als Nebeneffekt der Verarbeitung auf. SDK-Instrumentierung auf Framework-Ebene ergänzt interne Reasoning-Schritte, die das Gateway nie sieht; beide ergänzen sich also und sind keine Alternativen.
Kann ich TrueFoundry in meiner eigenen VPC oder On-Prem bereitstellen?
Ja – in der VPC, On-Prem, Air-Gapped, hybrid oder über mehrere Clouds hinweg, ohne dass Daten Ihre Domäne verlassen.
Unterstützt TrueFoundry MCP und KI-Agenten generell?
Ja. Es umfasst ein MCP Gateway, ein Agent Gateway und eine MCP & Agents Registry mit Zugriffskontrolle auf Tool-Ebene. Agenten auf Basis von LangGraph, CrewAI, AutoGen oder einem eigenen Framework lassen sich alle zentral steuern.
Lässt es sich in meinen bestehenden Observability-Stack integrieren?
Ja. Das Gateway ist OpenTelemetry-kompatibel und lässt sich in Grafana, Datadog, Prometheus oder Ihren bevorzugten Stack integrieren. Es verfolgt jede Anfrage vom Prompt bis zur Ausführung von Tools und Modellen, sodass Sie eine einheitliche Protokollierung erhalten, ohne Ihre bestehenden Systeme entfernen zu müssen.









.png)
.png)
.png)
.png)

.webp)
.webp)
.png)

.png)
.png)
.png)
.png)
.webp)
.webp)

.png)
.png)





