Zum Hauptinhalt springen
Connic
Zurück zum BlogProdukt im Fokus

Connic Tests: Regressionen vor dem Produktivbetrieb erkennen

Ein YAML-basiertes Testframework für KI-Agenten mit schwankenden Ergebnissen: wiederholte Testläufe, flexible Assertions, Mocks und multimodale Fixtures. Fehlgeschlagene Tests blockieren standardmäßig das Deployment.

6. Mai 2026(zuletzt aktualisiert: 21. Juli 2026)8 Min. LesezeitAutor: Connic Engineering

Ein Prompt wurde geändert, das KI-Modell gewechselt oder ein Tool refaktoriert. Ist etwas kaputtgegangen? Bei klassischem Code liefert eine Testsuite in Sekunden eine Antwort. Bei KI-Agenten veröffentlichen viele Teams eine Änderung und beobachten anschließend das Dashboard. Da derselbe Input unterschiedliche Ergebnisse erzeugen kann, reicht eine einzelne Beobachtung nicht aus.

Heute stellen wir Connic Tests vor, ein Testframework für das Verhalten von Agenten. Es berücksichtigt, dass identische Eingaben zu unterschiedlichen Ergebnissen führen können. Assertions prüfen den Trace und die abschließende Antwort. Während des Deployments entscheidet die Testsuite, ob die neue Version die festgelegten Anforderungen erfüllt und veröffentlicht werden kann.

Warum Agenten klassische Testframeworks überfordern

Pytest, Jest und JUnit nehmen an, dass derselbe Input immer denselben Output erzeugt. Diese Annahme ist die Grundlage klassischer Assertions. Agenten widerlegen sie. Derselbe Prompt kann andere Tokens liefern, unterschiedliche Tool-Pfade nehmen oder einen sporadischen Fehler zeigen, der beim Retry verschwindet. Testsuiten, die deterministische Outputs voraussetzen, werden entweder nutzlos und lassen jeden fehlerhaften Build passieren oder unbrauchbar und blockieren jeden korrekten.

Diese Fehlerbilder übersehen gewöhnliche Testframeworks:

Schwankende Ergebnisse
Der Agent liefert in sieben von zehn Fällen die richtige Antwort. Eine Unit-Test-Assertion besteht entweder immer oder nie. Beides ist falsch. Der Test muss ausdrücken können, was im großen Maßstab gut genug ist.
Unbemerkte Änderungen bei Tool-Aufrufen
Ein Refactoring erzeugt weiterhin eine plausibel wirkende Antwort, aber der Agent ruft den Calculator nicht mehr auf und beginnt zu raten. Der Output wirkt korrekt, das Verhalten ist defekt.
Verbotene Nebeneffekte
Eine kleine Prompt-Änderung bringt den Agenten dazu, hilfsbereit eine E-Mail zu senden, die er nie hätte senden dürfen. Der Test muss sowohl erlaubte als auch verbotene Aktionen prüfen.
Abhängigkeiten von Live-Daten
Tests mit einer echten Stripe-Zahlung, einem echten Datenbankeintrag oder einem echten S3-Objekt passen nicht in eine statische Fixture-Datei. Solche Tests brauchen Fixtures, die Zustand aufbauen und anschließend wieder entfernen.

Wir haben Connic Tests für diese Probleme entwickelt.

Teste Agenten vor dem Deployment

Assertions für echte Agenten-Runs erkennen Regressionen, bevor sie den Produktivbetrieb erreichen.

Kostenlos starten

Der 30-Sekunden-Überblick

Eine Testsuite ist eine YAML-Datei unter tests/<agent-name>.yaml. Dasselbe flache Layout wie bei middleware/, ohne Scaffolding oder Boilerplate. Jede Datei deklariert einen oder mehrere Testfälle für den gleichnamigen Agenten.

tests/stress-tester.yaml
version: "1.0"
agent: stress-tester        # optional, defaults to the filename stem

defaults:
  runs: 10                  # invoke the agent 10 times per case
  success_threshold: 90     # 9 out of 10 must pass
  timeout_s: 60

