quellgeist-commits について
Quellgeistのインシデントトリアージ向けに、ローカルのデプロイログから最近のコミットを検索する読み取り専用MCPサーバーです。デプロイ履歴と照合できるコミット情報を返します。
主な機能
- 01最近のコミットを取得
- 02ローカルデプロイログの読み取り
- 03読み取り専用アクセス
活用シーン
- 01インシデント直前のコミット確認
- 02デプロイとエラー信号の関連付け
MCP 対応
stdio経由でMCPクライアントに`get_recent_commits`ツールを公開します。Quellgeistの読み取り専用インシデントトリアージ用MCPサーバーの一つです。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Quellgeist
信頼できる初動のインシデントトリアージです。根本原因の仮説を順位付けし、すべての主張に実在する証拠ハンドルを引用します。そしてエージェントは推測する代わりに回答を差し控えます。
Quellgeist は、モデルに依存しない、本番環境のインシデントを初動でトリアージする AI エージェントです。
読み取り専用ツール(構造化ログ+最近のデプロイ+メトリクス時系列)に対して、解釈しやすい JSON アクションによる ReAct ループを実行し、構造化された Diagnosis を出力します。信頼度順に並べた根本原因の仮説はそれぞれ、エージェントが実際に確認した構造化証拠ハンドル(LogRef.id/CommitRef.sha/MetricRef.id)に裏付けられており、自由形式のテキストは使いません。特徴となるアイデアは2つです。
- 構造化ハンドルによる引用。 証拠は文ではなく検証可能なハンドルであるため、引用の捏造は測定可能であり、キー不要の捏造チェックによって決定論的に拒否されます。あいまいな文字列照合に頼るものではありません。
- ハルシネーションより回答の差し控えを優先。 自信たっぷりに述べられた誤った原因は、最悪の回答です。そのため、*「証拠不十分」*も第一級の結果として扱います。
ステータス:Wave 4 完了 — ファインチューニングは成功しました。 ローカル推論モデル(Ollama 経由で提供される Qwen3-4B)の DR-0020 QLoRA ファインチューニングにより、ベースモデルのホールドアウト評価 0/16 から 12/16へと性能が向上しました。捏造はゼロ、推測的フィルタリングもゼロで、ベースモデルより低コストです。さらに、同じホールドアウト評価で31B の最先端モデル(Gemma-4-31B、10/16)を上回り、完全オフラインでコストは $0です。記憶による再現ではないことを、3つの方法で三角測量しています(フィクスチャ ≈ ホールドアウト、コアの新規データ ≥ コアの重複データ、構造プローブ 7/10)。 注意すべき限界は2つあります。
resource_exhaustionクラスには転移せず(0/N。最先端モデルは通過)、敵対的な回答差し控えの再現率はシステム全体で 6/12 です。これはファインチューニングによる性能低下ではなく、31B の最先端モデルも同じ上限(同じく 6/12)に達しています。このエージェントが失敗するときは、不完全か慎重すぎるだけで、自信満々に捏造することはありません。ステータスとロードマップ · ファインチューニングのケーススタディをご覧ください。
異なる点
| 証拠はハンドルです | 各仮説は、ツールの結果からそのままコピーしたログ行のソース安定 ID またはコミットの sha を引用します。これが、決定論的な捏造チェックで検索される単位です。説明文は表示専用の note に格納されます。(DR-0009) |
| 回答の差し控えは機能です | シグナルが弱い場合、エージェントは理由を添えて abstained=true を返し、仮説リストを空にします。これはスキーマによって強制されます。 |
| 設計上、モデルに依存しません | ループは通常のチャットテキストから JSON アクションを解析するため、Gemini の無料プランでもローカルの4ビット Qwen でも同じように動作し、バックエンド固有のネイティブな関数呼び出しに依存しません。設定を1つ変更するだけでモデルを切り替えられます。(DR-0008、DR-0010) |
| 信頼性は主張ではなくゲートで保証します | キー不要の決定論的な CI ゲート(ruff + black + pytest。フィクスチャを使った評価ハーネスを含む)が、プッシュのたびに実行されます。 |
これは何か/何ではないか
- これは: 初動のトリアージエージェントです。読み取り専用のログ/デプロイ/メトリクスから、モデルに依存しないループを通じて、順位付けされ、根拠が引用された根本原因の仮説(または誠実な回答保留)を提示します。このループは、ホスト型の最先端モデルまたはローカルの 4B モデルで動作します。
- これは違います: 自律的な修復ツールではありません(本番環境に変更を加えることはありません。解決の検証は先送りされた、まず削る対象のウェーブです)。本番環境で堅牢性が検証されたサービスでもありません(デモは意図的にシンプルなものです)。汎用エージェントでもありません。評価に使用するホールドアウトは、語彙外だが構造内のものです。未知のインシデントの形態や実際の本番データについて主張するものではありません。
クイックスタート(約 30 秒でサービスを壊し、構造化ログを確認)
uv と Python 3.12 以降が必要です。
実際の形に近い診断を、キー不要のコマンド 1 つで確認(モデルも API キーも不要):
uv sync && uv run quellgeist diagnose --demo # renders the demo incident's cited postmortem
次に、稼働中のデモサービスに対してループ全体を実行します。
uv run uvicorn demo.app.main:app # 1. start the toy service (leave running)
# --- in a second shell, from the repo root ---
uv run python -m demo.chaos.bad_deploy # 2. inject a simulated bad deploy
curl -s localhost:8000/login # 3. trip /login -> 500s + structured error logs
uv run quellgeist diagnose --show-trace # 4. diagnose live (needs a model; see below)
uv run python -m demo.chaos.reset # back to a green slate
この実行には推論モデルが必要です。詳しくはモデルの実行を参照してください。キーがない場合、quellgeist diagnose は 1 を返し、1 行のエラーとヒントを表示して終了します(トレースバックは表示しません)。--demo はキーなしで常に動作し、ゴールドデータから同じ形式の出力を決定論的に生成します。
アーキテクチャ
独自の分かりやすいループがオーケストレーション層となり、読み取り専用の 3 つのツールが証拠インターフェースとなります。Diagnosis スキーマは、事後分析レンダラーと評価ジャッジの両方が参照する契約です。
flowchart TD
trigger(["incident trigger - CLI"]) --> loop
model["reasoner via LiteLLM<br/>(Gemini or local Qwen, swappable)"] -. "chat completion" .-> loop
subgraph loopbox["model-agnostic JSON-action ReAct loop"]
loop["run_loop()<br/>decide, call tool, observe, repeat"]
end
loop -- "query_logs" --> logs["logs tool<br/>structured JSONL, stable ids"]
loop -- "get_recent_commits" --> commits["commits tool<br/>deploy_log.json, shas"]
loop -- "query_metrics" --> metrics["metrics tool<br/>time-series, named series"]
logs -- "rows + ids" --> loop
commits -- "commits + shas" --> loop
metrics -- "series + names" --> loop
loop --> diag["Diagnosis (schema.py)<br/>ranked hypotheses citing<br/>LogRef.id / CommitRef.sha / MetricRef.id, or abstains"]
diag --> pm["postmortem renderer<br/>deterministic Markdown"]
diag --> judge["eval judge<br/>fixture scenarios, CI gate"]
3 つのツールはすべて、stdio 経由の MCP サーバー(python -m quellgeist.servers.logs_mcp、…commits_mcp、…metrics_mcp)としても公開されています。現在、エージェントは ToolSpec レジストリの背後で同じツール関数をプロセス内で再利用しています。stdio の MCP-クライアント経由でエージェントがサーバーを操作する方式は、ロードマップに記載されています(DR-0010)。
詳細:
docs/architecture.mdでは、パイプライン全体(ループ → ツール → 検証器 → 事後分析)、シーケンス図、モジュールマップ、および横断的な設計判断について説明しています。
各リリースにタグを付けるたびに、サーバーは Official MCP Registry に公開されます(docs/publishing.md を参照)。公開後は、uvx --from quellgeist quellgeist-logs-mcp(または …-commits-mcp / …-metrics-mcp)でそれぞれ実行できます。
セッション例
不具合のあるデプロイを注入します。これによりマーカーがドロップされ、verify_token が NoneType の回帰を起こします。また、エラーの直前に該当コミットが反映されたことを示す deploy_log.json が書き込まれます(例示用の stdout です。タイムスタンプは実行時のものです。パスはリポジトリルートからの相対パスです)。
$ uv run python -m demo.chaos.bad_deploy
injected bad deploy a1b2c3d (touched demo/app/auth.py) at 2026-06-24T12:22:43Z
marker: demo/.bad_deploy
deploy log: demo/deploy_log.json
next: hit /login to generate the 500s, then `quellgeist diagnose`
推論モデルが設定されている場合、quellgeist diagnose はログとデプロイ情報を読み取り、事後分析を出力します。CI 環境には検証済みのモデルキーがないため(DR-0012)、以下の診断はゴールドデータからレンダリングされています。フィクスチャにラベル付けされた原因と証拠ハンドルから render_postmortem を使って決定論的に生成されたものであり、モデルの実出力ではありません。
# Incident Postmortem (rendered from gold)
## Root-cause hypotheses
### 1. Bad deploy a1b2c3d (10:01:50Z) refactored auth.py and introduced a NoneType error in verify_token; /login 500s begin ~20s later at 10:02:12Z. (confidence: 1.00)
Evidence:
- log #2
- commit a1b2c3d
同じレンダリングを自分で再現できます(モデルは不要です)。
uv run python - <<'PY'
from evals.scenarios.generator import load_scenario
from quellgeist.agent.schema import Diagnosis, Hypothesis
from quellgeist.output.postmortem import render_postmortem
s = load_scenario("evals/scenarios/fixtures/bad_deploy_0001.json")
gold = Diagnosis(hypotheses=[
Hypothesis(cause=s.gold_cause, confidence=1.0, evidence=s.gold_evidence_refs)
])
print(render_postmortem(gold, title="Incident Postmortem (rendered from gold)"))
PY
重要なのは文章ではありません。log #2 と commit a1b2c3d が、言い換えではなく、実際のシグナルを直接参照する正確なハンドルである点です。実際の実行では、1 行の要約と推奨アクションも追加されます。また、確信を持って原因を特定するには証拠が弱すぎる場合は、明確に回答を保留します。
--out postmortem.md を指定すると事後分析をファイルに書き込めます。また、自己完結型の HTML ページとして --out postmortem.html(または --format html)を指定することもできます。いずれも同じ決定論的なレンダリングで、外部アセットは使用しません。
モデルの実行
推論器には任意の LiteLLM モデル文字列を指定します。--model または QG_MODEL 環境変数で選択します(デフォルトは gemini/gemini-3.5-flash)。プロバイダーのキーは LiteLLM が環境変数から読み込み、リポジトリには保存されません。
export QG_MODEL="gemini/gemini-3.5-flash"
export GEMINI_API_KEY="…"
uv run quellgeist diagnose --show-trace
Ollama を使えば完全にローカルかつオフラインでも実行できます。これが想定されているホーム環境でのデフォルトです(DR-0008。正確なアーティファクトは DR-0019 で固定されています)。API キーは不要です。
ollama pull qwen3:4b-instruct-2507-q4_K_M
export QG_MODEL="ollama_chat/qwen3:4b-instruct-2507-q4_K_M"
uv run quellgeist diagnose --show-trace
ベースモデルとチューニング済みモデルの違い — 重要です。 上記の
ollama pullで取得するのは ベースモデルの Qwen3-4B です。これは誠実で安全な 最低限の性能 を担保します。ホールドアウトデータでは 0/16 点で、すべてのケースで回答を控え、決して捏造しません(DR-0019)。12/16 という見出しの数値は、finetune/README.mdに従ってビルドしてサーブする DR-0020 のファインチューニング済みモデル(無料の Colab QLoRA 実行 →ollama create)のものです。チューニング済み GGUF がワンライナーで取得できるよう公開されるまでは、通常のollama pullで得られるのはベースモデルです。安全ですが、まだ実用性はありません。実際の診断を確認するには、ホスト型モデル(上記)かファインチューニング済みモデルを使用してください。
注意事項(DR-0012):検証されていない課金設定のないプロジェクトの Gemini キーを使うと、現在のモデルでは 429 limit: 0 が返されます。そのため、同梱の CI ゲートは意図的にキー不要とし、モデルを使った評価はキーがある場合に限り、CI 外で実行します(DR-0015)。自宅で使う場合に想定されているデフォルトの推論器は、Ollama 経由のローカル Qwen3-4B です(DR-0008)。
評価の実行(推論器+検証器+LLM 審査員)
フィクスチャ評価では、決定論的なキーワード審査員と捏造ゼロのチェック(キー不要のゲート)を使って推論器を採点します。さらに、2 つのモデル層(DR-0016)を実行できます。1 つは引用した根拠が各仮説を裏付けているか確認し、裏付けがなければ回答を控える検証器、もう 1 つは助言的な評価基準を用いる LLM 審査員です。
export GEMINI_API_KEY="…"
export QG_MODEL="gemini/gemini-3.5-flash"
QG_VERIFY=1 QG_JUDGE_LLM=1 \
QG_MIN_CALL_INTERVAL_S=6 \ # pace calls under the free-tier RPM (avoids 429 bursts)
uv run python -m evals.run_evals
QG_VERIFIER_MODEL/QG_JUDGE_MODEL を設定すると、各層で使用するモデルを上書きできます(デフォルトは QG_MODEL)。バックエンドに接続できない場合(クォータ超過/503/タイムアウト)、または認証情報が拒否された場合(キーの欠落/無効/期限切れ)は、失敗ではなくスキップとして報告されます(DR-0015/DR-0017)。そのため、CI 外の評価が無料枠の一時的な不具合で失敗扱いになることはありません。LLM 審査員のスコアは参考情報であり、ゲートとして使われることはありません。人手でラベル付けしたゴールドサブセットでは、独立した審査員(groq/llama-3.1-8b-instant ≠ 推論器)を使った場合、人間の判定と Cohen のカッパ係数 0.81 で一致しました。このサブセットで検証済みです(DR-0018)。ただし、QG_JUDGE_MODEL が推論器と同じ場合は、引き続き自己採点となります。
CI 外の評価は Groq で実行されます(
groq/llama-3.3-70b-versatile、GROQ_API_KEYが必要です)。Gemini の無料枠はクラウド CI から利用できないことが判明しました(429 → 503 → タイムアウト → 無効なキー)。そのため、環境変数を 1 つ変更して推論器を切り替えました。これはモデル非依存という理念の実践例です(DR-0017)。想定されている自宅環境でのデフォルトは、引き続きローカルの Qwen3-4B です(DR-0008)。
実データでの使用
デモでは、形式が標準化された 3 つのファイルを使いますが、本番環境のシグナルはそのような形ではありません。quellgeist ingest はアダプターです。実際のデータソースを指定すると、ツールが読み込む標準ファイルを作成します。
quellgeist ingest \
--logs /var/log/myapp/ # file or directory; JSONL, JSON, plain text, or mixed
--deploys deploys.json # JSON array, GitHub payload, or `git log` text
--metrics prom.json # a Prometheus response or a canonical array
--out-dir ./signals
# prints the `export QG_*` lines; then:
quellgeist diagnose --show-trace --strict-citations # add --model / a provider key
形式が整っていない実データにも対応します(外部のフィールド名はスキーマに合わせて別名を付け、タイムスタンプは UTC に正規化し、不正な行は実行をクラッシュさせずに強制変換します)。また、query_logs は 1 回の観測で返す行数を制限します(QG_MAX_ROWS、デフォルトは 200)。そのため、ログが大きくてもコンテキストウィンドウがあふれません。決定論的な「引用するか、回答を控える」保証は実利用時にも適用されます。diagnose は引用されたすべてのハンドルを実際のシグナルと照合し、捏造があれば警告します(CI で使う場合、--strict-citations を指定するとゼロ以外の終了コードで終了します)。詳しくは、ガイド docs/ingestion.md を参照してください。
ライブサービスを実行する(v2)
v2では、同じ変更禁止のコアを、ライブで並行処理と可観測性を備えたインシデント対応サービスでラップします。署名付き webhook が調査を開始し、ワーカープールがインシデントごとに分離されたスナップショット上で変更されていないループを実行します。トレースとコストを含む各実行は SQLite に永続化され、オペレーターが Slack と自己完結型の HTML ページへの投稿前に承認/誘導/却下します。さらに、サンドボックスで修正を行った後、エージェントがシグナルを再読み込みして復旧を確認します。すべて追加機能であり、変更禁止の測定対象は一切変更されません。スタック全体を 1 つのファイルから実行できます:
cp .env.example .env # set QG_WEBHOOK_SECRET, QG_OPERATOR_TOKEN, QG_VERIFIER_MODEL…
docker compose up --build # demo service + agent service + Ollama
docker compose exec ollama ollama pull qwen3:4b-instruct-2507-q4_K_M # first run only
# break it, trigger an investigation, review, then confirm the fix in the sandbox:
docker compose exec demo python -m demo.chaos.bad_deploy
# … POST a signed incident to :8000/incidents, approve it on the HTML page …
docker compose exec demo python -m demo.chaos.fix_deploy # heal without wiping the log
# … POST /incidents/{id}/verify-resolution → recovered | not_recovered | inconclusive
シークレットは環境変数のみに保持します(公開リポジトリのため)。このサービスはフェイルクローズです。webhook シークレットがない場合はすべてのリクエストを拒否し、オペレータートークンがない場合はオペレーター向け機能を閉じます。また、捏造した診断や未検証の診断を投稿することはありません。設計については、DR-0023 と 仕様を参照してください。
ステータスとロードマップ
段階的なウェーブで構築しています。詳細に実装されているのは現在のウェーブのみです
(docs/quellgeist-plan-rolling-wave.mdを参照)。
すべての意思決定の履歴は
ADR ログに記録されています。
| ウェーブ | 対象範囲 | ステータス |
|---|---|---|
| 0 | モデル選定のリスクを下げる(4B でループをオーケストレーションできるか) | ✅ 完了 — デフォルト = Qwen3-4B(DR-0008) |
| 1 | 不適切なデプロイの一連の流れ:デモ → 障害発生 → 診断 → 事後分析;評価ハーネス + CI | ✅ 完了 — 基幹部分を構築し、単体テストを実施 |
| 2 | 信頼性のコア:検証パス、決定論的な捏造チェック、棄権、LLM-as-judge | ✅ 構築済み — キー不要の決定論的ゲート + オプトインの検証器/判定器;捏造ゼロで初回の実運用に成功(DR-0016/DR-0017)。判定器の検証 + 信頼性の割合はウェーブ 3 に引き継ぎ |
| 3 | 対応範囲の拡大:設定/環境 + リソース枯渇のクラス、メトリクス、約 50 のシナリオ | ✅ 完了 — 65 シナリオのスイートで 3 クラスに対応;初回の全件実行は 61/65、捏造 0 件;判定器を検証済み(カッパ係数 0.81)。信頼性と判定器のケーススタディを参照 |
| 4 | コスト/ファインチューニング:QLoRA で Qwen3-4B とベースモデルおよび最先端モデルを比較、検証器の有無も比較 | ✅ 完了 — ホールドアウトでベースモデルは 0/16 → ファインチューニング済みモデルは 12/16(捏造 0 件、推測フィルター 0 件、ベースモデルより低コスト);Gemma-4-31B と同等の競争力(能力では 10/16 で上回り、棄権では 6/12 で同点);resource_exhaustion は未学習で、敵対的な状況での棄権は共通して 6/12 が上限(ケーススタディ、DR-0019/DR-0020) |
| 5 | 仕上げとリリース:HTML レンダリング、セキュリティ確認、MCP レジストリ、ローンチ | 🚧 エンジニアリング完了 — リリース待ち(HTML レンダリング + セキュリティスキャナー + 脅威モデル + レジストリ/OIDC の足場は完了;残る作業はリリースタグとローンチ) |
| 6 | 解決確認ループ | ⤳ v2(ウェーブ 9)に統合 |
| v2(7–9) | ライブのインシデント対応サービス(webhook → 並行ワーカー → 実行の永続化 → HITL レビュー → Slack/HTML → サンドボックスでの解決再確認)+ Dockerfile/compose | ✅ 構築済み — ウェーブ 7–9 をリリース済み:署名付き webhook → 並行ワーカー → 根拠を示した実行の永続化 → フェイルクローズの HITL レビューゲート → Slack/HTML → 決定論的なサンドボックスでの解決再確認;非 root の Docker + compose;キー不要のテスト 339 件、変更禁止部分の差分は空(DR-0023/0027/0028、仕様) |
| v2 トラック B(10) | 信頼性トラック:タイミングを考慮した検証器 + 構造を変えた/構造外への汎化評価 | 🚧 スコープ策定済み — DR-0024–0026 |
ウェーブの区切りは意図的なもので、未完成という意味ではありません。詳細に構築されているのは現在のウェーブのみで、後続のウェーブはスコープを定めたうえで、意図的に未実装としています。v2 は実証済みの v1 コアへの追加機能であり、変更禁止のファインチューニング測定対象には一切手を加えません
(DR-0023;tests/frozen/ で保護)。
信頼性ゲート
決定論的な CI ゲートが信頼性の契約です。339 件のテスト(ruff +
black を pre-commit で実行後、pytest を実行。ループのクラッシュしない動作/適切な棄権、決定論的な捏造チェックと引用ベースの判定ゲート、検証器と助言用 LLM 判定器、パラメーター化されたシナリオ生成、判定検証ハーネス、サーバーフィルター、事後分析レンダラー、フィクスチャを利用した評価ハーネス、実データの取り込みと堅牢性レイヤー、エンドツーエンドの実インシデント用ハーネス、v2 ライブサービス(署名付き webhook、インシデントごとの並行分離、HITL レビューゲート、決定論的なサンドボックス解決チェック)を網羅)を Python 3.12 および 3.13 で実行します。
別途、モデル駆動型評価では、65 シナリオのスイートで推論器を実行します。最新の全件実行では 61/65 件が合格し、捏造された証拠は 0 件でした(Cerebras Gemma-4-31B)。クラスごとの内訳と失敗分析については、信頼性ケーススタディをご覧ください。
uv run pytest tests/ -q
uv run pre-commit run --all-files
開発と貢献
開発環境のセットアップ、規約、wave モデルについては CONTRIBUTING.md を、報告方法とシークレットを含めない/おもちゃのデモに関するポリシーについては SECURITY.md を、コミュニティの行動規範については CODE_OF_CONDUCT.md をご覧ください。バグ報告と機能リクエストには issue templates を使用し、PR は PR template に従ってください。
ライセンス
MIT © Rajeev Shyam Kumar.
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。