ML On-Call Agent
ML On-Call Agent
「昨夜の実行はなぜリグレッションしたのか?」 —— ドリフトレポート、評価実行、デプロイログを関連付けて答え、主張のすべてに引用を付けるマルチエージェントシステム。
MCP 経由で公開されているため、ツールは任意の MCP クライアントから利用できる。
ステータス: 65 テスト。診断は重み付けされた証拠から決定的に計算されるため、以下の数字はすべてアサーションであり、デモではない。
実際の問題
ML システムは静かに劣化する。誰かがようやく気づいたとき、証拠は互いに通信しない3つの場所に散らばっている:
ドリフトレポート —— 入力分布は動いたか?
評価実行 —— オフラインスコアはリグレッションしたか、どのスライスで?
デプロイログ —— 誰か何かをデプロイしたか?
それらを関連付けるのは仕事であり、3つの JSON ファイルを頭の中で同時に保持することを意味するため、午前3時に人々が下手に行う仕事である。
これら3つのアーティファクトはこのリポジトリのために発明されたものではない。それらは
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、ランダムより悪い)。
指摘できるものは何もない。答えは2つの否定と1つの肯定——ドリフトなし、デプロイなし、ランキング崩壊——を組み合わせることから得られる。これは単一のアーティファクトの要約なら見逃すであろうまさにそのものである。また、model-drift-monitor がそれ自体について文書化している盲点を、1層上から診断したものでもある。
すべてが依存する設計上の決定
診断は決定的である。言語モデルはナレーションするだけである。
明白な構築方法は、3つの JSON ファイルをプロンプトに貼り付けて何が悪かったのかを尋ねることだ。それは毎回流暢な何かを生成する——証拠が何も支持しない場合も含めて——そしてテスト不可能である。なぜなら散文に対してアサーションできず、正しい答えと運のいい答えを区別できないからだ。
そこで推論は普通の Python で行われる:
各スペシャリストは1つのアーティファクトを読み、
Findingを出力するすべての finding は引用——ファイル、フィールド、値——を保持する。
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 は、モデルがある場合とない場合で判定が同一であることをアサートする。もし失敗したら、モデルが推論を始めたということ——そして推論はその瞬間からテスト不可能になる。
診断力の大部分は否定的証拠にある。「ドリフトなし」と「何もデプロイされていない」は、重みを持つ finding である。ドリフト 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直線的なパイプラインにはない2つの特性:
批評家は作業を送り返すことができる。 判定が2つのアーティファクトに依存しているのに3つ目が読まれていない場合、証拠の半分から導かれた結論を公開するのではなく、コントロールはスーパーバイザーに戻る。
サイクルは有界である。 MAX_REVISIONS = 2 が上限を定め、recursion_limit が逃げ出したものを捕捉する。ループできるエージェントは無限にループできるエージェントであり、暴走したオンコールエージェントはページに答える代わりにページを生成する。
これはLLM も API キーもなしで実行される——スーパーバイザーはプレーンな Python ルールでルーティングする——そのため、ルーティング、委任、批評家のループバックはすべてオフラインでユニットテストされる。test_the_graph_and_the_plain_loop_agree は、LangGraph 実行とプレーンな for ループがすべてのシナリオで同一の判定に達することをアサートし、グラフが推論ではなくオーケストレーションを追加することを証明する。
各アーティファクトの実際の価値
python -m oncall.cli ablate証拠 | タスク成功率 | アクション精度 |
3つすべて | 100% | 100% |
ドリフトなし | 67% | 67% |
評価なし | 67% | 67% |
変更ログなし | 100% | 100% |
正直な否定的結果であり、静かに忘れられないようアサートされている。 変更ログを削除しても、このシナリオセットでは何もコストがかからない——bad_deploy はドリフトと評価の証拠だけからすでに分離可能である。変更ログは、診断を変えることではなく、コミットを特定することによってその地位を獲得する。これは人間が行動するために必要なことだ。
test_the_change_log_currently_changes_no_verdicts がそれを固定する。将来のシナリオがそれを決定的にした場合、テストは失敗し、この表は変更されなければならない。それがアサーションの目的である。
アブレーションは、統合に1週間かけたソースが判定を1つも変えないことを発見する唯一の方法である。
そしてアーティファクトが失われたとき
ジョブは失敗し、バケットは空になり、パスは変わる。興味深い質問は、エージェントがまだ答えるかどうかではなく——答えるだろう——気づくかどうかである:
missing drift -> verdict bad_deploy flagged=True
missing evals -> verdict bad_deploy flagged=True
missing changes -> verdict bad_deploy flagged=True3つのファイルのうち2つから静かに診断するエージェントは、拒否するエージェントより悪い。なぜなら誰もそれを信用してはいけないと知らないからだ。
MCP サーバー
python -m oncall.mcp_server # stdio, for Claude Desktop et al
python -m oncall.mcp_server --http --port 89317つのツール——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 |
| 削除 —— |
| 削除 —— 低レベル |
手動の |
|
|
|
さらに実時間を費やした2つ:
@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 が反対している民間伝承のしきい値の間違いであり、1リポジトリ先で再現されたものである。検出と有意性は2つの質問である: 下限は現在 0.005(「ダッシュボードが表示するものなら何でも」)であり、ハーネス自身の測定された noise_std が判別を行う。
回復テストは失敗できなかった。 consulted を事前にシードすることでスキップされたスペシャリストを偽装した——しかし批評家は利用可能と相談済みを比較するため、何かを相談済みとマークすることは、テストされているまさにそのチェックからギャップを隠した。それは recovered: False を報告し、壊れた批評家のように見えた。障害は簿記ではなくルーティングに注入されなければならない。build_graph(skip_first_pass=...) がそれを行い、批評家は現在、ギャップを実際に捕捉してスーパーバイザーを送り返すことが実証されている。
制限事項、率直に述べる
シナリオは合成的である。 意図的に——実際のインシデントにはラベル付きの根本原因が付属しない。それがまさに診断が難しい理由である。数字は方法を特徴付けるものであり、本番システムを特徴付けるものではない。
6つのシナリオは小さなセットである。 6つでの100%は一般的な100%ではなく、次に追加されるシナリオはそれを確認するよりも壊す可能性が高い。
キャリブレーションはここでは測定不能である。 誤答がないため、信頼度を比較する対象がない。CLI は数字をでっち上げる代わりに
n/aを印刷して理由を述べる——test_calibration_is_honestly_unmeasurable_hereがそれを固定する。重みは手動設定である。 それらは証拠の価値に関する私の判断をコード化しており、より大きなラベル付きインシデントセットがあればフィッティングできるだろう——ホールドアウト分割で。6つのシナリオにフィッティングすることは記憶化になるからだ。
ツール選択精度は、3つの常時存在するアーティファクトでは自明に 1.0 である。 この指標がここにあるのは、4つ目のツールで重要になり始めるからであり、事後的に追加することは、エージェントが何ヶ月もすべてを呼び出していたことを発見する方法である。
ライブ統合はない。 ディスクからアーティファクトを読む。実際のウェアハウス、CI システム、git ホストに配線することは、推論の仕事ではなくデプロイの仕事である。
批評家は完全性と支持をチェックし、正しさはチェックしない。 重みが間違っているとは言えず、証拠が薄いことだけを言える。
ロードマップ
より大きなラベル付きインシデントセット、そしてホールドアウト分割で重みをフィッティングする。
より多くのスペシャリスト——サービングレイテンシ、コスト台帳、フィーチャーストアの鮮度——これはツール選択精度が意味を持ち始める場所である。
MCP サーバーをシナリオビルダーではなく実際のアーティファクトソースに配線する。
マルチインシデント相関: 3つのサービスが同時にリグレッションすることは、3つのインシデントではなく1つのインシデントである。
ライセンス
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