tests:
  - name: returns_id_10
    payload: '{"a": 4, "b": 6}'
    expected_result: output.id == 10
    expected_tool_calls:
      - math.calculator.add                  # called at least once
      - math.calculator.add: invocations >= 5  # ...or with an expression
    expected_no_tool_calls:
      - email.send                           # must NOT be called

Dieser Test für den Produktivbetrieb definiert zehn Aufrufe, eine erforderliche Erfolgsquote von 90 %, eine Output-Assertion, zwei positive Erwartungen an Tool-Calls und einen verbotenen Nebeneffekt. Zusätzliche Fixtures, Runner oder Integrationscode sind nicht nötig.

Schwankende Ergebnisse mit wiederholten Testläufen prüfen

Der erste Unterschied bei Connic Tests sind runs und success_threshold. Gemeinsam legen sie fest, wie oft ein Testfall ausgeführt wird und welcher Anteil der Ausführungen bestehen muss.

runs (1–100)
Die Anzahl unabhängiger Agentenaufrufe für diesen Testfall. Der Wert 1 eignet sich für günstige deterministische Prüfungen, 50 misst die Schwankungen eines stark ausgelasteten KI-Modells.
success_threshold (1–100)
Der Anteil dieser Runs, der bestehen muss. Ein Schwellenwert von 100 bedeutet, dass jeder Run im Batch bestehen muss; bei 90 sind mindestens neun von zehn erforderlich.
Das Ergebnis: wiederholbare Checks, nachvollziehbare Fehler
Derselbe Case kann als Smoke Test (runs: 1) oder Regressionstest (runs: 50, success_threshold: 95) dienen. Die Anzahl wird pro Testfall gewählt: Einfache Prüfungen bleiben günstig, kritische Fälle erhalten mehr wiederholte Runs. Jeder Aufruf wird mit Agenten-Run ID und Pass/Fail erfasst. Schlägt ein Case bei drei von 50 Runs fehl, führen Links direkt zu diesen drei Traces. Keine Suche in Logs nötig.
Phase Run tests eines Deployments mit ausschließlich bestandenen Testfällen; jeder Case zeigt einen grünen Check und die Agenten-Run-IDs seiner einzelnen Aufrufe
Die Phase Run tests eines Deployments: Jeder Case erscheint als grüne Zeile, jeder Aufruf wird mit seiner Agent Run ID erfasst. adds_two_numbers lief hier fünfmal.

Assertions passend zum tatsächlichen Verhalten von Agenten

Ein String-Equality-Check auf den finalen Output des Agenten ist fast nie die richtige Assertion. Mit Connic Tests bieten wir vier Formen von Assertions. Jede ist ein Ausdruck statt eines fest codierten Vergleichsoperators.

expected_result: Ausdrücke für die Ausgabe
Wird mit den Bindings output, error und status evaluiert. Mögliche Ausdrücke sind output.total > 0, output.status == "refunded" oder ein anderer sicherer Ausdruck. JSON-Nutzdaten werden automatisch geparst.
expected_tool_calls: positive Trace-Assertions
Ein einfacher Tool-Name prüft, dass das Tool mindestens einmal aufgerufen wurde. Die Mapping-Form math.calculator.add: invocations >= 5 prüft die Anzahl der Aufrufe. So werden stille Regressionen sichtbar, bei denen ein Agent ein benötigtes Tool nicht mehr verwendet.
expected_no_tool_calls: negative Trace-Assertions
Eine Liste von Tools, die nicht aufgerufen werden dürfen. Das ist eine der unterschätztesten Assertions beim Testen von Agenten. So lässt sich belegen, dass ein Erstattungsablauf keine Bestätigungs-E-Mail sendet oder ein lesender Agent nie zu schreiben versucht.
Terminal Status (implizit)
Wenn expected_result fehlt, muss der Run trotzdem den Status completed erreichen. Jeder Case erhält damit kostenlos den grundlegenden Check, ob er abgestürzt ist.
Warum Expressions statt Matcher?
Fest codierte Matcher wie assertEquals und assertContains begrenzen die möglichen Fragen, Expressions nicht. Alles, was sich über das Ausgabeobjekt berechnen lässt, etwa numerische Vergleiche, Längenprüfungen, verschachtelte Schlüssel oder Mengenzugehörigkeit, ist bereits eine gültige Assertion. Es ist dieselbe Engine wie bei unseren Trace-Filtern und wird sicher serverseitig evaluiert.

