ML On-Call Agent
ML On-Call Agent
"¿Por qué el run de anoche sufrió una regresión?" — un sistema multi-agente que lo responde correlacionando un informe de deriva, una ejecución de evaluación y un registro de despliegue, y cita cada afirmación que hace.
Expuesto a través de MCP, por lo que las herramientas funcionan desde cualquier cliente MCP.
Estado: 65 pruebas. El diagnóstico se calcula de forma determinista a partir de evidencia ponderada, por lo que cada número a continuación es una aserción, no una demo.
El problema real
Un sistema de ML se degrada silenciosamente. Cuando alguien finalmente se da cuenta, la evidencia está dispersa en tres lugares que no se comunican entre sí:
un informe de deriva — ¿se movió la distribución de entrada?
una ejecución de evaluación — ¿regresaron las puntuaciones offline, y en qué segmentos?
un registro de despliegue — ¿desplegó alguien algo?
Correlacionarlos es un trabajo, y es un trabajo que la gente hace mal a las 3 de la madrugada porque significa tener tres archivos JSON en la cabeza a la vez.
Esos tres artefactos no son inventados para este repositorio. Son lo que model-drift-monitor, llm-eval-pipeline y ai-code-review-bot ya producen. El lector se escribió contra un artefacto real, no contra documentación.
El resultado
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.0La verdad de referencia se conoce por construcción, por lo que el agente se evalúa en lugar de admirarse. "El agente produjo un informe de incidente plausible" no es un resultado — lo plausible es lo que hacen los modelos de lenguaje, incluso cuando la evidencia no respalda nada.
El escenario que es el punto
concept_drift: las entradas son estadísticamente idénticas, no se desplegó nada, y el ranking del modelo se ha invertido (AUC 0.729 → 0.326, peor que aleatorio).
No hay nada a lo que apuntar. La respuesta proviene de combinar dos negativos y un positivo — sin deriva, sin despliegue, ranking colapsado — que es exactamente lo que un resumen de cualquier artefacto individual pasaría por alto. Es también el punto ciego que model-drift-monitor documenta sobre sí mismo, diagnosticado una capa más arriba.
La decisión de diseño sobre la que todo se sostiene
El diagnóstico es determinista. El modelo de lenguaje solo narra.
La construcción obvia es pegar tres archivos JSON en un prompt y preguntar qué salió mal. Produce algo fluido cada vez — incluso cuando la evidencia no respalda nada — y no es comprobable, porque no puedes hacer aserciones sobre prosa ni distinguir una respuesta correcta de una afortunada.
Así que el razonamiento es Python ordinario:
cada especialista lee un artefacto y emite
Findingscada hallazgo lleva una cita — archivo, campo, valor.
Findingrequiere una, por lo que no se puede construir una afirmación sin fuentecada hallazgo nombra qué causas raíz respalda y cuáles descarta
diagnose()suma los pesos — una función pura, probada unitariamente contra la verdad
| 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 afirma que el veredicto es idéntico con y sin un modelo. Si alguna vez falla, el modelo ha empezado a hacer el razonamiento — y el razonamiento deja de ser comprobable en el momento en que lo hace.
La evidencia negativa es donde está la mayor parte del poder diagnóstico. "Sin deriva" y "no se desplegó nada" son hallazgos, con pesos. Un LLM que resumiera el JSON de deriva los omitiría, porque no pasó nada.
El grafo
SUPERVISOR ──► drift ──┐
▲ ├──► evals ───┤ one specialist per artifact, each consulted once
│ └──► changes ─┤
│ ▼
│ DIAGNOSE sum the weighted findings
│ ▼
└────────────── CRITIC "is this conclusion supported?"
(bounded) ▼
REPORTDos propiedades que un pipeline en línea recta no tiene:
El crítico puede devolver el trabajo. Si el veredicto se apoya en dos artefactos mientras un tercero nunca fue leído, el control vuelve al supervisor en lugar de publicar una conclusión extraída de la mitad de la evidencia.
El ciclo está acotado. MAX_REVISIONS = 2 lo limita y recursion_limit atrapa lo que escape. Un agente que puede iterar es un agente que puede iterar para siempre, y un agente on-call desbocado genera páginas en lugar de responderlas.
Se ejecuta sin LLM y sin API key — el supervisor enruta mediante una regla Python simple — así que el enrutamiento, la delegación y el bucle de retorno del crítico se prueban unitariamente offline. test_the_graph_and_the_plain_loop_agree afirma que una ejecución de LangGraph y un bucle for simple llegan a veredictos idénticos en cada escenario, lo que demuestra que el grafo añade orquestación, no razonamiento.
Cuánto vale realmente cada artefacto
python -m oncall.cli ablateevidencia | éxito de tarea | precisión de acción |
las tres | 100% | 100% |
sin deriva | 67% | 67% |
sin evaluaciones | 67% | 67% |
sin cambios | 100% | 100% |
Un resultado negativo honesto, y se afirma para que no pueda olvidarse en silencio. Quitar el registro de cambios no cuesta nada en este conjunto de escenarios — bad_deploy ya es separable solo con la evidencia de deriva y evaluación. El registro de cambios se gana su lugar al nombrar el commit, que es lo que un humano necesita para actuar, no al cambiar el diagnóstico.
test_the_change_log_currently_changes_no_verdicts lo fija. Si un escenario futuro lo vuelve estructural, la prueba falla y esta tabla tiene que cambiar. Para eso sirve la aserción.
La ablación es la única forma de descubrir que una fuente que dedicaste una semana a integrar no cambia ningún veredicto.
Y cuando un artefacto falta
Los trabajos fallan, los buckets están vacíos, las rutas cambian. La pregunta interesante no es si el agente sigue respondiendo — lo hará — sino si se da cuenta:
missing drift -> verdict bad_deploy flagged=True
missing evals -> verdict bad_deploy flagged=True
missing changes -> verdict bad_deploy flagged=TrueUn agente que diagnostica en silencio desde dos de tres archivos es peor que uno que se niega, porque nadie sabe que debe desconfiar de él.
El servidor MCP
python -m oncall.mcp_server # stdio, for Claude Desktop et al
python -m oncall.mcp_server --http --port 8931Siete herramientas — list_incidents, get_drift_report, get_eval_run, get_changes, investigate_incident, compare_incidents, list_specialists — más un recurso y un recurso con plantilla.
Las herramientas devuelven evidencia, no prosa. Cada una entrega el artefacto o el diagnóstico estructurado, así que el modelo del cliente razona sobre datos con citas en lugar de sobre un párrafo que alguien ya resumió. Un resumen es donde muere el detalle.
Escrito contra mcp 2.0.0, que es una reescritura que rompe compatibilidad
Vale la pena decirlo, porque casi todo lo publicado es 1.x y no funciona. Cada uno de estos fue verificado ejecutándolo:
1.x | 2.0.0 |
| desaparecido — |
| desaparecido — el |
|
|
|
|
Dos más que costaron tiempo real:
@server.tool()debe ser llamado.@server.toola secas lanza unTypeErrorque lo dice.Un
-> dicta secas no produce ningúnstructuredContent. El contenido de texto sigue ahí, por lo que se ve bien en un cliente de chat y rompe silenciosamente cualquier cliente que lea el campo estructurado. Cada herramienta aquí devuelve un genérico parametrizado (Dict[str, Any]) por esa razón, y hay una prueba.
Probando un servidor de protocolo sin un subproceso
Client(server) acepta un objeto de servidor directamente, por lo que todo el ciclo de ida y vuelta del protocolo se ejecuta en proceso — sin subproceso, sin puerto, sin inestabilidad de ninguno. Esa facilidad es la única razón por la que las pruebas de protocolo son baratas aquí.
Inicio rápido
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 testsApúntalo a artefactos reales:
python -m oncall.cli write ./artifacts --scenario bad_deploy
# then: Evidence.load("./artifacts") reads a real pipeline's output unchangedTodo se ejecuta sin API key. investigate --narrate añade un párrafo inicial escrito por el modelo si GEMINI_API_KEY está configurada, y no cambia nada más.
Bugs que vale la pena leer
Una tolerancia codificada se tragó el caso de evaluación inestable. regressions() usaba un umbral de 0.02, por lo que un movimiento de 0.006 nunca se registraba y la verificación de ruido nunca se ejecutaba — el agente decía healthy cuando la verdad era noise. Ese es exactamente el error de umbral folclórico contra el que argumenta model-drift-monitor, reproducido un repositorio más allá. Detección y significancia son dos preguntas: el piso ahora es 0.005 ("cualquier cosa que un dashboard mostraría") y el noise_std medido por el propio harness hace la discriminación.
La prueba de recuperación no podía fallar. Fingía un especialista omitido pre-sembrando consulted — pero el crítico compara available contra consulted, así que marcar algo como consultado ocultaba la brecha del mismo chequeo que se estaba probando. Reportaba recovered: False y parecía un crítico roto. La falta debe inyectarse en el enrutamiento, no en el registro; build_graph(skip_first_pass=...) lo hace, y el crítico ahora demuestra que captura la brecha y devuelve al supervisor.
Limitaciones, dichas claramente
Los escenarios son sintéticos. Deliberadamente — los incidentes reales no vienen con una causa raíz etiquetada, que es precisamente por lo que diagnosticarlos es difícil. Los números caracterizan el método, no ningún sistema de producción.
Seis escenarios es un conjunto pequeño. El 100% en seis no es 100% en general, y el siguiente escenario añadido tiene más probabilidades de romperlo que de confirmarlo.
La calibración no es medible aquí. Sin respuestas incorrectas no hay nada contra lo que comparar la confianza. La CLI imprime
n/ay dice por qué en lugar de inventar una cifra —test_calibration_is_honestly_unmeasurable_herelo fija.Los pesos están fijados a mano. Codifican mi juicio sobre cuánto vale la evidencia, y un conjunto de incidentes etiquetado más grande permitiría ajustarlos en su lugar — con una división de reserva, porque ajustarlos en seis escenarios sería memorización.
La precisión de selección de herramientas es trivialmente 1.0 con tres artefactos siempre presentes. La métrica está aquí porque empieza a importar en la cuarta herramienta, y añadirla retroactivamente es como descubres que el agente ha estado llamando a todo durante meses.
Sin integraciones en vivo. Lee artefactos desde el disco. Conectarlo a un warehouse real, un sistema de CI y un host de git es trabajo de despliegue, no de razonamiento.
El crítico comprueba completitud y respaldo, no corrección. No puede decirte que los pesos están mal, solo que la evidencia era escasa.
Hoja de ruta
Un conjunto de incidentes etiquetado más grande, y ajustar los pesos en una división de reserva.
Más especialistas — latencia de servicio, ledger de costes, frescura del feature store — que es donde la precisión de selección de herramientas empieza a significar algo.
Conectar el servidor MCP a fuentes de artefactos reales en lugar de un constructor de escenarios.
Correlación multi-incidente: tres servicios regresando a la vez es un incidente, no tres.
Licencia
MIT.
This server cannot be installed
Maintenance
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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