ML On-Call Agent
ML On-Call Agent
"어젯밤 실행이 왜 퇴보했을까?" — 드리프트 리포트, 평가 실행, 배포 로그를 상호 연관시켜 답하는 멀티 에이전트 시스템이며, 주장하는 모든 내용에 출처를 인용합니다.
MCP로 노출되므로, 모든 MCP 클라이언트에서 도구를 사용할 수 있습니다.
상태: 테스트 65개. 진단은 가중치가 적용된 증거로부터 결정론적으로 계산되므로, 아래의 모든 수치는 데모가 아니라 단언입니다.
실제 문제
ML 시스템은 조용히 성능이 저하됩니다. 누군가 마침내 알아차렸을 때, 증거는 서로 통신하지 않는 세 곳에 흩어져 있습니다:
드리프트 리포트 — 입력 분포가 이동했는가?
평가 실행 — 오프라인 점수가 퇴보했는가, 어떤 슬라이스에서?
배포 로그 — 무엇인가 배포된 것이 있는가?
이들을 상호 연관시키는 것은 하나의 작업이며, 사람들은 새벽 3시에 그 일을 형편없이 해냅니다. 세 개의 JSON 파일을 동시에 머릿속에 담고 있어야 하기 때문입니다.
그 세 가지 아티팩트는 이 저장소를 위해 만들어진 것이 아닙니다. 그것들은
model-drift-monitor,
llm-eval-pipeline
그리고 ai-code-review-bot이
이미 생산하는 것들입니다. 이 리더는 문서가 아니라 실제 아티팩트를 대상으로 작성되었습니다.
결과
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실측 정답은 구성 방식상 알려져 있으므로, 에이전트는 감탄의 대상이 아니라 평가의 대상입니다. "에이전트가 그럴듯한 인시던트 보고서를 만들었다"는 것은 결과가 아닙니다 — 그럴듯함은 언어 모델이 하는 일이며, 증거가 아무것도 뒷받침하지 않을 때도 그렇습니다.
핵심 시나리오
concept_drift: 입력은 통계적으로 동일하고, 배포된 것은 없으며, 모델의 랭킹이 역전되었습니다 (AUC 0.729 → 0.326, 무작위보다 나쁨).
가리킬 만한 것이 없습니다. 답은 두 개의 부정과 하나의 긍정 — 드리프트 없음, 배포 없음, 랭킹 붕괴 — 을 결합해야 나옵니다. 이는 어떤 단일 아티팩트의 요약이라도 놓치는 바로 그 지점입니다. 또한 이것은 model-drift-monitor가 자신에 대해 문서화한 사각지대를 한 단계 위에서 진단한 것입니다.
모든 것이 의존하는 설계 결정
진단은 결정론적입니다. 언어 모델은 서술만 할 뿐입니다.
당연한 구현은 세 개의 JSON 파일을 프롬프트에 붙여 넣고 무엇이 잘못되었는지 묻는 것입니다. 그것은 매번 유창한 무언가를 만들어냅니다 — 증거가 아무것도 뒷받침하지 않을 때도 — 그리고 테스트할 수 없습니다. 산문에 대해 단언할 수도 없고, 정답과 운이 좋은 답을 구별할 수도 없기 때문입니다.
따라서 추론은 평범한 Python입니다:
각 전문가는 하나의 아티팩트를 읽고
Finding들을 생성합니다모든 파인딩은 인용 — 파일, 필드, 값 — 을 담습니다.
Finding은 인용을 요구하므로, 출처 없는 주장은 구성될 수 없습니다각 파인딩은 그것이 지지하는 근본 원인과 배제하는 근본 원인을 지목합니다
diagnose()는 가중치를 합산합니다 — 순수 함수이며, 실측에 대해 단위 테스트됩니다
| 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는 모델이 있든 없든 판정이 동일하다고 단언합니다. 만약 그 테스트가 실패한다면, 모델이 추론을 시작한 것이며 — 추론은 그렇게 되는 순간 테스트 가능성을 잃습니다.
진단 능력의 대부분은 부정적 증거에 있습니다. "드리프트 없음"과 "배포된 것 없음"은 가중치가 있는 파인딩입니다. 드리프트 JSON을 요약하는 LLM은 아무 일도 일어나지 않았기 때문에 그것들을 건너뛸 것입니다.
그래프
SUPERVISOR ──► drift ──┐
▲ ├──► evals ───┤ one specialist per artifact, each consulted once
│ └──► changes ─┤
│ ▼
│ DIAGNOSE sum the weighted findings
│ ▼
└────────────── CRITIC "is this conclusion supported?"
(bounded) ▼
REPORT직선형 파이프라인이 갖지 못한 두 가지 속성:
비평가는 작업을 되돌려보낼 수 있습니다. 판정이 두 아티팩트에 근거하는데 세 번째 것이 전혀 읽히지 않았다면, 절반의 증거로 도출된 결론을 게시하는 대신 제어권이 감독자에게 돌아갑니다.
순환은 제한됩니다. MAX_REVISIONS = 2가 상한을 정하고 recursion_limit이 빠져나가는 것을 잡아냅니다. 루프할 수 있는 에이전트는 영원히 루프할 수 있는 에이전트이며, 통제 불능의 온콜 에이전트는 답변하는 대신 페이지를 생성합니다.
그것은 LLM도 API 키도 없이 실행됩니다 — 감독자는 단순한 Python 규칙으로 라우팅합니다 — 따라서 라우팅, 위임, 비평가의 루프백은 모두 오프라인에서 단위 테스트됩니다. test_the_graph_and_the_plain_loop_agree는 LangGraph 실행과 단순한 for 루프가 모든 시나리오에서 동일한 판정에 도달한다고 단언하며, 이는 그래프가 추론이 아니라 오케스트레이션을 추가한다는 것을 증명합니다.
각 아티팩트가 실제로 지니는 가치
python -m oncall.cli ablate증거 | 작업 성공 | 행동 정확도 |
세 가지 모두 | 100% | 100% |
드리프트 없음 | 67% | 67% |
평가 없음 | 67% | 67% |
변경 로그 없음 | 100% | 100% |
정직한 부정적 결과이며, 조용히 잊히지 않도록 단언으로 고정되어 있습니다. 이 시나리오 집합에서는 변경 로그를 제거해도 아무 비용이 들지 않습니다 — bad_deploy는 이미 드리프트 및 평가 증거만으로 분리 가능합니다. 변경 로그는 진단을 바꾸는 것이 아니라 커밋을 지목함으로써 그 자리를 얻습니다. 그것이 인간이 행동하기 위해 필요한 것입니다.
test_the_change_log_currently_changes_no_verdicts가 그것을 고정합니다. 만약 미래의 시나리오가 변경 로그를 결정적으로 만들면, 테스트가 실패하고 이 표는 변경되어야 합니다. 단언이 존재하는 이유가 바로 그것입니다.
일주일 동안 통합한 소스가 판정을 바꾸지 않는다는 것을 발견하는 유일한 방법은 절제입니다.
그리고 아티팩트가 사라질 때
작업은 실패하고, 버킷은 비어 있고, 경로는 바뀝니다. 흥미로운 질문은 에이전트가 여전히 답하는지가 아니라 — 답할 것입니다 — 그것을 인지하는지입니다:
missing drift -> verdict bad_deploy flagged=True
missing evals -> verdict bad_deploy flagged=True
missing changes -> verdict bad_deploy flagged=True세 개 중 두 개의 파일로 조용히 진단하는 에이전트는 거부하는 에이전트보다 나쁩니다. 아무도 그 에이전트를 불신해야 한다는 것을 모르기 때문입니다.
MCP 서버
python -m oncall.mcp_server # stdio, for Claude Desktop et al
python -m oncall.mcp_server --http --port 8931일곱 개의 도구 — list_incidents, get_drift_report, get_eval_run,
get_changes, investigate_incident, compare_incidents, list_specialists
— 그리고 하나의 리소스와 템플릿 리소스가 있습니다.
도구는 산문이 아니라 증거를 반환합니다. 각 도구는 아티팩트 또는 구조화된 진단을 돌려주므로, 클라이언트의 모델은 누군가가 이미 요약한 문단이 아니라 인용이 포함된 데이터를 바탕으로 추론합니다. 요약은 세부 사항이 죽는 곳입니다.
mcp 2.0.0에 맞춰 작성됨 — 그것은 호환성을 깨는 재작성입니다
명시할 가치가 있습니다. 공개된 거의 모든 것이 1.x이고 작동하지 않기 때문입니다. 다음 각 항목은 실행해서 검증되었습니다:
1.x | 2.0.0 |
| 사라짐 — |
| 사라짐 — 저수준 |
|
|
|
|
또한 실제 시간을 소모한 두 가지:
@server.tool()은 반드시 호출되어야 합니다.@server.tool만 단독으로 쓰면 그렇게 말해주는TypeError가 발생합니다.-> dict만으로는structuredContent가 전혀 생성되지 않습니다. 텍스트 콘텐츠는 여전히 있으므로 채팅 클라이언트에서는 정상으로 보이고, 구조화 필드를 읽는 모든 클라이언트를 조용히 깨뜨립니다. 여기의 모든 도구는 그 이유 때문에 매개변수화된 제네릭(Dict[str, Any])을 반환하며, 테스트도 있습니다.
서브프로세스 없이 프로토콜 서버 테스트하기
Client(server)는 서버 객체를 직접 받아들이므로, 전체 프로토콜 왕복이 프로세스 내에서 실행됩니다 — 서브프로세스도, 포트도, 어느 쪽에서 비롯된 불안정성도 없습니다. 그 편의성이 이곳의 프로토콜 테스트가 저렴한 유일한 이유입니다.
빠른 시작
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실제 아티팩트를 지정하세요:
python -m oncall.cli write ./artifacts --scenario bad_deploy
# then: Evidence.load("./artifacts") reads a real pipeline's output unchanged모든 것은 API 키 없이 실행됩니다. investigate --narrate는 GEMINI_API_KEY가 설정되어 있을 때 모델이 작성한 도입 문단을 추가하며, 그 외에는 아무것도 바꾸지 않습니다.
읽어볼 가치가 있는 버그들
하드코딩된 허용 오차가 불안정한 평가 사례를 삼켜버렸습니다. regressions()는 0.02 임계값을 사용했기 때문에 0.006만큼의 변동은 결코 등록되지 않았고 노이즈 검사도 실행되지 않았습니다 — 에이전트는 진실이 noise인 곳에서 healthy라고 말했습니다. 이것은 model-drift-monitor가 반대하는 관습적 임계값 실수가 한 저장소 건너에서 재현된 것입니다. 검출과 유의성은 두 가지 다른 질문입니다: 이제 하한은 0.005("대시보드에 표시되는 모든 것")이고, 하네스 자체가 측정한 noise_std가 판별을 수행합니다.
복구 테스트는 실패할 수 없었습니다. consulted를 미리 채워 넣음으로써 건너뛴 전문가를 위조했습니다 — 그러나 비평가는 available(사용 가능)과 consulted(조회됨)를 비교하므로, 무언가를 consulted로 표시하는 것은 테스트 대상인 바로 그 검사에서 공백을 숨겼습니다. 그것은 recovered: False를 보고했고 고장난 비평가처럼 보였습니다. 결함은 부기가 아니라 라우팅에 주입되어야 합니다. build_graph(skip_first_pass=...)이 그렇게 하며, 이제 비평가는 공백을 실제로 잡아내고 감독자를 되돌려보냅니다.
한계, 명확하게
시나리오는 합성입니다. 의도적입니다 — 실제 인시던트에는 라벨이 붙은 근본 원인이 따라오지 않으며, 그것이 바로 진단이 어려운 이유입니다. 숫자는 운영 시스템이 아니라 방법론을 특성화합니다.
여섯 개의 시나리오는 작은 집합입니다. 여섯 개에서 100%는 일반적으로 100%가 아니며, 다음에 추가되는 시나리오는 그것을 확증하기보다 깨뜨릴 가능성이 더 큽니다.
보정은 여기서 측정할 수 없습니다. 오답이 없으면 신뢰도를 비교할 대상이 없습니다. CLI는 수치를 지어내지 않고
n/a를 출력하며 이유를 설명합니다 —test_calibration_is_honestly_unmeasurable_here가 그것을 고정합니다.가중치는 수동으로 설정됩니다. 가중치는 증거가 얼마나 가치 있는지에 대한 제 판단을 담고 있으며, 더 큰 라벨링된 인시던트 집합이 있다면 대신 적합될 수 있습니다 — 보류된 분할로, 여섯 개의 시나리오에 적합시키는 것은 암기가 되기 때문입니다.
도구 선택 정확도는 항상 존재하는 세 개의 아티팩트가 있으므로 자명하게 1.0입니다. 이 지표가 여기 있는 이유는 네 번째 도구에서부터 중요해지기 때문이며, 소급해서 추가하는 것이 에이전트가 수개월 동안 모든 것을 호출해 왔다는 사실을 발견하는 방법입니다.
실시간 통합은 없습니다. 디스크에서 아티팩트를 읽습니다. 실제 데이터 웨어하우스, CI 시스템, git 호스트에 연결하는 것은 추론 작업이 아니라 배포 작업입니다.
비평가는 완전성과 지지를 검사하지, 정확성을 검사하지 않습니다. 가중치가 틀렸다고 말해줄 수 없고, 단지 증거가 빈약했다는 것만 알려줄 수 있습니다.
로드맵
더 큰 라벨링된 인시던트 집합을 만들고, 보류된 분할에서 가중치를 적합시키기.
더 많은 전문가 — 서빙 지연 시간, 비용 원장, 피처 스토어 신선도 — 도구 선택 정확도가 의미를 갖기 시작하는 지점.
MCP 서버를 시나리오 빌더 대신 실제 아티팩트 소스에 연결하기.
다중 인시던트 상관관계: 세 개의 서비스가 동시에 퇴보하는 것은 세 개의 인시던트가 아니라 하나의 인시던트입니다.
라이선스
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