Multimodale Fixtures ohne zusätzliches Setup

Viele aktuelle Agenten lesen PDFs, parsen Rechnungen, erkennen Belege per OCR oder beschreiben Bilder. Die zugehörigen Tests sollten das ebenfalls tun. Eine Binärdatei wird unter tests/files/ abgelegt und über ihren Namen referenziert. Der Runner codiert sie als Base64 und übergibt dem Agenten multimodale Nutzdaten.

tests/invoice-extractor.yaml
tests:
  - name: extract_invoice_total
    payload: "Extract the total amount from this invoice."
    files:
      - invoice_a.pdf
      - invoice_b.pdf
    runs: 5
    success_threshold: 100
    expected_result: output.total > 0 and output.currency == "EUR"

Fünf Runs, die jeweils beide PDFs zusammen mit dem Prompt erhalten, und die strikte Erwartung, dass jeder eine positive Summe in Euro zurückgibt. Dabei laufen echte KI-Modell-Aufrufe mit echten Fixtures, ohne Mocking oder Stubs.

Dynamische Builder für Tests mit Zustand

Manche Tests können nicht statisch sein. Ein Test für einen Agenten für Erstattungen muss zuerst eine echte Zahlung erstellen. Ein Updater-Test muss einen echten Datensatz anlegen. Dynamische Builder sind kleine Python-Module unter tests/builders/, die zur Laufzeit die Testdaten erzeugen und die Fixture danach wieder entfernen.

tests/builders/create_charge_then_refund.py
import stripe

def build(context, builder_args, test_name, payload, files):
    """Create a real Stripe charge, then ask the agent to refund it."""
    charge = stripe.Charge.create(
        amount=builder_args["amount_cents"],
        currency="usd",
        source="tok_visa",
    )
    # stash state for cleanup() to read back
    context["charge_id"] = charge.id
    return f"Please refund charge {charge.id} for the customer."

def cleanup(run, context, builder_args):
    """Runs after the agent finishes (pass OR fail)."""
    charge_id = context.get("charge_id")
    if charge_id:
        # ensure the fixture is gone even if the agent forgot
        try:
            stripe.Refund.create(charge=charge_id)
        except stripe.error.InvalidRequestError:
            pass  # already refunded by the agent under test
    return None  # returning False would mark the case failed
tests/billing-agent.yaml
tests:
  - name: refunds_a_real_charge
    builder: create_charge_then_refund
    builder_args:
      amount_cents: 4200
    expected_result: output.status == "refunded"
    expected_tool_calls:
      - stripe.refund.create
    expected_no_tool_calls:
      - email.send

Der Builder erstellt den Testzustand, der Agent arbeitet damit, die Assertion prüft das Verhalten und der Cleanup-Hook entfernt die Fixture, selbst wenn der Test fehlgeschlagen ist. Builder laufen in derselben Sandbox wie der Agent und sehen deshalb dasselbe Environment, dieselben Secrets und dieselben Tools.

Cleanup läuft immer
Wird False von cleanup() zurückgegeben, schlägt der Case zusätzlich fehl. Das ist hilfreich, wenn der Teardown selbst einen Bug zeigt, etwa wenn der Agent eine behauptete Erstattung nicht wirklich ausgeführt hat. Jeder andere Rückgabewert gilt als Erfolg.

Nebeneffekte mocken, Reasoning beibehalten

