> So tracest du LLM-Agenten mit OpenTelemetry: GenAI Semantic Conventions und ihr Status, Span-Baum, Token-Metriken, Sampling, PII, Evals und Tool-Optionen.
>
> Web page: https://balazscsorba.com/de/blog/agent-observability-opentelemetry · Language: Deutsch · Also available in: [English](https://balazscsorba.com/blog/agent-observability-opentelemetry.md) · [Magyar](https://balazscsorba.com/hu/blog/agent-observability-opentelemetry.md)
> Author: Balázs Csorba · Published: 2026-10-02 · Keywords: LLM agent observability OpenTelemetry, OpenTelemetry GenAI semantic conventions, how to trace LLM agents, gen_ai semantic conventions attributes, LLM token usage and cost metrics, LLM tracing sampling, PII in LLM traces, Langfuse vs Arize Phoenix vs Datadog, AI agent tracing evals, OpenTelemetry LLM tracing

[Blog](https://balazscsorba.com/de/blog)/LLMOps & Evals

# Observability für LLM-Agenten mit OpenTelemetry: Traces, Tokens, PII und Evals

So tracest du LLM-Agenten mit OpenTelemetry: GenAI Semantic Conventions und ihr Status, Span-Baum, Token-Metriken, Sampling, PII, Evals und Tool-Optionen.

[Balázs Csorba](https://balazscsorba.com/de/about)·2\. Oktober 2026·12 Min. Lesezeit

-   OpenTelemetry
-   LLM observability
-   AI agents
-   Tracing
-   Evals

![Diagramm: Ein Agentenlauf verzweigt sich in OpenTelemetry-Spans für Modellaufrufe, Tool-Aufrufe, Token-Metriken und Eval-Ergebnisse, die an ein Trace-Backend exportiert werden.](https://balazscsorba.com/images/blog/agent-observability-opentelemetry/cover.webp?v=e8e3b0f588)

## Das Wichtigste in Kürze

-   Die OpenTelemetry GenAI Semantic Conventions liegen jetzt in einem eigenen Repository und haben weiter den Status Development. Pinne Versionen und rechne mit umbenannten Attributen.
-   Bilde einen Agentenlauf als einen Trace ab: ein invoke\_agent-Root-Span, chat-Spans für jeden Modellaufruf und execute\_tool-Spans für jeden Tool-Aufruf. Erst dieser Baum macht Schleifen und verschwendete Schritte sichtbar.
-   Erfasse Token-Zahlen, Modell, Finish Reason und Fehlertyp auf jedem Span, lass aber Prompts, Tool-Argumente und Ergebnisse standardmäßig draußen (in den Conventions sind sie Opt-in) und speichere sie getrennt, wenn du sie brauchst.
-   Sample nach Ergebnis, nicht per Münzwurf: Behalte jeden Fehler, jeden langsamen oder teuren Lauf und jeden fehlgeschlagenen Eval, dazu einen kleinen Anteil vom Rest. Denk daran, dass Evals meist erst nach dem Trace fertig sind.
-   Jedes OTLP-Backend kann Agenten-Traces annehmen. Die echten Unterschiede sind, wie gut es die gen\_ai-Attribute versteht, wo es gehostet wird und was es kostet. Starte mit dem Standard und halte den Exporter austauschbar.

Auf dieser Seite

1.  [Warum Agenten Traces brauchen und nicht nur Logs](https://balazscsorba.com/#why-traces)
2.  [Die GenAI Semantic Conventions: was es gibt und wie stabil es ist](https://balazscsorba.com/#semantic-conventions)
3.  [Der Trace-Baum: ein Lauf, ein Trace](https://balazscsorba.com/#trace-tree)
4.  [Was auf jedem Span erfasst werden sollte](https://balazscsorba.com/#what-to-record)
5.  [Token- und Kostenmetriken](https://balazscsorba.com/#tokens-and-cost)
6.  [Sampling: die interessanten Läufe behalten](https://balazscsorba.com/#sampling)
7.  [PII und sensible Inhalte in Traces](https://balazscsorba.com/#pii)
8.  [Traces mit Evals verbinden](https://balazscsorba.com/#evals)
9.  [Tool-Optionen](https://balazscsorba.com/#tools)
10.  [Eine Checkliste für den ersten Sprint](https://balazscsorba.com/#checklist)
11.  [Wo ich noch nicht zu viel investieren würde](https://balazscsorba.com/#closing)
12.  [Quellen](https://balazscsorba.com/#sources)

Ein klassischer Web-Request ist ein Aufruf, eine Antwort und ein Stacktrace, wenn etwas kaputtgeht. Ein Agentenlauf ist ein kleines Programm, das das Modell beim Laufen selbst schreibt: Es plant, ruft ein Tool auf, liest das Ergebnis, ruft das Modell erneut auf, versucht es nochmal und läuft manchmal in einer Schleife, bis ein Budget aufgebraucht ist. Wenn so ein Lauf viermal so viel kostet wie nötig oder unbemerkt eine falsche Antwort liefert, zeigen dir Logs verstreute Zeilen, nicht die Form dessen, was passiert ist.

Distributed Tracing ist schon das richtige Werkzeug für die Frage „was ist in welcher Reihenfolge passiert und wie lange hat jeder Teil gedauert“. OpenTelemetry (OTel) ist der herstellerneutrale Weg, Traces zu erzeugen, und hat inzwischen eigene GenAI Semantic Conventions. Sie sind jung, immer noch als Development markiert und gerade umgezogen. Dieser Artikel handelt also genauso davon, was du pinnen und kapseln solltest, wie davon, was du erfassen solltest.

Ich gehe durch die Conventions und ihren echten Status, den Span-Baum eines Agentenlaufs, was auf jeden Span gehört, Token- und Kostenmetriken, Sampling, PII, die Verbindung zu Evals und wie die gängigen Backends dazu passen. Am Ende steht eine Checkliste. Ich setze voraus, dass du weißt, was [eine Agent Loop](https://balazscsorba.com/de/blog/agent-loop-explained) ist.

## Warum Agenten Traces brauchen und nicht nur Logs

Drei Fehlerbilder von Agenten sind ohne Trace fast unsichtbar. **Schleifen und verschwendete Schritte**: Das Modell ruft dasselbe Such-Tool fünfmal mit leicht veränderten Argumenten auf. **Stille Verschlechterung**: Ein Retrieval-Schritt liefert nichts, das Modell antwortet aus dem Gedächtnis und die Ausgabe wirkt plausibel. **Kostendrift**: Eine Prompt-Änderung oder ein größeres Tool-Ergebnis bläht den Kontext auf, und jeder spätere Modellaufruf im Lauf wird teurer.

Alle drei sind Eigenschaften eines ganzen Laufs, nicht eines einzelnen Aufrufs. Ein Trace liefert dir den Lauf als Baum mit Zeit, Token-Zahlen und Ergebnis pro Knoten und lässt dich die Fragen stellen, auf die es ankommt: Wie viele Modellaufrufe pro Anfrage im p95, welches Tool schlägt am häufigsten fehl, welcher Schritt dominiert die Latenz. Wenn du nur loggst, baust du aus Korrelations-IDs ein schlechteres Tracing-System nach.

## Die GenAI Semantic Conventions: was es gibt und wie stabil es ist

Semantic Conventions sind die vereinbarten Namen für Attribute, Spans und Metriken, damit ein Backend Telemetrie aus jeder Bibliothek versteht. Für GenAI decken sie Modell-Spans (Inference, Embeddings, Retrieval, Memory), Agenten-Spans (create\_agent, invoke\_agent, invoke\_workflow, plan), Tool-Ausführung, Metriken, Events und eine MCP-Convention ab. Providerspezifische Seiten gibt es für Anthropic, OpenAI, AWS Bedrock und Azure AI Inference.

Zwei Fakten zählen, bevor du darauf aufbaust. Erstens sind die Conventions **umgezogen**: Die Seite auf opentelemetry.io leitet nur noch auf das eigene Repository open-telemetry/semantic-conventions-genai weiter. Zweitens sind sie **nicht stabil**. Die Übersichtsseite trägt den Status Development, und in der Juli-2026-Auswertung, die ich als unabhängige Quelle genutzt habe, war kein GenAI-spezifisches Attribut, kein Span, keine Metrik und kein Event als Stable markiert (nur gemeinsame Attribute wie error.type sind es). Rechne damit, dass sich Namen zwischen Releases ändern.

Praktisch bedeutet das einen Versionsschalter. Instrumentierungen, die die älteren Conventions unterstützten, liefern standardmäßig weiter die eingefrorene Ausgabe der Version 1.36 und brauchen OTEL\_SEMCONV\_STABILITY\_OPT\_IN=gen\_ai\_latest\_experimental, um die neuere Form zu senden. Nicht jedes Framework behandelt diese Variable gleich, also prüfe einen echten exportierten Span, statt der Doku zu vertrauen. Datadog zum Beispiel verlangt die Form ab Version 1.37.

**Behandle die Conventions als bewegliches Ziel**

Ich würde die Versionen der Instrumentierungspakete pinnen, eine dünne Schicht eigener Helfer zwischen Anwendung und OTel-API legen (damit eine Umbenennung eine Ein-Zeilen-Änderung ist) und einen Golden-File-Test pflegen, der je einen Span jeder Art exportiert und die Attributnamen vergleicht. Wenn ein Framework-Update die Ausgabe ändert, soll der Test fehlschlagen und nicht deine Dashboards still leer werden.

## Der Trace-Baum: ein Lauf, ein Trace

Die Conventions definieren die Span-Arten, die du brauchst. Die Wurzel ist ein **invoke\_agent**\-Span (Kind INTERNAL bei einem Agenten im selben Prozess, CLIENT bei einem entfernten Agenten-Dienst). Darunter hängt pro Modellaufruf ein **chat**\-Span (benannt nach Operation und angefragtem Modell, Kind CLIENT), pro Tool-Aufruf ein **execute\_tool**\-Span (INTERNAL) und, falls dein Agent eine explizite Planungsphase hat, ein **plan**\-Span. Eine mehrstufige Pipeline um Agenten kann einen invoke\_workflow-Span nutzen. Retrieval hat einen eigenen Span, benannt nach der Datenquelle.

Ein Agentenlauf als ein Trace. Die Span-Namen folgen den Conventions, die grauen Notizen sind das, worauf ich in jedem Knoten schaue.

Zwei Details lohnen sich zum Übernehmen. Der Span-Name eines Modellaufrufs ist die Operation plus das Modell, zum Beispiel chat plus Modellname, das hält die Kardinalität niedrig und das Wasserfall-Diagramm lesbar. Und die Conventions ermutigen ausdrücklich, **eigene** Tools von Hand mit execute\_tool-Spans zu instrumentieren, weil eine Auto-Instrumentierung Tools in deinem Code nicht kennen kann. Für Tools, die MCP-Server aufrufen, kann die MCP-Convention den Trace-Kontext in den Request-Metadaten mitgeben (traceparent, tracestate und baggage), sodass die Serverseite im selben Trace landet. Warum diese Serversicht wichtig ist, steht in [MCP-Tool-Design: Lessons Learned](https://balazscsorba.com/de/blog/mcp-tool-design-lessons-jira-server).

Noch ein Punkt zur Form: Ein wiederholter Modellaufruf sollte ein Span sein, der alle Wiederholungen umfasst, nicht mehrere, denn die Convention definiert den Span als die logische Operation aus Sicht des Aufrufers. Willst du die Wiederholungen sehen, erfasse sie als Events oder Attribute an diesem Span.

## Was auf jedem Span erfasst werden sollte

Der Standard sagt dir, was verfügbar ist, nicht was den Speicherplatz wert ist. Mit diesem Set würde ich anfangen. Die Namen in der zweiten Spalte stammen aus den Conventions, sofern nicht als eigene (custom) markiert.

Einheit

Zu setzende Attribute

Warum es sich lohnt

Agentenlauf (invoke\_agent)

gen\_ai.agent.name, gen\_ai.agent.version, gen\_ai.conversation.id, error.type, dazu custom: Release, Mandant, Endergebnis

Läufe nach Agentenversion und Session gruppieren, Releases vergleichen, Läufe finden, die in einer Übergabe oder einem Fehler endeten

Modellaufruf (chat)

gen\_ai.operation.name, gen\_ai.provider.name, gen\_ai.request.model, gen\_ai.response.model, gen\_ai.response.finish\_reasons, gen\_ai.usage.input\_tokens, gen\_ai.usage.output\_tokens, Zahlen für Cache-Read- und Reasoning-Tokens, error.type

Kosten pro Aufruf, Abbrüche (Finish Reason length), Cache-Trefferquote, Modell-Fallbacks, welche Providerfehler dominieren

Request-Einstellungen

gen\_ai.request.temperature, gen\_ai.request.max\_tokens, gen\_ai.request.reasoning.level, gen\_ai.prompt.name, gen\_ai.prompt.version

Verhaltensänderungen erklären, Qualität an eine Prompt-Version binden

Tool-Aufruf (execute\_tool)

gen\_ai.tool.name, gen\_ai.tool.call.id, gen\_ai.tool.type, error.type, dazu custom: lesend oder schreibend, Freigabe erteilt

Fehlerrate und Latenz pro Tool, Schreibaktionen und ihre Freigeber finden

Retrieval

gen\_ai.data\_source.id, dazu custom: Top-k, Trefferzahl, Dokument-IDs ohne Inhalt

Leeres oder schwaches Retrieval erkennen, bevor das Modell es hinter einer flüssigen Antwort versteckt

Inhalt

gen\_ai.system\_instructions, gen\_ai.input.messages, gen\_ai.output.messages, gen\_ai.tool.call.arguments, gen\_ai.tool.call.result (alle Opt-in)

Debugging und Testfälle, zum Preis von Datenschutz und Speicher (siehe Abschnitt PII)

Evaluation

gen\_ai.evaluation.name, gen\_ai.evaluation.score.value, gen\_ai.evaluation.score.label, gen\_ai.evaluation.explanation

Qualitätssignal direkt an dem Span, den es bewertet

Setze die Attribute, die ein Sampler brauchen könnte, schon beim Erzeugen des Spans. Die Conventions nennen gen\_ai.operation.name, gen\_ai.provider.name, gen\_ai.request.model und die Serveradresse (bei Agenten-Spans zusätzlich gen\_ai.agent.name) als die Attribute, die bei der Erzeugung vorliegen SOLLTEN, weil ein Head-Sampler später ergänzte Attribute nicht sehen kann.

## Token- und Kostenmetriken

Spans liefern Detail pro Lauf, Metriken liefern günstige, langlebige Trends. Die Conventions definieren Token-Usage-Counter pro Kategorie (Input, Output, Cache Read, Cache Write, Reasoning), aufgeteilt nach Modalität, und beschreiben sie als primäre Instrumente für den Verbrauch und als Näherung für die Kosten. Daneben gibt es Histogramme für die Token-Verteilung pro Operation, gedacht für p95- und p99-Ausreißer und ausdrücklich nicht für Summen oder Kosten. Für Agenten gibt es Histogramme für die Dauer einer Invocation, die Zahl der Inference-Aufrufe und die Zahl der Tool-Aufrufe pro Invocation sowie eine Tool-Ausführungsdauer. Die letzten beiden würde ich zuerst aufs Dashboard legen: Sie zeigen eine Schleife, bevor es die Rechnung tut.

Achte auf die Arithmetik. Die Input-Token-Zahl SOLL gecachte Tokens enthalten, und die Zahlen für Cache Read, Cache Write und Reasoning sind Teilmengen der Input- und Output-Summen. Wer sie als getrennte Posten addiert, zählt doppelt. Die Conventions definieren außerdem **kein Preis- oder Kostenattribut**, Kosten rechnest du also selbst: Token-Kategorien mal einer Preistabelle pro Antwortmodell, im Backend oder in einer Pipeline-Stufe, und versioniere diese Tabelle. Was du tun kannst, sobald du die Zahlen siehst, steht im [Artikel zu LLM-Kosten, Latenz und Prompt Caching](https://balazscsorba.com/de/blog/llm-cost-latency-prompt-caching-routing).

Halte die Metrik-Dimensionen niedrig in der Kardinalität: Modell, Provider, Agentenname, Operation, Ergebnis. Eine User-ID oder Konversations-ID gehört an einen Span, nicht an eine Metrik, sonst wächst deine Metrikrechnung mit deiner Nutzerbasis.

## Sampling: die interessanten Läufe behalten

Agenten-Traces sind größer als normale Web-Traces, und mit Inhaltserfassung können sie viel größer sein. Du wirst samplen. OpenTelemetry unterscheidet **Head Sampling** (die Entscheidung fällt beim Start des Traces, etwa ein fester Prozentsatz nach Trace-ID) von **Tail Sampling** (die Entscheidung fällt, nachdem alle oder die meisten Spans bekannt sind, sodass du Traces mit Fehlern oder hoher Latenz immer behalten kannst). Die Dokumentation ist offen bei den Kosten: Tail Sampling ist schwerer zu implementieren und zu betreiben, und die Komponente, die entscheidet, muss zustandsbehaftet sein.

Für Agenten würde ich eine einfache Policy nutzen und die Prozentwerte als Startpunkt zum Nachjustieren verstehen:

-   **100 % behalten** bei Läufen mit Fehler, Timeout, Übergabe an einen Menschen oder Nutzerbeschwerde.
-   **100 % behalten** bei Läufen, die bei Kosten, Dauer oder Zahl der Modellaufrufe weit über dem Normalen liegen. Das sind deine Schleifen.
-   **100 % behalten** bei Läufen, die einen Eval nicht bestanden haben, und bei Läufen in einem Canary-Release.
-   **Einen kleinen Anteil samplen**, sagen wir 5 bis 10 Prozent, vom Rest, damit du eine repräsentative Baseline behältst.
-   **Raten nicht aus gesampelten Traces ableiten.** Berechne Raten und Alarme aus Metriken (den oben genannten Dauer-, Token- und Tool-Call-Instrumenten), nicht durch Zählen gesampelter Traces.

Zwei agentenspezifische Fallen. Ein Lauf kann Minuten dauern, also muss der Tail-Sampler lange genug warten, bevor er entscheidet, und währenddessen jeden Span dieses Laufs im Speicher halten. Und ein Eval-Score kommt meist an, nachdem der Trace abgeschlossen und exportiert ist, kann die Tail-Entscheidung also nicht steuern, außer du bewertest inline. Wenn fehlgeschlagene Evals das Sampling überleben sollen, führe entweder einen billigen Inline-Check bei jedem Lauf aus oder hänge den Score später an und sorge dafür, dass der aussortierte Trace für die markierten Läufe noch verfügbar ist.

## PII und sensible Inhalte in Traces

Prompts, Tool-Argumente und Tool-Ergebnisse enthalten, was deine Nutzer und Systeme enthalten: Namen, E-Mail-Adressen, Bestellnummern, Vertragstexte, manchmal Geheimnisse. Die Conventions beziehen klar Stellung. Instruktionen, Eingaben und Ausgaben gelten als sensibel und oft groß, daher SOLLEN Instrumentierungen sie standardmäßig nicht erfassen und ein Opt-in anbieten. Sie beschreiben drei Muster: nichts aufzeichnen (der Standard), Inhalte in Span-Attributen aufzeichnen oder Inhalte extern speichern und nur Referenzen an den Spans ablegen. Das Letzte ist in Produktion das empfohlene Muster, weil externer Speicher eigene Zugriffskontrollen hat.

Daraus ergibt sich ein praktisches Setup:

-   **Produktions-Standard:** nur Metadaten. Modell, Tokens, Finish Reason, Tool-Namen, Fehlertypen, IDs. Erstaunlich viel Debugging funktioniert damit.
-   **Vorproduktion und Tests:** vollständiger Inhalt auf den Spans, weil es keine echten personenbezogenen Daten gibt und du maximale Sichtbarkeit willst.
-   **Inhalte in Produktion:** nur über das Muster mit externem Speicher, für eine gesampelte oder markierte Teilmenge, mit kurzer Aufbewahrung und Zugriff nur für die, die ihn brauchen. Die Conventions erlauben einen In-Process-Hook, der Inhalte vor dem Aufzeichnen ändern oder schwärzen kann, und dieser Hook läuft unabhängig von der Sampling-Entscheidung.
-   **Vor dem Export schwärzen**, nicht im Backend. Eine Verarbeitungsstufe in deiner Telemetrie-Pipeline oder ein In-Process-Hook kann Muster wie E-Mail-Adressen und Kartennummern entfernen. Verlass dich nicht darauf, dass der Anbieter das erledigt, nachdem die Daten dein Netz verlassen haben.
-   **Pseudonyme IDs nutzen** für Nutzer und Konversationen, nie rohe E-Mail-Adressen oder Namen, damit du einen Lauf finden kannst, ohne dass der Trace zum Personendaten-Register wird.

Tool-Argumente verdienen besondere Aufmerksamkeit, weil sie oft der identifizierendste Teil eines Laufs sind und leicht vergessen werden. Wenn deine Traces die EU verlassen oder bei einem US-Anbieter landen, gelten dieselben Regeln wie für die Modell-API selbst, siehe [DSGVO und LLM-APIs](https://balazscsorba.com/de/blog/gdpr-llm-api-eu-data-residency). Prompt-Inhalt in Traces ist außerdem eine Quelle für Prompt Injection: Ein Trace-Viewer, der nicht vertrauenswürdige Modellausgabe rendert, ist ein Ziel, ein weiterer Grund, den Zugriff eng zu halten.

## Traces mit Evals verbinden

Traces sagen dir, was passiert ist, Evals sagen dir, ob es gut war. Am nützlichsten sind sie zusammen. Die Conventions definieren ein **gen\_ai.evaluation.result**\-Event mit Evaluationsname, Score-Wert, lesbarem Label, Erklärung und der Response-ID und sagen, dass es dem bewerteten GenAI-Operation-Span untergeordnet sein SOLL oder die Response-ID tragen soll, wenn kein Span verfügbar ist. Ein LLM-Judge oder eine regelbasierte Prüfung, die nachträglich läuft, kann ihr Urteil so direkt auf den bewerteten Knoten schreiben.

Ich nutze diese Verbindung auf drei Arten. **Offline:** Lass das Eval-Dataset durch denselben instrumentierten Agenten laufen, markiere die Traces mit einer Lauf- oder Release-Kennung (ein eigenes Attribut) und vergleiche Kosten, Schrittzahl und Score pro Release an einem Ort. **Online:** Bewerte eine Stichprobe der Produktionsläufe und alarmiere bei sinkender Bestehensquote, mit den fehlgeschlagenen Traces einen Klick entfernt. **Feedback-Schleife:** Wenn ein Produktions-Trace fehlschlägt, kopiere seine Eingabe (und das erwartete Verhalten) ins Testset. Dafür muss der Inhalt erfasst sein, nutze also für die markierten Läufe das Muster mit externem Speicher. Wie du die Evals selbst baust, steht in [LLM-Evals für Produkt-Features](https://balazscsorba.com/de/blog/llm-evals-for-product-features).

## Tool-Optionen

Das Schöne an OTLP: Die Wahl des Backends kommt zuletzt. Das habe ich in der Dokumentation der Anbieter selbst geprüft:

Tool

Wie es OpenTelemetry annimmt

Gut zu wissen

Langfuse

OTLP-Endpunkt unter /api/public/otel mit Basic Auth, HTTP/JSON und HTTP/protobuf, kein gRPC. Mappt gen\_ai-Attribute, OpenInference und eigene langfuse-Attribute

LLM-spezifische Funktionen obendrauf (Prompt-Verknüpfung, Scoring, Kosten-Tracking), selbst hostbar. Das Repository steht unter MIT, außer den ee-Verzeichnissen mit separater Lizenz

Arize Phoenix

Baut auf OpenTelemetry auf, nutzt die OpenInference-Conventions, die OTel ergänzen, lokaler Collector unter /v1/traces

Open Source und selbst gehostet, unter der Elastic License 2.0. Arize AX ist die verwaltete Variante, stark für Experimente und Evals

Datadog LLM Observability

OTLP über HTTP/protobuf mit dd-api-key-Header, verlangt die gen\_ai-Form ab OpenTelemetry 1.37

Spans ohne gen\_ai-Attribut werden verworfen, laut Doku vergehen einige Minuten, bis Traces erscheinen. Am besten, wenn du schon auf Datadog bist

Honeycomb

OTLP über gRPC, HTTP/protobuf und HTTP/JSON, mit API-Key-Header und EU-Endpunkt

Ein allgemeines Trace-Backend: Die Ingest-Doku, die ich gelesen habe, sagt nichts GenAI-Spezifisches, die Ansichten baust du selbst

Meine Empfehlung: Instrumentiere mit OpenTelemetry und einer eigenen dünnen Helferschicht, exportiere über eine Pipeline-Stufe unter deiner Kontrolle, zum Beispiel einen OpenTelemetry Collector (ein naheliegender Ort für Schwärzen, Sampling und Kostenanreicherung), und wähle das Backend nach Hosting-Modell und nach dem, was dein Team schon betreibt. Wenn Datenresidenz zählt, ist ein selbst gehostetes Langfuse oder Phoenix am leichtesten zu verteidigen. Wenn du schon für eine allgemeine Observability-Plattform zahlst, prüfe, wie gut sie gen\_ai-Spans darstellt, bevor du ein weiteres Tool ergänzt. Andere Anbieter, etwa den Grafana-Stack, habe ich nicht geprüft und lasse sie bewusst weg.

## Eine Checkliste für den ersten Sprint

In dieser Reihenfolge würde ich vorgehen:

1.  Wähle das OTLP-Backend und setze eine Pipeline-Stufe unter deiner Kontrolle dazwischen. Schwärzen und Sampling machst du dort.
2.  Installiere die Instrumentierung für deinen Provider oder dein Framework, pinne die Version und prüfe einen echten exportierten Span gegen die Conventions (inklusive der Variable OTEL\_SEMCONV\_STABILITY\_OPT\_IN).
3.  Füge pro Lauf einen invoke\_agent-Root-Span hinzu und manuelle execute\_tool-Spans für deine eigenen Tools.
4.  Setze Modell, Provider, Token-Verbrauch, Finish Reason und Fehlertyp auf jedem Modell-Span, ergänze Agentenversion, Release und eine pseudonyme Konversations-ID.
5.  Schalte die Inhaltserfassung in Produktion aus und in der Vorproduktion an. Entscheide den Weg über externen Speicher für markierte Läufe.
6.  Baue drei Dashboards: Modell- und Tool-Aufrufe pro Lauf (p50, p95), Tokens und berechnete Kosten pro Agentenversion, Fehler- und Timeout-Rate pro Tool.
7.  Ergänze die Sampling-Policy: alle Fehler, Ausreißer und fehlgeschlagenen Evals, ein kleiner Anteil vom Rest.
8.  Schreibe Eval-Ergebnisse als gen\_ai.evaluation.result-Events an die bewerteten Spans und speise fehlgeschlagene Traces zurück ins Testset.
9.  Füge einen Golden-File-Test hinzu, der fehlschlägt, wenn sich die Form der Instrumentierungsausgabe ändert.

Wenn du mit einem Harness arbeitest, zahlt sich dieselbe Instrumentierung auch dort aus, siehe [Harness Engineering für Coding-Agenten](https://balazscsorba.com/de/blog/harness-engineering-coding-agents).

## Wo ich noch nicht zu viel investieren würde

Baue keine tiefe, maßgeschneiderte Analytik auf den exakten Attributnamen eines Standards im Status Development. Baue auf den Konzepten: ein Baum aus Spans mit Token-Zahlen, Ergebnissen und Scores, und halte die Zuordnung von Konzept zu Attributname an einer einzigen Stelle. Die Conventions werden sich weiterbewegen, und die Backends werden aufholen. Ein Team, das jeden Lauf tracet und die Frage „was hat dieser Lauf getan und was hat er gekostet“ beantworten kann, ist weiter als eines, das wartet, bis sich der Standard setzt.

## Quellen

1.  [OpenTelemetry: GenAI semantic conventions repository (open-telemetry/semantic-conventions-genai)](https://github.com/open-telemetry/semantic-conventions-genai)
2.  [GenAI conventions: overview (status Development)](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/README.md)
3.  [GenAI conventions: model spans, execute\_tool and content capture](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)
4.  [GenAI conventions: agent spans](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md)
5.  [GenAI conventions: metrics](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-metrics.md)
6.  [GenAI conventions: inference token metrics](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-token-metrics.md)
7.  [GenAI conventions: events (gen\_ai.evaluation.result)](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-events.md)
8.  [GenAI conventions: Model Context Protocol](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/mcp.md)
9.  [OpenTelemetry docs: GenAI conventions moved notice](https://opentelemetry.io/docs/specs/semconv/gen-ai/)
10.  [OpenTelemetry docs: Sampling](https://opentelemetry.io/docs/concepts/sampling/)
11.  [John Hodge: The state of the OpenTelemetry GenAI semantic conventions (July 2026)](https://john-hodge.com/blog/opentelemetry-genai-semantic-conventions/)
12.  [Langfuse docs: OpenTelemetry integration](https://langfuse.com/docs/opentelemetry/get-started)
13.  [Langfuse repository and licence](https://github.com/langfuse/langfuse)
14.  [Arize Phoenix repository](https://github.com/Arize-ai/phoenix)
15.  [Arize OpenInference repository](https://github.com/Arize-ai/openinference)
16.  [Datadog docs: OpenTelemetry instrumentation for LLM Observability](https://docs.datadoghq.com/llm_observability/instrumentation/otel_instrumentation/)
17.  [Honeycomb docs: Send data with OpenTelemetry](https://docs.honeycomb.io/send-data/opentelemetry/)

## Häufige Fragen

Was sind die OpenTelemetry GenAI Semantic Conventions?

Sie sind die Standardnamen für Attribute, Spans, Metriken und Events von Generative-AI-Workloads: gen\_ai.operation.name, gen\_ai.request.model, gen\_ai.usage.input\_tokens, execute\_tool-Spans, invoke\_agent-Spans und mehr. Stand Oktober 2026 werden sie im Repository open-telemetry/semantic-conventions-genai gepflegt, und jedes GenAI-spezifische Element ist weiterhin als Development markiert, nicht als Stable.

Wie tracet man einen LLM-Agenten mit OpenTelemetry?

Erzeuge pro Agentenlauf einen Trace. Umschließe den Lauf mit einem invoke\_agent-Span, jeden Modellaufruf mit einem chat-Span und jeden Tool-Aufruf mit einem execute\_tool-Span, und setze die gen\_ai-Attribute für Modell, Token-Verbrauch, Finish Reason und Fehler. Nutze eine Instrumentierungsbibliothek für deinen Provider oder dein Framework, ergänze manuelle Spans für eigene Tools und exportiere per OTLP.

Sollte ich Prompts und Antworten in Traces loggen?

Standardmäßig nicht. Die Conventions stufen Instruktionen, Eingaben und Ausgaben als sensibel und groß ein, weisen Instrumentierungen an, sie ohne Opt-in nicht zu erfassen, und empfehlen in Produktion, Inhalte extern zu speichern und nur Referenzen am Span abzulegen. Erfasse vollständige Inhalte in der Vorproduktion oder für eine gesampelte, zugriffsbeschränkte Teilmenge.

Wie verfolge ich LLM-Token-Verbrauch und Kosten mit OpenTelemetry?

Erfasse gen\_ai.usage.input\_tokens und gen\_ai.usage.output\_tokens auf jedem Inference-Span und nutze die Token-Usage-Counter für Dashboards. Die Conventions definieren Token-Zahlen, keine Preise. Die Kosten berechnest du also im Backend oder in der Pipeline aus einer Preistabelle pro Antwortmodell. Gecachte und Reasoning-Tokens sind Teilmengen der Input- und Output-Summen.

Welches Tool ist das beste für LLM-Observability: Langfuse, Phoenix, Datadog oder Honeycomb?

Das hängt davon ab, was du schon betreibst. Langfuse und Arize Phoenix sind auf LLMs ausgerichtet und selbst hostbar, Datadog LLM Observability passt zu Teams, die schon auf Datadog sind, und verlangt gen\_ai-Attribute ab OpenTelemetry 1.37, und Honeycomb ist ein allgemeines OTLP-Trace-Backend. Instrumentiere zuerst mit OpenTelemetry, dann bleibt das Backend eine austauschbare Entscheidung.

Wie verbinde ich Traces mit Evals?

Hänge Eval-Ergebnisse an den Span, den sie bewerten. Die GenAI Conventions definieren ein gen\_ai.evaluation.result-Event mit Name, Score, Label und Erklärung, das dem bewerteten Span untergeordnet sein soll. Lass Offline-Evals durch denselben instrumentierten Code laufen und mache aus fehlgeschlagenen Produktions-Traces neue Testfälle.

Geschrieben von Balázs Csorba

Senior Fullstack & AI Engineer in der Steiermark – über 10 Jahre Vue, Nuxt, Node.js und PHP, heute baue ich Werkzeuge für KI-Agenten.

[KI-Entwicklung & MCP-Server →](https://balazscsorba.com/de/expertise/ai-engineer)[Über mich →](https://balazscsorba.com/de/about)

## Weitere Artikel

-   [Prompting vs. RAG vs. Fine-Tuning vs. Distillation: Entscheidungshilfe für 2026](https://balazscsorba.com/de/blog/fine-tuning-vs-rag-vs-prompting)
-   [Claude Opus 5.5 holt Platz 1 bei Artificial Analysis – die eigentliche Story ist medium](https://balazscsorba.com/de/blog/artificial-analysis-leaderboard-claude-opus-5-5)
-   [Typisierte Entscheidungen für LLM-Routing und Triage: kalibrierte Konfidenz mit Jev](https://balazscsorba.com/de/blog/jev-typed-decisions-llm-routing)
-   [LLM-Evals für Produktfeatures: von handgelesenen Traces zum CI-Gate](https://balazscsorba.com/de/blog/llm-evals-for-product-features)

## Klingt nach dem, was du suchst?

Erzähl mir von deinem Projekt oder deiner Stelle – ich freue mich, von dir zu hören.

[Gespräch buchen](mailto:contact@balazscsorba.com) [Auf LinkedIn vernetzen](https://www.linkedin.com/in/balazs-csorba)
