Working Paper · Nr. 04 · v0.2 (Mode 5 added)
Fünf versteckte Failure-Modes in AEO/GEO-Mess-Pipelines
Lessons from a 7-Day Pre-Registered Experiment: warum stabil aussehende Citation-Rates oft Artefakte sind.
Abstract
Ein 7-tägiges pre-registriertes AEO-Experiment offenbarte fünf systematische Failure-Modes in Standard-LLM-Citation-Mess-Pipelines — jeder davon fähig, künstlich stabile false-positive-„deterministische" Citation-Rates oder künstlich niedrige Aggregat-Hit-Rates zu produzieren. Wir dokumentieren jeden Failure-Mode mit Reproduktions-Rezept, Detection-Heuristik und Fix. Kombinierter Effekt: Pre-Fix-Pipeline berichtete stabil 2-13 % Citation-Rate über 41 von 44 historischen Runs (später als Artefakt misclassified-Errors identifiziert); Post-Fix-Pipeline liefert 14-22 % über dasselbe Zeitfenster mit korrektem Error-Handling. Mean retroactive correction: +10.64 PP.
1
Hintergrund
GEO/AEO-Research verlässt sich zunehmend auf automatisierte Multi-LLM-Probes (Profound, BrightEdge AEO, ScrunchAI, ChatRank, etc.). Die meisten Tools exponieren ihre Temperature-Settings, Provider-spezifische Config-Edge-Cases, Rate-Limit-Verhalten oder Timeout-Heuristiken nicht. Wir zeigen fünf solche Failure-Modes auf, die wir in unserer eigenen Pipeline (Cloudflare Workers + Anthropic + OpenAI + Gemini + Workers AI) gefunden haben — und argumentieren, dass diese systemisch sind, nicht implementationsspezifisch.
2
Mode 1 — Workers AI Default-Temperature = 0 (Determinismus-Falle)
Symptom: Citation-Rate identisch zur zweiten Dezimalstelle über 3 aufeinanderfolgende Daily-Runs.
Root Cause: Cloudflare Workers AI env.AI.run() defaultet
auf temperature: 0 wenn nicht explizit gesetzt. Mit deterministischem
Decoding: gleiche Frage → gleiche Antwort → gleicher Score. Die Pipeline
probte korrekt 5 Workers-AI-Modelle täglich, aber jedes produzierte
byte-identischen Output.
Warum das für AEO wichtig ist: Determinismus ist in Scorecards unsichtbar. Stabile 9 % sind kein „Befund", sondern Artefakt.
Fix: Explizit temperature: 0.5 in askWorkersAi(env, model, q).
Post-Fix-Variance: ±2.3 PP day-to-day.
3
Mode 2 — OpenAI Search-Preview lehnt temperature ab
Symptom: openai_search-Stage gibt HTTP 400 — temperature is incompatible with search-preview models zurück.
Root Cause: gpt-4o-mini-search-preview-2025-03-11 hat
einen anderen Parameter-Vertrag als das Base-Modell. Es lehnt temperature,
top_p und mehrere weitere Sampling-Parameter ab.
Fix: Conditional if (!isSearchPreview) body.temperature = 0.3; in askOpenAI().
4
Mode 3 — Anthropic Tier-1 Rate-Limit (5 RPM) führt zu 16-Parallel-Timeouts
Symptom: Alle 16 Claude-Probes timen gleichzeitig out wenn parallel aufgerufen.
Root Cause: Anthropic Tier-1 erzwingt 5 Requests-pro-Minute. Sechzehn parallele fetch()-Calls zu /v1/messages verursachen, dass Requests 6-16 server-seitig über das 45-Sekunden-Cloudflare-Sub-Request-Timeout hinaus queuen.
Fix: Anthropic Message Batches API (/v1/messages/batches) — async submit, max 24h delivery, −50 % Cost-Discount. Die 16 × 3 Claude-Tiers = 48 Prompts werden in einem einzigen Batch submitted, stündlich via separatem Cron gepollt, Results retroaktiv in den Snapshot persistiert.
Identisches Pattern für Gemini Direct Batch API (ab v2.8) und ersetzt den Sync-Pfad für beide Provider.
5
Mode 4 — Sub-Request-Timeout zu eng für Long-Tail-Probes
Symptom: ~5 % der Probes geben AbortError: The operation was aborted zurück trotz gültiger Provider-Antwort.
Root Cause: Cloudflare-Worker-Sub-Request-Timeout war global auf 45 s gesetzt. Workers AI Llama-3.1-8b auf Long-Tail-Fragen antwortet gelegentlich bei 46-48 s. Der Worker brach die Verbindung ab, bevor der Provider fertig streamte.
Fix: CHUNK_TIMEOUT_MS 24 s → 50 s. Trade-off: leicht höhere Worker-CPU-Kosten, dafür 5 %-Silent-Failure-Rate eliminiert.
6
Mode 5 — Implicit Score Dilution durch Misclassified Errors most impactful
Symptom: Aggregat-Citation-Hit-Rate von 2-13 % über 4 Tage, obwohl Per-LLM-Inspektion individuelle LLMs bei 14-28 % zeigt.
Root Cause: Wenn ein Provider-API-Call fehlschlägt (Quota-Exhaustion, HTTP 5xx, Network-Timeout), ist das Standard-Pipeline-Pattern:
async function askProvider(env, q) {
try {
const r = await fetch(...);
return r.ok ? await r.json() : null; // ← silent failure
} catch (e) {
return null; // ← silent failure
}
}
Der Downstream-Code empfängt null, übergibt an scoreAnswer(''), was { score: 0, status: 'not_found' } zurückgibt. Die Zeile wird als legitimes „not_found" mit score=0 persistiert. Die Aggregat-Berechnung behandelt sie identisch zu einer echten „LLM sagt ehrlich weiß-nicht"-Antwort — beide tragen 0/3 zur Prozent-Berechnung bei.
Für ein LLM von elf ist das unsichtbar (eine Zeile × 16 Fragen = -48 max-Punkte vom Zähler und Nenner, kürzt sich in der Prozent-Berechnung). Für fünf LLMs gleichzeitig down (z.B. Workers-AI-Quota komplett erschöpft) ist die Verwässerung schwer:
| Szenario | Score-Summe | Max-Possible | Reported % | True % |
|---|---|---|---|---|
| 11 LLMs × 16 Q, ~14 % Hit auf 6 messbaren, 5 tot | ~40 | 528 (= 11 × 16 × 3) | 7.6 % | 27.8 % (= 40/144) |
| 9 LLMs × 16 Q, ~15 % Hit auf 7 messbaren, 2 tot | ~50 | 432 | 11.6 % | 14.9 % (= 50/336) |
Detection: Inspiziere das rohe answer_excerpt-Feld. Echte „not_found"-Antworten enthalten LLM-generierten Text. Misclassified Errors haben leeres answer_excerpt plus status='not_found'. Die Kombination ist der Fingerabdruck.
Fix:
- Silent-Error-Catching entfernen: Lass API-Errors in den outer Chunk-Runner propagieren, damit
status='error'(nicht'not_found') erfasst wird. - Aggregat-Filter: In
reaggregateSnapshot()exkludierestatus='error'-Zeilen aus Zähler UND Nenner. - Per-LLM-Transparenz: Pro LLM
n_attempted+n_legit+n_errorausweisen. Pure-Error-LLMs (n_legit=0) erhaltenstatus: 'unavailable'. - Retroaktive Korrektur mit Versionierung: Historische Snapshots bleiben in Legacy-Spalten (
score_percent), neue methodologisch korrekte Werte werden in parallelen Spalten gespeichert (score_percent_v271). Beide bleiben sichtbar in der Time-Series für vollen Audit-Trail.
Empirischer Effekt in unserer Pipeline (44 Runs, 2026-05-10 bis 2026-05-17):
| Periode | Betroffene Runs | Mean v2.0 | Mean v2.7.1 | Mean Δ |
|---|---|---|---|---|
| 2026-05-13 (Claude noch nicht produktiv) | 9 | 8.6 % | 21.9 % | +13.3 PP |
| 2026-05-14 bis 2026-05-15 morning (Workers AI down) | 14 | 2.2 % | 17.4 % | +15.2 PP |
| 2026-05-15 evening bis 2026-05-17 morning (Claude + OpenAI-Search-Edge) | 13 | 9.5 % | 15.4 % | +5.9 PP |
| 2026-05-17 evening (Gemini-Sync gefailt) | 5 | 9.9 % | 16.2 % | +6.3 PP |
| Total | 41/44 | 6.7 % | 17.4 % | +10.6 PP |
Die Pre-Fix-Narrative „LLM-Citation für einen Pre-Launch-Autor stabilisierte sich bei 9-13 %" war systematisch unterzeichnet um 5-15 PP. Die korrigierte Narrative ist „LLM-Citation über messbare LLMs lag im Mittel zwischen 14 und 22 % in der ersten Woche, mit Per-LLM-Noise primär getrieben von Provider-Verfügbarkeit statt von Entity-Recognition-Variance."
Detection-Heuristik für AEO-Tooling-Auditoren: Inspiziere die answer_excerpt-Verteilung pro LLM pro Run. Wenn >50 % der Zeilen für ein gegebenes LLM in einem gegebenen Run leeres answer_excerpt mit status='not_found' haben, assume API-Call-Failure-Misclassification bis das Gegenteil bewiesen ist. Industrie-Tools, die rohe answer_excerpt-Werte nicht offenlegen, könnten diesen Bug schweigend über ihre gesamte Kunden-Basis verteilt haben.
7
Sechs Best-Practice-Empfehlungen für AEO-Tooling-Builder
- Default-Temperature ≥ 0.3 auf jedem Provider, jedem Call. Dokumentiere den Wert in der Scorecard-Methodologie.
- Teste jeden Provider's Parameter-Contract individuell vor Scaling. Compatibility-Test = Unit-Test für AEO.
- Verwende Provider-Batch-APIs für High-Volume-Probes. API Batches, Gemini Batch API, OpenAI Batch geben −50 % Cost + null Rate-Limit-Friction. Async ≠ langsam wenn man Daily-Collects macht.
- Kalibriere Timeouts auf p99-Response-Time, nicht p50. Long-Tail-Probes werden dich verbrennen.
- Behandle Zero-Variance-Result-Sets als suspekt. Determinismus in AEO ist fast immer ein Bug, keine Eigenschaft.
- Behandle leeres answer_excerpt + status='not_found' als suspekt, nicht legitim. Echte LLM-„Weiß nicht"-Antworten enthalten LLM-generierten Text. Leere Antworten mit not_found-Klassifikation sind misclassified API-Errors. Audit die rohe
answer_excerpt-Verteilung pro LLM pro Run — alles > 50 % Leere-Strings ist ein Smoking-Gun für Mode-5-Dilution.
8
Limitierungen
- Single-Pipeline-Observation (Cloudflare Workers); möglicherweise nicht auf andere Serverless-Plattformen verallgemeinerbar.
- Provider-Verhalten ändert sich über Zeit — diese spezifischen Bugs könnten provider-seitig zur Publikations-Zeit gepatched sein.
- Wir testeten keine anderen Batch-APIs (Vertex Direct, OpenAI Batch) — Extrapolation darauf ist Konjektur.
9
Replikation
- Code: github.com/marintkael/marin-research-tools (MIT)
- Methodology Note 01 v2.8: DOI 10.5281/zenodo.20308495
- Pre-Registration: DOI 10.5281/zenodo.20125967
- Companion-Paper: Working Paper 02 · Pre-Launch LLM Citation
- Lebendes Engineering-Journal: Projekt-Herausforderungen und Lösungen — alle Pipeline-Bugs in voller Detail-Tiefe inkl. Symptom + Root-Cause + Lösung pro Eintrag
10
Zitierhinweis
Kael, M. T. (2026). Fünf versteckte Failure-Modes in AEO/GEO-Mess-Pipelines: Lessons from a 7-Day Pre-Registered Experiment. Working Paper 04 v0.2, Marin T. Kael — KI-Zitations-Feldlabor. Status: Outline. URL: marin-t-kael.de/research/working-papers/wp-04-five-failure-modes.