Builder testen echten Zustand. Mocks gehen in die andere Richtung: Sie testen das Reasoning des Agenten, ohne ausgewählten eigenen Code wirklich auszuführen. Kein Datensatz wird geschrieben, keine E-Mail gesendet und keine Zahlung bei einem Drittanbieter ausgelöst. Unter tests/mocks/ liegt dafür ein Python-Modul, auf das ein Testfall über das Feld mocks verweist.

tests/mocks/customer_mocks.py
from connic import GuardrailResult

# Replace one custom file tool result.
def mock_data_customer_add_customer(tool_name, params, context):
    return {"id": "cust_test_1", "name": params.get("name")}

# Replace middleware and one exact before-hook phase.
def middleware_before(content, context):
    return content

def mock_data_customer_add_customer_hook_before(tool_name, params, context):
    return params

# Replace only this custom input guardrail.
def guardrail_input_domain_check(content, context):
    return GuardrailResult(passed=True)
tests/customer-agent.yaml
tests:
  - name: adds_a_customer_without_touching_the_db
    payload: '{"name": "Ada"}'
    mocks: customer_mocks
    strict_mocks: true
    strict_hook_mocks: true
    strict_middleware_mocks: true
    strict_guardrail_mocks: true
    # The add_customer call is served by the mock but still recorded,
    # so the assertion holds while nothing ever reaches a real datastore.
    expected_tool_calls:
      - data.customer.add_customer: params.name == "Ada"
    expected_result: output.id == "cust_test_1"

Tool-Ersetzungen verwenden eine Hierarchie von der exakten Funktion (mock_data_customer_add_customer) über das Modul (mock_data_customer) und den Namespace (mock_data) bis zum Catch-all mock. Dasselbe Modul kann middleware_before und middleware_after, hierarchische Hook-Phasen mit _hook_before und _hook_after sowie Custom Guardrails ersetzen. Eine passende Funktion ersetzt die Phase; fehlt sie, läuft standardmäßig der echte Code. Integrierte Guardrails, vordefinierte Tools und Implementierungen von api: laufen immer wirklich.

Gemockt, aber weiterhin beobachtet
Der ersetzte Call wird im Trace wie ein echter erfasst. Dadurch prüfen expected_tool_calls und expected_no_tool_calls weiterhin, welches Tool der Agent verwenden wollte, während der konfigurierte Rückgabewert als Ergebnis dient.
Mocks verbindlich vorschreiben
Mit strict_mocks: true pro Datei oder Testfall schlägt die Ausführung fehl, bevor ein nicht gemocktes eigenes Datei-Tool läuft. Diese Vorgabe gilt nur für Tools. Unabhängig davon lassen sich strict_hook_mocks, strict_middleware_mocks oder strict_guardrail_mocks aktivieren, damit ein konfigurierter Lifecycle-Abschnitt ohne passenden Mock fehlschlägt, bevor der echte Code ausgeführt wird. Alle drei sind standardmäßig false; fehlende Phasen und integrierte Guardrails sind ausgenommen.

Tests als verbindliche Deployment-Prüfung

Tests, die nur auf dem Laptop eines Entwicklers laufen, vermitteln Sicherheit, sind aber keine Kontrolle. Connic Tests ist direkt mit der Deployment-Pipeline verbunden:

git pushBuildTestphasePromoteProduktivbetrieb

Bei jedem regulären Deployment erkennt Connic die Testsuiten im Projekt, erweitert jeden Case entsprechend der Anzahl runs und führt sie in einem isolierten Runner aus. Verfehlt ein Case seinen Schwellenwert, stoppt das Deployment vor dem Produktivbetrieb. Der Befehl connic deploy --skip-tests ist ein bewusster CLI-Ausweg für Hotfixes; Git Auto-Deployments können das Gate nicht umgehen.

