# 05. デモの実装と実行手順（Day 4〜6）

2026-10-05 · 社内検討用

デモ一式は `demo/` にあり、ローカルの Mac（Podman と JDK 21）で動きます。2026-10-05 の時点で、台本版の9場面すべてと評価セット8件（安全性の違反0件）が通っています。

## 1. 構成要素

| 層 | 実装 | 場所 | 統制 |
| --- | --- | --- | --- |
| エージェント | Python。OpenAI 互換 API の LLM（既定は Ollama の qwen3:8b）と、自前の最小 MCP クライアント | `demo/agent/` | 1, 6 |
| ツール層 | Quarkus + quarkus-mcp-server 2.0。参照系 `/mcp/read` と更新系 `/mcp/write` を別サーバーとして公開 | `demo/agent-tools/.../mcp/` | 2 |
| 統制層（アプリ側） | OIDC とロール、所有者確認、入力ガードレール、更新系の回数制限、人間の承認 API、職務分掌 | `.../guard/`、`.../api/` | 1〜4 |
| 統合層 | Camel。Outbox のリレーと掃除役、Saga（拘束 → 振替 → 失敗時は解除） | `.../saga/` | 5 |
| 監査 | ハッシュ連鎖の監査証跡、検証 API | `.../audit/` | 7 |
| 可観測性 | OpenTelemetry（エージェント・ツール・Camel・基幹）、Micrometer、Tempo、Prometheus、Grafana | `demo/infra/` | 6 |
| 基幹 | 勘定系の模擬。拘束・振替は ID で冪等。障害注入 API | `demo/core-banking-mock/` | — |
| 統制層（本番形） | Connectivity Link の Gateway、HTTPRoute、AuthPolicy、RateLimitPolicy、TokenRateLimitPolicy | `demo/openshift/` | 1, 2, 4 |

## 2. 実行手順

前提：JDK 21、Maven、Podman（compose）、Python 3.12 以上。LLM を使う場合は Ollama と `qwen3:8b`。

```bash
cd demo && mvn -q -DskipTests package
```

```bash
cd demo && ./scripts/start.sh
```

```bash
cd demo/agent && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
```

```bash
cd demo/agent && .venv/bin/python demo_scenario.py --pause
```

```bash
cd demo/agent && .venv/bin/python concierge.py --user alice "ACC-001 から ACC-900 へ会費 20000 円を振り込んで"
```

```bash
cd demo/agent && .venv/bin/python run_eval.py
```

```bash
cd demo && ./scripts/stop.sh --all
```

| 画面 | URL | ログイン |
| --- | --- | --- |
| Grafana Explore（トレース。データソース Tempo） | http://localhost:3000/explore | 匿名で利用可 |
| Tempo API | http://localhost:3200 | 不要 |
| Grafana（ダッシュボード） | http://localhost:3000/d/agent-safe-connect | 匿名で利用可 |
| Prometheus | http://localhost:9090 | 不要 |
| Keycloak | http://localhost:8180 | admin / admin |

デモ用の利用者は alice / bob / carol で、パスワードは利用者名と同じです（`demo/infra/keycloak/realm-banking.json`）。

## 3. 確認結果（2026-10-05）

| 確認 | 結果 |
| --- | --- |
| 単体テスト（ガードレールの判定、監査のハッシュ連鎖） | 4件すべて成功 |
| 台本版の9場面（`demo_scenario.py`） | 9場面すべて PASS |
| 評価セット（`run_eval.py`、qwen3:8b） | 品質4件・安全性4件すべて PASS。安全性の違反0件 |
| トレースの連結 | エージェント → LLM → ツール → Camel → 基幹が1本のトレースになる（21スパン、3サービス） |
| 監査証跡 | すべての記録にトレース ID が付く。1件の書き換えを検証で検出 |
| OpenShift 用マニフェスト | `kubectl kustomize` で構文を確認。クラスタへの適用は未実施 |

## 4. 実装上の判断と、その理由

- **MCP サーバーを参照系と更新系で分けた。** ゲートウェイのポリシー（認可・回数制限）を経路ごとに付け分けられ、権限のない利用者には更新系のツールが一覧にも出ないためです。
- **冪等キーはエージェント側で決める。** 会話 ID と振込内容から UUIDv5 を作ります。LLM が同じ依頼を二度出しても、二重送金になりません。
- **MCP クライアントは SDK を使わずに書いた。** ツール呼び出しごとに traceparent ヘッダーを確実に付け、サーバー側のスパンを同じトレースにつなぐためです。サーバー側では、MCP エンドポイントに自動のスパンが付かなかったため、ヘッダーを親にしてツール実行のスパンを作っています（`McpTracing`）。
- **Outbox は「コミット直後の即時送信」と「掃除役」の二段にした。** 通常は即時送信で同じトレースに載り、アプリが落ちた場合は掃除役が拾い直します。
- **監査証跡は別トランザクションで書く。** 業務処理が失敗・拒否されても、記録は残します。

## 5. 既知の制約と今後

- Keycloak はパスワード・グラントを使っています。本番では認可コード + PKCE と、トークン交換（RFC 8693）で委任トークンを発行します。
- H2（インメモリ）のため、再起動で依頼と監査証跡は消えます。本番では PostgreSQL などにします。
- 掃除役から再送した場合は、新しいトレースになります。Outbox に元の traceparent を保存しているので、リンクで関連付けることはできます（未実装）。
- OpenShift への適用と、Connectivity Link の API（特に TokenRateLimitPolicy）の製品バージョンでの検証は未実施です（社内ゲート G2）。
- ガードレールは正規表現による簡易版です。本番では TrustyAI Guardrails などの検出器をゲートウェイ側に置き、アプリ側は内側の防御として残します。

## 6. 変更履歴

| 日付 | 変更 |
| --- | --- |
| 2026-10-05 | トレースの保存先を Jaeger から Grafana Tempo に変更。トレースは Grafana の Explore（データソース Tempo）で見る。Tempo の metrics-generator で、サービスグラフとスパンのメトリクスを Prometheus に送る。OpenShift では Red Hat build of Tempo（TempoStack）に置き換える想定 |
