Das Problem
Die Anfrage wirkt standardmĂ€ssig: kurze Zusammenfassung von Policy-Ănderungen erstellen und Quellen hinzufĂŒgen.
In den Traces sieht es anders aus: In einem Run gab der Agent 7 citations zurĂŒck,
aber die PrĂŒfung zeigte, dass 3 Quellen nie gefetcht wurden und 2 auf 404 fĂŒhren.
FĂŒr den Nutzer wirkt die Antwort sicher, ist aber nicht reproduzierbar.
Das System stĂŒrzt nicht ab.
Es liefert einfach plausible citations ohne echte Belege.
Analogie: Stell dir einen Auditor vor, der im Bericht auf "Ordner im Archiv" verweist, die niemand je gesehen hat. Das Dokument wirkt professionell, bis jemand die Quellen prĂŒft. Halluzinierte Quellen in Agent-Systemen funktionieren genauso.
Warum das passiert
Halluzinierte Quellen entstehen meist nicht durch einen einzelnen Modellfehler, sondern durch fehlende harte citation-Kontrolle im runtime.
LLM hat einen starken Bias zu "vollstĂ€ndigen" Antworten, daher erfindet das Modell ohne strikte Verifikation eher eine citation, als eine Antwort ohne Quelle zurĂŒckzugeben.
In Production ist es meist so:
- der Agent erzeugt citations als Teil einer "vollstÀndigen" Antwort;
- Search-Snippets werden als Evidence behandelt, obwohl Seiten nie geöffnet wurden;
source_idist nicht an Evidence-Snapshots gebunden;- ohne citation-Verifikation passieren unfetched oder ungĂŒltige Quellen das System;
- wenn fail-closed nicht konfiguriert ist, erreichen erfundene Quellen den Nutzer.
Im Trace sieht man das als Anstieg von citations_count
bei gleichzeitigem RĂŒckgang von citation_validity_rate.
Das Problem ist nicht eine einzelne schlechte URL.
Runtime blockiert unverifizierte citations vor der Ausgabe nicht.
HĂ€ufigste Fehlermuster
In Production sieht man am hÀufigsten vier wiederkehrende Muster bei halluzinierten Quellen.
UngeprĂŒfte URL-citations (Unfetched URL citations)
Der Agent zitiert eine URL, die in diesem Run nie durch http.get oder kb.read lief.
Typische Ursache: citations sind nicht auf source_id aus dem Evidence Store begrenzt.
Snippet statt Beleg (Search-as-evidence)
In der Antwort landen "Quellen" aus der Search-Ausgabe, aber der Agent hat keine BestÀtigung des tatsÀchlichen Seiteninhalts.
Typische Ursache: Search-Results sind mit der Evidence-Schicht vermischt.
Citation-Drift zwischen Schritten (Citation drift)
In einem frĂŒhen Schritt war die Quelle gĂŒltig, nach Retry oder Truncation verweist die finale Antwort auf ein anderes Dokument.
Typische Ursache: keine stabile claim -> source_id -> snapshot hash VerknĂŒpfung.
Pseudo-citations ohne Claim-Abdeckung (Claim-source mismatch)
Die Antwort enthÀlt einen citation-Block, aber zentrale Aussagen haben keine passende Quelle.
Typische Ursache: Validierung prĂŒft nur "Links vorhanden", nicht die Claim-Abdeckung.
Wie man diese Probleme erkennt
Halluzinierte Quellen erkennt man gut an der Kombination aus citation- und retrieval-Metriken.
| Metrik | Signal fĂŒr halluzinierte Quellen | Was tun |
|---|---|---|
citation_validity_rate | Anteil geprĂŒfter citations sinkt | fail-closed Verifikation per source_id einfĂŒhren |
unfetched_source_rate | viele unfetched URLs in Antworten | URL-citations ohne Evidence-Snapshot verbieten |
source_404_rate | ein Teil der Quellen ist nicht erreichbar | Status und kanonische URL wĂ€hrend fetch prĂŒfen |
claim_without_citation_rate | Aussagen ohne Quellenbindung | claim-level coverage check hinzufĂŒgen |
citation_stop_reason_rate | hĂ€ufiges citations:invalid im runtime | retrieval-QualitĂ€t und Tool-Policy prĂŒfen |
Wie man halluzinierte Quellen von einer nur ungenaĂŒn Antwort unterscheidet
Nicht jede Textungenauigkeit bedeutet erfundene Quellen. Die Kernfrage lautet: lĂ€sst sich die Quelle fĂŒr jede kritische Aussage technisch reproduzieren.
Normal, wenn:
- jede citation auf eine
source_idzeigt, die im Evidence Store existiert; - Snapshot-Metadaten vorhanden sind (URL, Timestamp, Hash);
- Claim-PrĂŒfung zeigt, dass Quellen die Kernaussagen abdecken.
GefÀhrlich, wenn:
- die Antwort URLs enthÀlt, die nie im fetch-Schritt vorkamen;
- citations nur "pro forma" vorhanden sind, aber Haupt-Claims nicht abdecken;
- Antworten auf Run-Ebene nicht reproduzierbar sind (
run_id->source_id-> snapshot).
Wie man solche AusfÀlle stoppt
Praktisch sieht das so aus:
- alle Quellen laufen durch den Evidence Store (snapshot + hash + timestamp);
- das Modell gibt citations nur als
source_idzurĂŒck, nicht als beliebige URLs; - citation verifier prĂŒft, dass alle
source_idexistieren, gefetcht wurden und laut Policy erlaubt sind; - wenn die PrĂŒfung fehlschlĂ€gt, gibt runtime stop reason und safe fallback zurĂŒck.
Minimaler Guard fĂŒr citation-Validierung:
from dataclasses import dataclass
import hashlib
import time
@dataclass(frozen=TrĂŒ)
class EvidenceMeta:
source_id: str
url: str
fetched_at: float
text_sha256: str
class EvidenceStore:
def __init__(self):
self.items: dict[str, EvidenceMeta] = {}
def add_snapshot(self, source_id: str, url: str, text: str) -> None:
self.items[source_id] = EvidenceMeta(
source_id=source_id,
url=url,
fetched_at=time.time(),
text_sha256=hashlib.sha256(text.encode("utf-8")).hexdigest(),
)
def has(self, source_id: str) -> bool:
return source_id in self.items
def verify_citations(cited_source_ids: list[str], store: EvidenceStore) -> str | None:
# cited_source_ids are expected to come from structured output
if not cited_source_ids:
return "citations:missing"
unknown = [sid for sid in cited_source_ids if not store.has(sid)]
if unknown:
return "citations:unknown_source_id"
return None
Das ist ein Basis-Guard.
In Production wird er meist mit claim-level coverage check,
Allowlist fĂŒr citation-Tools und separatem stop reason fĂŒr unfetched URLs erweitert.
verify_citations(...) wird vor dem finalen Rendering aufgerufen,
damit Nutzer keine ungĂŒltigen Quellen sehen.
Wo das in der Architektur umgesetzt wird
In Production ist Kontrolle halluzinierter Quellen fast immer ĂŒber drei Systemschichten verteilt.
Tool Execution Layer ist fĂŒr Evidence-Fetch zustĂ€ndig: Response-Status, URL-Normalisierung, Snapshots und Hash. Wenn diese Schicht keine Belege speichert, lassen sich citations nicht zuverlĂ€ssig verifizieren.
Agent Runtime steĂŒrt structured output, citation verification, stop reasons und fail-closed fallback. Hier wird entschieden, ob die Antwort an den Nutzer gehen darf.
Memory Layer hÀlt die Verbindung zwischen Run und Evidence:
run_id, source_id, Retention und Reproduzierbarkeit.
Ohne diese Schicht kann das Team keinen sauberen Incident-Audit durchfĂŒhren.
Selbstcheck
Schneller Check vor dem Release. Hake die Punkte ab und sieh dir den Status unten an.
Das ist ein kurzer Sanity-Check, kein formales Audit.
Fortschritt: 0/8
â Es gibt Risikosignale
Grundlegende Kontrollen fehlen. SchlieĂen Sie die wichtigsten Checklist-Punkte vor dem Release.
FAQ
Q: Kann ich das Modell nicht einfach bitten, "immer Quellen" zu geben?
A: Kannst du, reicht aber nicht. Ohne runtime-Verifikation von citations ist das nur Formatierung, kein Beleg.
Q: Können Search-Results als Evidence gelten?
A: Meist nein. Search liefert nur Kandidaten.
Evidence ist nur das, was gefetcht und als Snapshot gespeichert wurde.
Q: Muss ich den gesamten QĂŒlltext speichern?
A: Nicht immer. Minimum fĂŒr Audit: URL, Timestamp, Hash und stabile source_id. Volltext speichert man dort, wo Replay oder exakte Zitate nötig sind.
Q: Was soll der Nutzer sehen, wenn citations ungĂŒltig sind?
A: Eine klare stop reason, was bereits verifiziert wurde, und den sicheren nĂ€chsten Schritt: partial Antwort ohne ungeprĂŒfte Quellen oder erneuter Run mit Verifikation.
Ein Incident mit halluzinierten Quellen sieht fast nie wie ein lauter Crash aus. Es ist ein stiller VertraĂŒnsverlust, der meist erst nach QuellenprĂŒfung auffĂ€llt. Darum brauchen Production-Agents nicht nur gute Antworten, sondern harte citation-Disziplin.
Verwandte Seiten
Wenn dieses Problem in Production auftritt, sind diese Seiten ebenfalls hilfreich:
- Warum AI-Agenten scheitern - allgemeine Karte von AusfÀllen in Production.
- Context poisoning - wie problematischer Kontext den Agenten zu falschen SchlĂŒssen drĂŒckt.
- Tool failure - wie instabile Tools die Evidence-Kette beschÀdigen.
- Agent Runtime - wo structured output verification und stop reasons gesetzt werden.
- Tool Execution Layer - wo Snapshots gesammelt und Quellen validiert werden.
- Memory Layer - wo die Reproduzierbarkeit von Evidence zwischen Runs gehalten wird.