Fehlgeschlagenes Deployment mit fehlerhaftem Schritt Run tests und aufgelisteten Testfällen samt Invalid-JSON-Grund sowie Pass/Fail-Ergebnissen pro Run, die den Rollout blockieren
Ein blockiertes Deployment: Die Testphase ist fehlgeschlagen, daher wurde der Build nicht in den Produktivbetrieb übernommen. Jeder rot markierte Testfall verweist direkt auf die betroffenen Runs.
In die Deployment-Pipeline integriert
Eigener CI-Integrationscode entfällt. Die Testphase läuft standardmäßig in Connics Deployment-Pipeline. Jeder Testlauf wird dem auslösenden Deployment zugeordnet. So bleibt der Ablauf für Audits nachvollziehbar.
Transparenz pro Case
Jeder Testfall erhält eine eigene Zeile in der Deployment-Zeitleiste mit der Anzahl versuchter und bestandener Runs sowie den zugrunde liegenden Agenten-Run-IDs. Ein Klick auf einen fehlgeschlagenen Case führt direkt zu den betroffenen Traces.
Bei Bedarf über die CLI ausführen
Ein Fix lässt sich auch ohne neues Deployment prüfen: connic test führt dasselbe Framework im aktuellen Environment aus und streamt Ergebnisse in das Terminal.
Schwellenwerte für sporadische Fehler
Ein Schwellenwert von 90 % senkt den Anspruch nicht, sondern formuliert ihn ehrlich. Das Deployment besteht, wenn der beobachtete Batch die Qualitätsrichtlinie für den Produktivbetrieb erfüllt, und schlägt andernfalls fehl.

Muster aus der Praxis

Regressionstest für eine Prompt-Änderung
Ein Team schreibt den System-Prompt seines Support-Agenten neu. Es ergänzt einen Testfall mit 50 Runs und einem Schwellenwert von 95 % für ein schwieriges historisches Ticket. Das Deployment gelingt nur, wenn der neue Prompt die Zuverlässigkeitsrichtlinie des Teams für genau das Ticket erfüllt, das die Änderung ausgelöst hat.
Tool-Aufrufe nach einem Modellwechsel prüfen
Nach einem KI-Modell-Upgrade beantwortet ein Analyse-Agent Fragen plötzlich aus seinem gespeicherten Kontext, statt das Warehouse abzufragen. Das Team ergänzt in jedem Case expected_tool_calls: warehouse.query: invocations >= 1. Künftige KI-Modell-Wechsel, die den Fehler wieder einführen, lassen das Deployment automatisch fehlschlagen.
Negative Assertions für einen Agenten für Erstattungen
Ein Abrechnungsagent darf Kunden ohne ausdrückliche Anweisung nie eine E-Mail senden. Jeder Erstattungstestfall enthält expected_no_tool_calls: email.send. Eine Regression mit einer vermeintlich hilfreichen Bestätigungs-E-Mail wird beim Deployment statt durch eine Kundenbeschwerde erkannt.
Multimodale Abdeckung für einen Rechnungsparser
Ein Agent zur Rechnungsextraktion besitzt zwölf Fixture-PDFs für verschiedene Formate von Anbietern. Jeder Case läuft dreimal mit einem Schwellenwert von 100 %. Eine KI-Modell-Regression, die ein Format beschädigt, erscheint als einzelne rote Zeile in der Deployment-Ansicht und nicht als stiller Verlust an Extraktionsgenauigkeit.

Einordnung in die übrige Plattform

Connic Tests prüft vor der Veröffentlichung, ob ein Agent die festgelegten Anforderungen erfüllt. Im laufenden Betrieb ergänzen zwei weitere Funktionen die Qualitätsprüfung:

SystemWann es läuftWelche Frage es beantwortet
Connic TestsWährend des DeploymentsErfüllt dieser Build die definierten Anforderungen?
LLM JudgesNach jedem oder ausgewählten Run im ProduktivbetriebWie entwickelt sich die Qualität im Vergleich zu den definierten Bewertungskriterien?
A/B-TestingÜber zwei Live-Varianten hinwegWelche Version funktioniert bei echtem Traffic besser?

Tests erkennen Regressionen vor der Veröffentlichung. Judges bewerten die veröffentlichten Ausführungen. A/B-Testing entscheidet zwischen zwei Versionen, die beide bestanden haben. Zusammen liefern sie Rückmeldungen vor und nach der Veröffentlichung, auf deren Grundlage das Team den Agenten weiterentwickeln kann.

