Skip to main content
Glama

ML On-Call Agent

„Warum hat der gestrige Lauf Regressionen verursacht?" — ein Multi-Agenten-System, das diese Frage beantwortet, indem es einen Drift-Report, einen Eval-Run und ein Deploy-Log korreliert, und jede Behauptung mit einer Quelle belegt.

Bereitgestellt über MCP, sodass die Tools aus jedem MCP-Client funktionieren.

Status: 65 Tests. Die Diagnose wird deterministisch aus gewichteten Beweisen berechnet, daher ist jede Zahl unten eine Assertion, keine Demo.


Das eigentliche Problem

Ein ML-System verschlechtert sich lautlos. Wenn es schließlich jemand bemerkt, sind die Beweise über drei Orte verstreut, die nicht miteinander kommunizieren:

  • ein Drift-Report — hat sich die Eingabeverteilung verschoben?

  • ein Eval-Run — haben sich die Offline-Scores verschlechtert, und auf welchen Slices?

  • ein Deploy-Log — hat jemand etwas ausgerollt?

Sie zu korrelieren ist eine Aufgabe, und es ist eine Aufgabe, die Menschen um 3 Uhr morgens schlecht erledigen, weil es bedeutet, drei JSON-Dateien gleichzeitig im Kopf zu halten.

Diese drei Artefakte sind nicht für dieses Repository erfunden. Sie sind das, was model-drift-monitor, llm-eval-pipeline und ai-code-review-bot bereits produzieren. Der Reader wurde gegen ein echtes Artefakt geschrieben, nicht gegen Dokumentation.


Das Ergebnis

python -m oncall.cli evaluate
 scenario         truth           verdict          conf  margin  steps  action
 healthy          healthy         healthy          0.57     2.0      9  no action
 data_shift       data_shift      data_shift       0.71     8.0      9  retrain on recent data
 bad_deploy       bad_deploy      bad_deploy       0.66     8.5      9  roll back
 concept_drift    concept_drift   concept_drift    0.81     9.0      9  retrain with fresh labels
 pipeline_break   pipeline_break  pipeline_break   0.62     5.0      9  fix the upstream pipeline
 flaky_eval       noise           noise            0.62     3.0      9  rerun the evaluation

task success    : 100%
action accuracy : 100%
mean steps      : 9.0

Die Ground Truth ist konstruktionsbedingt bekannt, daher wird der Agent bewertet statt bewundert. „Der Agent hat einen plausiblen Incident-Report erzeugt" ist kein Ergebnis — plausibel ist das, was Sprachmodelle tun, auch wenn die Beweise nichts hergeben.

Das Szenario, um das es geht

concept_drift: Die Eingaben sind statistisch identisch, nichts wurde ausgerollt, und das Ranking des Modells hat sich umgekehrt (AUC 0,729 → 0,326, schlechter als Zufall).

Es gibt nichts, worauf man zeigen könnte. Die Antwort ergibt sich aus der Kombination von zwei Negativen und einem Positiven — kein Drift, kein Deploy, Ranking kollabiert — was genau das ist, was eine Zusammenfassung eines einzelnen Artefakts übersehen würde. Es ist auch der blinde Fleck, den model-drift-monitor über sich selbst dokumentiert, eine Ebene höher diagnostiziert.


Die Designentscheidung, auf der alles beruht

Die Diagnose ist deterministisch. Das Sprachmodell erzählt nur.

Der naheliegende Bau wäre, drei JSON-Dateien in einen Prompt einzufügen und zu fragen, was schiefgelaufen ist. Das erzeugt jedes Mal etwas Flüssiges — auch wenn die Beweise nichts hergeben — und es ist untestbar, weil man nicht auf Prosa asserten oder eine richtige Antwort von einer glücklichen unterscheiden kann.

