Eine minimale, funktionsfähige Experimentierplattform für KI-Agenten: A/B-Tests und Schattenausführungen
Wie man entscheidet, ob die Agentenversion B die Version A ersetzen sollte, unter Verwendung von Pipeline-Definitionen, lokaler Zuweisung, Expositionsereignissen, Spuren, Sandbox-Bewertungen, Schattenläufen und Schutzmechanismen.
Quellen: A minimum viable experimentation platform for AI agents
Es ist schwieriger, zu beurteilen, ob eine neue Agentenversion der im Produktivbetrieb verwendeten überlegen ist, als es auf den ersten Blick scheint. In der Entwicklung ist das Verfahren handhabbar: Man verwendet eine Reihe von Testfällen, führt beide Versionen aus, betrachtet einige Ausgabebeispiele, lässt ein anderes Modell die Ergebnisse bewerten und entscheidet anschließend, ob sich weitere Arbeit lohnt. Die Sache wird schwieriger, wenn das Ziel nicht ein Prompt oder ein einzelner Modellaufruf ist, sondern ein System, dessen Komponenten nach eigenen Zeitplänen ändern und auf Weise miteinander interagieren, die nicht immer offensichtlich sind.
Stellen Sie sich einen Kundenservice-Agenten vor, der aus diesen Komponenten zusammengesetzt ist:
agent runtime
memory and retrieval
system prompt
model
tools
guardrails
application logic
Nehmen wir an, die Abrufstrategie ändert sich und die Aufgabenerfüllung im Testdatensatz steigt. Der Agent könnte tatsächlich besser sein. Es ist auch möglich, dass er mehr Modellaufrufe vornimmt, was 20 Prozent mehr Kosten verursacht, sich bei echten Nutzern anders verhält, oder von einem anderen Komponenten profitiert, der zufällig im selben Zeitraum geändert wurde. In diesem Fall sieht die Aufgabe weniger wie eine Modellbewertung aus und eher wie ein Experiment.
Im Folgenden wird ein Überblick über die kleinste Plattform gegeben, auf die man sich für eine recht einfache Frage verlassen kann:
should version B replace version A?
Das macht nur bei einer bestimmten Größe Sinn. Ein einzelner Agent, zwanzig manuell überprüfte Testfälle sowie eine Handvoll interner Nutzer benötigen den Großteil davon nicht. Die Plattform ist dann nützlich, wenn mehrere Teams unabhängig voneinander Modelle, Anweisungen, Speicher, Tools sowie Agent-Implementierungen ändern, Experimente ununterbrochen laufen und schließlich jemand eine Produktivumstellung unter Verwendung von Belegen genehmigen muss, die auch Monate später noch klar lesbar sind. Eine firmenweite Agent-Plattform entspricht genau dieser Beschreibung.
Was B eigentlich ist
Das erste Problem ist grundlegend. Nehmen wir an, ein Experiment besagt:
A = agent-v17
B = agent-v18
Was ist genau agent-v18? Wenn sich die Anweisung während des Experiments ändert, wird der Abrufindex neu erstellt und das Modellgateway wechselt auf sein Standardmodell – dabei sagt die Kennzeichnung fast nichts darüber aus, was tatsächlich bewertet wurde. Dies trifft Agenten besonders hart, denn das am Ende beobachtete Verhalten stammt aus dem gesamten Pipeline-Prozess und nicht von einer einzelnen, isolierten Modellaufrufung.
Daher ist die unveränderliche Pipeline-Definition das zu bewertende Konzept. Sie kann wie folgt aussehen:
pipeline:
name: support-agent
version: 18
components:
runtime:
artifact: agent-runtime@sha256:...
memory:
artifact: memory-service@sha256:...
configuration:
strategy: hybrid
top_k: 8
model:
route: support
model: provider/model-x
prompt:
artifact: sha256:...
tools:
- artifact: customer-lookup@sha256:...
- artifact: refund-tool@sha256:...
Das genaue Artefaktformat spielt kaum eine Rolle. Entscheidend ist, dass eine Variante als Systemkonfiguration rekonstruiert werden kann, sodass Monate später jemand feststellen kann, was ein dem B zugewiesener Benutzer eigentlich ausführen sollte. Dadurch bleibt die Experimentierplattform unabhängig von den jeweils aktuellen Veränderungen. Ein Experiment könnte beispielsweise Folgendes vergleichen:
model X vs model Y
Ein anderer könnte vergleichen:
memory top_k=5 vs top_k=8
Eine dritte Variante könnte zwei völlig unterschiedliche Implementierungen von Agenten gegeneinander antreten lassen. Aus Sicht des Experiments ist jede dieser Varianten lediglich eine andere Form eines Pipelines. Sobald ein Experiment beginnt, werden diese Definitionen festgelegt. Wenn sich die Behandlung ändern muss, wird eine neue Iteration des Experiments erstellt, sodass die historische Bedeutung von B niemals heimlich überschrieben wird.
Die Zuweisung sollte keine Abhängigkeit in der Produktion darstellen
Dann stellt sich die Frage, wer A und wer B erhält. Ein verlockendes Design sieht vor, dass jede Anfrage einen zentralen Experimentierdienst um die entsprechende Behandlung bittet. Dadurch wird die Experimentierplattform in das Verfügbarkeits- und Latenzbudget der Anwendung selbst einbezogen – was für ein System, dessen Hauptzweck die Messung ist, ein schlechter Kompromiss darstellt.
Die erste Version verwendet deterministisches Hashing. Die Steuerungsplattform sendet ihre aktuelle Konfiguration an ein SDK, das innerhalb der Anwendung vorhanden ist, und die Auswahl des Einsatzes erfolgt direkt dort, lokal. Dadurch entsteht eine nützliche Fehlereigenschaft: Wenn der Experimentdienst ausfällt, kann die Plattform vorübergehend keine neuen Experimente starten oder Zuweisungen ändern, doch die Anwendung bleibt unberührt und das SDK arbeitet weiter mit seiner letzten gültigen Konfiguration.
Für das MVP reichen einige Randomisierungsmechanismen aus:
request
user
session
workflow_instance
Die letzte Variante existiert, weil Agenten nicht unbedingt so lange aktiv sind wie eine Webanfrage. Ein Agent kann heute mit der Migration eines Repositoriums beginnen, auf eine externe Genehmigung warten und am nächsten Tag fortfahren. Würde die Zuweisung anhand der Konfiguration von morgen neu berechnet, könnte derselbe Workflow bei einer Implementierung beginnen und bei einer anderen enden, wodurch sowohl die Operationen als auch die Analyse unnötig erschwert würden. Die Zuweisung bleibt daher unverändert:
workflow_instance = migration-8291
variant = B
pipeline = agent-v18
und es wird jedes Mal mit dem Workflow weitergeleitet, wenn dieser wieder aufgenommen wird.
Zuweisung unterscheidet sich von Ausführung
Eine weitere Unterscheidung wird wichtig, wenn die Behandlung irgendwo innerhalb eines Agenten-Pipelines stattfindet. Das Eintreffen in einem Behandlungsarm garantiert nicht, dass die Behandlung tatsächlich ausgeführt wurde.
Nehmen wir zwei im Test befindliche Speichermanifestationen. Ein Benutzer gelangt zur neuen Speicherversion B, doch der Agent antwortet, ohne eine Speichersuche durchzuführen. Die Zuweisung existiert zwar, doch der getestete Komponente hatte nie die Gelegenheit, das Ergebnis zu beeinflussen. Dies sollten zwei getrennte Ereignisse sein:
ASSIGNMENT
user-18271 → B
EXPOSURE
memory-v2 retrieval started
Dies liefert auch Informationen zur Experimentqualität. Neben der Anzahl der Nutzer, die einer jeden Gruppe zugeordnet wurden, kann das Expositionsprofil überprüft werden:
assigned 10,428
exposed 8,912
exposure rate 85.46%
Falls A und B unerwartet unterschiedliche Expositionsraten aufweisen, verdient dieser Unterschied zunächst Aufmerksamkeit.
Ein damit verbundenes Problem tritt auf, wenn die zugewiesene Behandlung nicht die ist, die tatsächlich ausgeführt wird. Angenommen, B wählt Modell Y, Modell Y gibt einen 503-Fehler aus und der Gateway wechselt auf X. Die Aufzeichnung lautet dann:
assigned_variant = B
realized_model = X
fallback_reason = provider_unavailable
und die Ausführung bleibt bei B.
Dies folgt der Intent-to-Treat-Regel, ITT. Jeder Proband wird in der Gruppe analysiert, in die er zufällig eingeteilt wurde, selbst wenn die tatsächlich durchgeführte Behandlung anders ist. Der Rückgriff auf diese Variante gehört zum Verlauf bei B, und das Später Entfernen solcher Anfragen würde die Stichprobe aufgrund eines nach der Zufallsauswahl eingetretenen Ereignisses umgestalten. Die Daten zur Exposition und zur tatsächlich erhaltenen Behandlung bleiben wertvoll, hauptsächlich als Gesundheits- und Diagnoseindikatoren, es sei denn, die Analyse besagt etwas anderes.
Tracing erklärt, was passiert ist
Ein Experimentsergebnis gibt an, ob sich ein Ausgangswert geändert hat, sagt aber nichts darüber aus, warum. Für die Erklärung des „Warums“ ist OpenTelemetry die sinnvolle Wahl, nicht ein neues Tracing-Protokoll. Die Experimentier-Schicht muss lediglich etwas zusätzlichen Kontext zu jedem Span hinzufügen:
experiment.id
experiment.version
experiment.variant
experiment.assignment_id
pipeline.id
pipeline.version
execution.purpose
Sobald das eingestellt ist, ergibt sich ein zusammenfassendes Ergebnis wie folgt:
B has a lower task completion rate
kann zu einer weitaus nützlicheren Anfrage werden:
show failed B traces
Die Spuren zeigen an, ob der neue Pipeline schwächere Kontexte verwendet, Toolaufrufe wiederholt, auf ein anderes Modell wechselt, in Schleifen stecken bleibt oder einfach einen längeren Weg zum selben Ergebnis nimmt.
Eine Spur ist jedoch noch nicht die Protokollierung des Experiments. Sie erklärt gut, wie eine Ausführung abgelaufen ist, doch die Ergebnisse des Experiments können darüber hinaus bestehen bleiben. Ein Kunde könnte heute mit einem Agenten sprechen und eine Woche später, lange nachdem die ursprüngliche Spur beendet wurde, ein Abonnement erneuern. Daher läuft neben der Protokollierung ein kleinererer Ereignisstrom für Experimente:
assignment
exposure
outcome
feedback
evaluation
Die Spur protokolliert die Ausführung. Der Ereignisstrom übernimmt die Buchhaltung, die die Zufällisierung mit später einlaufenden Ergebnissen verknüpft.
Die Offline-Bewertung verwendet denselben Ablauf
Bevor B bei den Produktionsnutzern ankommt, sollte es bekannte Szenarien abdecken. Bei Agenten sollte ein Szenario nicht auf Folgendes reduziert werden:
prompt
expected answer
Denn das interessante Ergebnis ist oft nicht der zurückgegebene Text, sondern der Zustand der Umgebung danach. Ein Support-Szenario könnte so formuliert werden:
scenario:
id: duplicate-charge-001
input:
message: >
I was charged twice for order 9811.
environment:
fixture: duplicate-charge-customer
expected:
refund_count: 1
ticket_status: resolved
limits:
max_turns: 15
max_tool_calls: 20
max_cost: 0.50
Das gleiche Szenario wird anschließend mit Pipeline A und Pipeline B durchgeführt, möglicherweise mehrmals, da die Ausführungen der Agenten stochastisch sind und zwei Durchläufe derselben Konfiguration von demselben Ausgangszustand aus unterschiedliche Entwicklungspfade einschlagen können. Das MVP verwendet einen zurücksetzbaren Sandbox mit von Fixtures unterstützten Diensten oder Testdatenbanken. Die Erstellung einer allgemeinen Mehrschritt-Wiedergabe sollte lieber auf später verschoben werden.
Die Wiedergabe funktioniert nur solange, bis der Kandidat Interaktionen anfordert, die bereits aufgezeichnet wurden. Angenommen, B entscheidet sich in Schritt drei anders und ruft ein Tool auf, das im ursprünglichen Ablauf nie verwendet wurde. Dann enthält keine der aufgezeichneten Welten diesen Zweig. Das ehrliche Ergebnis ist:
REPLAY_DIVERGED
Eine fiktive Antwort, die vorgibt, dass der Lauf immer noch eine Wiederholung ist, ist der falsche Ansatz. Ein zustandsbasiertes Sandbox-Umfeld ermöglicht es beiden Agenten, sich natürlicherweise zu verzweigen, während ihre Ausgangsbedingungen kontrolliert werden – das ist eine bessere erste Annäherung an die Bewertung echter Agenten.
Schattenausführung schließt die Lücke
Ein nützlicher Schritt zwischen dem kontrollierten Sandbox-Umfeld und der Bereitstellung von B an Benutzer besteht darin, B asynchron auf einer Kopie der echten Produktionsdaten auszuführen, ohne dessen Ausgabe bereitzustellen. Schreibvorgänge sowie externe Nebeneffekte werden deaktiviert oder in eine isolierte Umgebung umgeleitet. Dadurch werden produktionsähnliche Eingaben bereitgestellt, und das Team kann beobachten:
latency
cost
tool usage
model fallbacks
guardrail failures
judge scores
trajectory differences
bevor ein Benutzer die Behandlung sieht.
Shadow Runs können nicht zeigen, ob B das am wichtigsten erscheinende Ergebnis verbessert, da die Benutzer B niemals sehen und daher nicht darauf reagieren können. Sie dienen als Zwischenstufe: realistische Eingaben und echtes Laufzeitverhalten, ohne die Produktrisiken, die mit einem Live-Experiment einhergehen.
Nicht jede Überprüfung benötigt einen LLM-Bewerter
Wenn der Agent ein Szenario beendet hat, muss das Ergebnis dennoch bewertet werden, weshalb die erste Version zwei Arten von Bewertern besitzt.
Die erste Art ist deterministisch. Wenn eine Aufgabe darin besteht, einen einzigen Rückerstattungsbetrag auszuzahlen und ein Ticket zu klären, kann die Umgebung einfach überprüft werden:
refund_count == 1
ticket_status == resolved
Es bringt nichts, ein anderes Modell zu fragen, ob die Aufgabe wahrscheinlich abgeschlossen wurde, wenn der resultierende Zustand überprüft werden kann.
Die zweite Art ist modellbasiert und bezieht sich auf Eigenschaften, die sich gegen Aussagen wehren:
helpfulness
clarity
tone
quality of explanation
Ein LLM-Richter hilft dabei, doch der Richter wird zu einem weiteren versionierten Komponenten und niemals zu einer anonymen Quelle der Wahrheit:
evaluator
evaluator version
judge model
judge prompt
rubric
Jeder generierte Score behält diese Herkunft bei. Es wird außerdem ein kleines, von Menschen beschriftetes Kalibrierungsdatensatz gepflegt, gegen den der Bewertungsalgorithmus regelmäßig abgeglichen wird. Ein LLM-basierter Bewertungsalgorithmus ist ein Messinstrument – wenn sich dieses Instrument ändert, ist es wichtig zu prüfen, ob sich auch seine Messwerte verändert haben. Agentenbasierte Bewertungsalgorithmen, die suchen, Tools aufrufen oder zusätzliche Beweise finden, sind nützlich und in einigen Bereichen vermutlich unvermeidlich – doch sie haben in der ersten Version keinen Platz.
Statistiken, bewusst begrenzt
Reife Experimentiersysteme bieten eine große Anzahl an Fortschritten. Ein besserer Ausgangspunkt ist ein kleiner Satz korrekt implementierter Methoden anstelle eines beeindruckenden, aber von wenigen Nutzern verstandenen statistischen Menüs. Die erste Version unterstützt:
A/B allocation
binary metrics
continuous metrics
95% confidence intervals
sample ratio mismatch detection
fixed-horizon analysis
Das reicht aus, um viele nützliche Fragen zu beantworten, und eine Zusammenfassung des Ergebnisses könnte lauten:
Experiment
support-agent-v18
Randomization
user
Primary metric
ticket resolution
A 81.4%
B 85.1%
Difference
+3.7 percentage points
95% CI
[...]
Experiment health
SRM PASS
Ein Ungleichgewicht im Stichprobenverhältnis erfordert besondere Aufmerksamkeit, denn die Ergebnisse dürfen niemals autoritativ erscheinen, wenn die Randomisierung selbst fehlerhaft zu sein scheint. Wenn ursprünglich ein gleichmäßiger Aufteilungsplan vorgesehen war und die tatsächliche Verteilung deutlich davon abweicht, wird das Experiment als fehlerhaft eingestuft – und damit ist die Sache erledigt, ohne dass ein Gewinner neben einem Warnsymbol angezeigt wird.
Operative Schutzmechanismen gehören ebenfalls zu dieser Ebene der Integrität. Eine Variante kann aus Kostengründen versagen, ohne technisch fehlerhaft zu sein. Stellen Sie sich einen Prompt-Loop vor, der Anfragen weiterleitet:
4 model calls
Zu:
47 model calls
Und die Antwort kann weiterhin HTTP 200 sein, selbst bei einer guten Antwort. Deshalb sind Obergrenzen notwendig:
max cost / execution
max tokens / execution
max agent turns
max tool calls
max variant spend / hour
Durch Überschreiten eines Schwellenwerts kann diese Ausführung gestoppt oder eine weitere Exposition gegenüber der Variante unterbrochen werden. Ein Gesundheitsbericht könnte dann wie folgt lauten:
Variant B
SRM PASS
Error rate PASS
Cost / request +312%
Circuit breaker TRIPPED
New exposure PAUSED
Ein Circuit Breaker ist keine statistische Schlussfolgerung. Es handelt sich um ein Sicherheitsmechanismus zur Betriebssicherheit, der verhindert, dass fehlerhafte Behandlungsweisen Ressourcen und Budget verschlingen, solange das Experiment noch nicht genügend Beobachtungen gesammelt hat, um etwas Statistisches sagen zu können.
Exklusivere Methoden können warten: CUPED, sequentielle Tests, Holdout-Gruppen, Experimentsschichten, klastergestützte Zufallsauswahl, adaptive Zuweisung und vieles mehr. Das Datenmodell sollte Platz für sie lassen, doch die erste Version muss lediglich einfache A/B-Tests korrekt durchführen.
Was zuerst entwickelt werden sollte
Nachdem die meisten aufschiebaren Elemente entfernt wurden, ist die Plattform handhabbar. Sie benötigt einen Kontrolldienst, der Folgendes enthält:
- einen Experimenten-Register
- ein Pipeline-Register
- ein Datensatz-Register
- einen Evaluierer-Register
- Metrikendefinitionen
Darauf befindet sich die SDK, die die Experimentkonfiguration herunterlädt und diese auf der Client-Seite deterministisch zuweist. Ein Eingabepfad ist erforderlich für:
assignment
exposure
outcome
feedback
evaluation
OpenTelemetry-Spuren werden ebenfalls aufgenommen. Geeignete Speichlösungen sind PostgreSQL für den Zustand der Steuerungsplattform, NATS JetStream oder Kafka für Ereignisse, ClickHouse für Experiment- und Spurenanalytik sowie S3-kompatibler Objektspeicher für umfangreiche Artefakte. Ein Offline-Runner verwendet Datensätze in Umgebungen, die zurückgesetzt werden können, um Tests mit A und B durchzuführen.
Viele Funktionen fehlen absichtlich. Das MVP befasst sich nicht mit willkürlicher virtualisierter Umgebungsverwaltung mit Zustand, subtilen Wechselwirkungen zwischen Experimenten, Abweichungen bei der Bewertung, automatisierter Ursachenanalyse, anhaltenden Behandlungseffekten oder kausaler Zuordnung über mehrere Agenten – und kann auch darauf verzichten. Von Anfang an sind nur die Aspekte wichtig, deren Behebung schwierig ist, sobald historische Daten von ihnen abhängen:
what was randomized
what treatment was assigned
what treatment actually ran
what pipeline version produced the execution
what outcome was measured
how that outcome was evaluated
Sollten diese Identitäten in Version eins erhalten bleiben, kann die Plattform erheblich bereichert werden, ohne dass sich die Bedeutung ihrer alten Experimente ändert.
Die nützliche Erkenntnis ist, dass Offline-Bewertungen, Schattenausführungen und Live-Experimente gemeinsam Pipeline-Definitionen, Spuren sowie Evaluierungswerkzeuge nutzen können, obwohl jede Methode ihre eigene Frage beantwortet. Offline-Ausführungen zeigen, wie A und B in kontrollierten Szenarien sich verhalten. Schattenausführungen zeigen, wie B mit Produktionsdaten umgeht, während die Nutzer unbeeinflusst bleiben. Live-Experimente zeigen, welche Veränderungen auftreten, wenn reale Nutzer zufällig aufgeteilt werden. Die Protokollierung dokumentiert, was während jeder Ausführung geschah, und hilft bei der Interpretation der Ergebnisse – doch eine Diagnose auf Spurenebene sollte niemals als kausale Schätzung gelten. Gemeinsam ermöglichen sie ein MVP, das zuverlässig drei Fragen beantworten kann:
What exactly did we run?
What happened when we ran it?
Did assigning users to B improve the outcome we care about?
Alles andere kann darum herum wachsen.