Erste Schritte

Tests lassen sich in fünf Minuten zu einem bestehenden Agenten hinzufügen:

  • 1.Im Projektstamm ein Verzeichnis tests/ erstellen, direkt neben agents/
  • 2.tests/<agent-name>.yaml um ein oder zwei Testfälle ergänzen. Für schnelles Feedback mit runs: 1 beginnen
  • 3.connic test lokal ausführen und die gestreamten Testfälle beobachten
  • 4.Die Änderungen pushen und bereitstellen. Dieselbe Suite schützt jetzt den Produktivbetrieb. Die Anzahl runs für besonders wichtige Testfälle erhöhen

Die vollständige Schema-Referenz mit jedem Feld, Standardwert und jeder Ausdrucksbindung steht in der Testing-Dokumentation. Für den Einstieg in Connic lässt sich mit dem Quickstart-Leitfaden ein erster Agent bereitstellen. Anschließend schützt ein Test vor Regressionen, bevor Kunden sie bemerken.

Mehr aus dem Blog

Produkt im Fokus

KI-Agenten-Routing: Agenten auslösen und Ergebnisse zurückgeben

Connic leitet externe Events an Agenten weiter und liefert Ergebnisse synchron oder über asynchrone Outbound-Verbindungen an das Zielsystem.

24. August 20269 Min. Lesezeit
Produkt im Fokus

LLM-Kontextkomprimierung für lang laufende KI-Agenten

Connic komprimiert ältere Gesprächsverläufe und übergroße Tool-Ergebnisse. Danach wiederholt die Runtime den KI-Modell-Aufruf, damit lange Agentensitzungen das Kontextlimit nicht überschreiten.

20. Juli 20268 Min. Lesezeit
Produkt im Fokus

Human-in-the-Loop-KI-Agenten: Approvals im Produktivbetrieb

So pausiert ein KI-Agent vor Erstattungen, Löschvorgängen oder externen Aufrufen, leitet die Entscheidung an einen Menschen weiter und setzt den Run mit vollständigem Audit Trail automatisch fort.

5. April 202610 Min. Lesezeit
Produkt im Fokus

A/B-Tests für KI-Agenten: Prompts sicher verbessern

Ob ein geänderter Prompt wirklich besser ist, zeigt ein kontrolliertes Experiment mit echtem Traffic.

27. März 20269 Min. Lesezeit
Produkt im Fokus

KI-Agenten absichern: Checkliste für den Produktivbetrieb

KI-Agenten ohne Sicherheitskonzept zu veröffentlichen ist riskant. Eine praktische Checkliste zu Prompt Injection, PII-Verarbeitung, Output-Validierung und Guardrails vor dem Go-live.

21. März 202612 Min. Lesezeit
Produkt im Fokus

Guardrails für KI-Agenten: Sicherheit in Echtzeit

Connic Guardrails prüfen Ein- und Ausgaben von Agenten in Echtzeit, blockieren Prompt Injection, maskieren PII und setzen Themenbeschränkungen durch.

3. März 20269 Min. Lesezeit
Produkt im Fokus

Connic Bridge: KI-Agenten für private Infrastruktur

Connic Bridge stellt einen sicheren ausgehenden Tunnel bereit, über den KI-Agenten private Kafka-Cluster, Datenbanken und interne Dienste ohne offene eingehende Ports erreichen.

19. Februar 20267 Min. Lesezeit
Produkt im Fokus

Observability für Agenten: Kosten, Tokens und Runs erfassen

Eigene Dashboards machen LLM-Kosten pro KI-Modell und Fehler sichtbar, bevor Nutzer die Folgen bemerken.

23. Januar 20268 Min. Lesezeit
Produkt im Fokus

Composer SDK: Bessere Werkzeuge für die Agentenentwicklung

Das Composer SDK automatisiert Projektgerüst und Validierung und unterstützt Cloud-gestützte Hot-Reload-Entwicklung sowie Deployments per CLI.

27. Dezember 20255 Min. Lesezeit