Daher ist die Schlussfolgerung gewöhnliches Python:

  • jeder Spezialist liest ein Artefakt und gibt Findings aus

  • jedes Finding trägt eine Zitation — Datei, Feld, Wert. Finding verlangt eine, sodass eine Behauptung ohne Quelle nicht konstruiert werden kann

  • jedes Finding benennt, welche Root Causes es stützt und welche es ausschließt

  • diagnose() summiert die Gewichte — eine reine Funktion, unit-getestet gegen die Wahrheit

| finding                                                    | source                     |
|------------------------------------------------------------|----------------------------|
| input drift is 'none': the scored population is             | `drift:severity=none`      |
| statistically the same as training                          |                            |
| roc_auc is 0.326 - WORSE THAN RANDOM. The model's ranking   | `evals:metrics.roc_auc     |
| has inverted, which is a changed relationship               |  =0.326`                   |
| 1 change(s) landed but none touch model behaviour           | `changes:changes[].files`  |

test_the_narration_does_not_change_the_diagnosis assertet, dass das Urteil mit und ohne Modell identisch ist. Falls es jemals fehlschlägt, hat das Modell begonnen, die Schlussfolgerung zu übernehmen — und die Schlussfolgerung hört in dem Moment auf, testbar zu sein.

Negative Beweise sind der Ort, an dem der meiste diagnostische Wert liegt. „Kein Drift" und „nichts wurde ausgerollt" sind Findings mit Gewichten. Ein LLM, das das Drift-JSON zusammenfasst, würde sie überspringen, weil nichts passiert ist.


Der Graph

   SUPERVISOR ──► drift ──┐
        ▲   ├──► evals ───┤   one specialist per artifact, each consulted once
        │   └──► changes ─┤
        │                 ▼
        │             DIAGNOSE          sum the weighted findings
        │                 ▼
        └──────────────  CRITIC         "is this conclusion supported?"
           (bounded)      ▼
                        REPORT

Zwei Eigenschaften, die eine gerade Pipeline nicht hat:

Der Kritiker kann Arbeit zurückschicken. Wenn das Urteil auf zwei Artefakten beruht, während ein drittes nie gelesen wurde, kehrt die Kontrolle zum Supervisor zurück, statt eine Schlussfolgerung zu veröffentlichen, die aus der Hälfte der Beweise gezogen wurde.

Der Zyklus ist begrenzt. MAX_REVISIONS = 2 begrenzt ihn, und recursion_limit fängt alles ab, was entkommt. Ein Agent, der loopen kann, ist ein Agent, der für immer loopen kann — und ein außer Kontrolle geratener On-Call-Agent erzeugt Seiten, statt sie zu beantworten.

Er läuft ohne LLM und ohne API-Key — der Supervisor routet über eine einfache Python-Regel — sodass das Routing, die Delegation und das Loop-back des Kritikers alle offline unit-getestet sind. test_the_graph_and_the_plain_loop_agree assertet, dass ein LangGraph-Lauf und eine einfache for-Schleife in jedem Szenario zu identischen Urteilen kommen, was beweist, dass der Graph Orchestrierung hinzufügt, nicht Schlussfolgerung.


Was jedes Artefakt tatsächlich wert ist

python -m oncall.cli ablate

Beweise

Aufgaben-Erfolg

Aktions-Genauigkeit

alle drei

100 %

100 %

ohne Drift

67 %

67 %

ohne Evals

67 %

67 %

ohne Changes

100 %

100 %

Ein ehrliches negatives Ergebnis, und es ist assertet, damit es nicht stillschweigend vergessen wird. Das Entfernen des Change-Logs kostet nichts bei diesem Szenario-Set — bad_deploy ist bereits allein aus den Drift- und Eval-Beweisen separierbar. Das Change-Log verdient seinen Platz durch die Benennung des Commits, was ein Mensch braucht, um zu handeln, nicht durch eine Änderung der Diagnose.

test_the_change_log_currently_changes_no_verdicts fixiert das. Wenn ein zukünftiges Szenario es tragend macht, schlägt der Test fehl, und diese Tabelle muss sich ändern. Dafür ist die Assertion da.

Ablation ist der einzige Weg, um zu entdecken, dass eine Quelle, für deren Integration du eine Woche gebraucht hast, keine Urteile verändert.

Und wenn ein Artefakt fehlt

Jobs schlagen fehl, Buckets sind leer, Pfade ändern sich. Die interessante Frage ist nicht, ob der Agent weiterhin antwortet — das tut er —, sondern ob er es bemerkt:

  missing drift     -> verdict bad_deploy   flagged=True
  missing evals     -> verdict bad_deploy   flagged=True
  missing changes   -> verdict bad_deploy   flagged=True

Ein Agent, der stillschweigend aus zwei von drei Dateien diagnostiziert, ist schlechter als einer, der sich weigert, weil niemand weiß, dass man ihm misstrauen sollte.


Der MCP-Server

python -m oncall.mcp_server                 # stdio, for Claude Desktop et al
python -m oncall.mcp_server --http --port 8931

Sieben Tools — list_incidents, get_drift_report, get_eval_run, get_changes, investigate_incident, compare_incidents, list_specialists — plus eine Resource und eine templated Resource.

Die Tools geben Beweise zurück, keine Prosa. Jedes gibt das Artefakt oder die strukturierte Diagnose zurück, sodass das Modell des Clients über Daten mit Zitationen schlussfolgert, statt über einen Absatz, den jemand bereits zusammengefasst hat. Eine Zusammenfassung ist der Ort, an dem das Detail stirbt.

Geschrieben gegen mcp 2.0.0, das ein breaking Rewrite ist

Erwähnenswert, weil fast alles Veröffentlichte 1.x ist und nicht funktioniert. Jedes davon wurde durch Ausführen verifiziert:

1.x

2.0.0

from mcp.server.fastmcp import FastMCP

wegModuleNotFoundError. Verwende MCPServer aus mcp.server.mcpserver

@server.list_tools() / @server.call_tool()

weg — der Low-Level-Server nimmt Konstruktor-Callbacks

stdio_client + ClientSession von Hand

Client(server_or_url_or_transport)

tool.inputSchema

tool.input_schema — snake_case am Modell, camelCase auf der Leitung

Zwei weitere, die echte Zeit gekostet haben:

  • @server.tool() muss aufgerufen werden. Bloßes @server.tool wirft einen TypeError, der genau das sagt.

  • Ein bloßes -> dict erzeugt überhaupt kein structuredContent. Der Textinhalt ist trotzdem da, also sieht es in einem Chat-Client gut aus und bricht stillschweigend jeden Client, der das strukturierte Feld liest. Jedes Tool hier gibt aus diesem Grund einen parametrisierten Generic (Dict[str, Any]) zurück, und es gibt einen Test dafür.

Testen eines Protokoll-Servers ohne Subprozess

Client(server) akzeptiert direkt ein Server-Objekt, sodass der gesamte Protokoll-Roundtrip im Prozess läuft — kein Subprozess, kein Port, keine Flakiness durch beides. Diese Möglichkeit ist der einzige Grund, warum Protokoll-Tests hier billig sind.


Schnellstart

git clone https://github.com/kanishqtanwar35-hub/ml-oncall-agent
cd ml-oncall-agent
pip install -r requirements.txt
export PYTHONPATH=src

python -m oncall.cli incidents                  # what can be investigated
python -m oncall.cli investigate concept_drift  # the full report
python -m oncall.cli evaluate                   # score it against truth
python -m oncall.cli ablate                     # what each artifact is worth
pytest -q                                       # 65 tests

Zeige es auf echte Artefakte:

python -m oncall.cli write ./artifacts --scenario bad_deploy
# then: Evidence.load("./artifacts") reads a real pipeline's output unchanged

Alles läuft ohne API-Key. investigate --narrate fügt einen vom Modell geschriebenen Eröffnungsabsatz hinzu, wenn GEMINI_API_KEY gesetzt ist, und ändert sonst nichts.


Bugs, die lesenswert sind

Eine hartkodierte Toleranz verschluckte den Flaky-Eval-Fall. regressions() verwendete einen 0,02-Schwellenwert, sodass eine 0,006-Bewegung nie registriert wurde und der Noise-Check nie lief — der Agent sagte healthy, wo die Wahrheit noise war. Das ist genau der Folklore-Schwellenwert-Fehler, gegen den model-drift-monitor argumentiert, ein Repository weiter reproduziert. Erkennung und Signifikanz sind zwei Fragen: Der Boden ist jetzt 0,005 („alles, was ein Dashboard zeigen würde"), und das selbst gemessene noise_std der Harness übernimmt die Unterscheidung.

Der Recovery-Test konnte nicht fehlschlagen. Er täuschte einen übersprungenen Spezialisten vor, indem er consulted vorab befüllte — aber der Kritiker vergleicht available gegen consulted, sodass das Markieren von etwas als konsultiert die Lücke vor genau der Prüfung verbarg, die getestet wurde. Er meldete recovered: False und sah aus wie ein kaputter Kritiker. Der Fehler muss in das Routing injiziert werden, nicht in die Buchhaltung; build_graph(skip_first_pass=...) macht das, und der Kritiker fängt die Lücke nun nachweislich und schickt den Supervisor zurück.


Einschränkungen, klar benannt

  • Die Szenarien sind synthetisch. Bewusst — echte Incidents kommen nicht mit einer beschrifteten Root Cause, genau deshalb ist ihre Diagnose schwer. Die Zahlen charakterisieren die Methode, nicht ein Produktionssystem.

  • Sechs Szenarien sind eine kleine Menge. 100 % bei sechs ist nicht 100 % im Allgemeinen, und das nächste hinzugefügte Szenario bricht es eher, als es zu bestätigen.

  • Kalibrierung ist hier nicht messbar. Ohne falsche Antworten gibt es nichts, womit man Konfidenz vergleichen könnte. Das CLI gibt n/a aus und sagt warum, statt eine Zahl zu erfinden — test_calibration_is_honestly_unmeasurable_here fixiert das.

  • Die Gewichte sind von Hand gesetzt. Sie kodieren mein Urteil darüber, was Beweise wert sind, und ein größerer beschrifteter Incident-Satz würde es erlauben, sie stattdessen anzupassen — mit einem zurückgehaltenen Split, weil das Anpassen an sechs Szenarien Memorisation wäre.

  • Die Tool-Auswahl-Genauigkeit ist trivial 1,0 bei drei immer vorhandenen Artefakten. Die Metrik ist hier, weil sie beim vierten Tool anfängt, wichtig zu werden, und das nachträgliche Hinzufügen ist der Weg, um zu entdecken, dass der Agent seit Monaten alles aufruft.

  • Keine Live-Integrationen. Es liest Artefakte von der Festplatte. Die Verbindung mit einem echten Warehouse, CI-System und Git-Host ist Deployment-Arbeit, keine Schlussfolgerungs-Arbeit.

  • Der Kritiker prüft Vollständigkeit und Unterstützung, nicht Korrektheit. Er kann dir nicht sagen, dass die Gewichte falsch sind, nur dass die Beweise dünn waren.

Roadmap

  1. Ein größerer beschrifteter Incident-Satz, und die Gewichte auf einem zurückgehaltenen Split anpassen.

  2. Mehr Spezialisten — Serving-Latenz, Kosten-Ledger, Feature-Store-Frische — wo die Tool-Auswahl-Genauigkeit anfängt, etwas zu bedeuten.

  3. Den MCP-Server mit echten Artefakt-Quellen verbinden, statt mit einem Szenario-Builder.

  4. Multi-Incident-Korrelation: Drei Dienste, die gleichzeitig Regressionen haben, sind ein Incident, nicht drei.

Lizenz

MIT.

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

  • Monitor MCP servers, API contracts and AI outputs for schema drift. Alerts on breaking changes.

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kanishqtanwar35-hub/ml-oncall-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server