# 04. デモシナリオ（Day 3）

2026-10-05 · 社内検討用

デモは **「顧客対応エージェントが、銀行の基幹に安全に照会と振込依頼をする」** 9つの場面で構成し、所要は約20分です。7つの統制がすべて、実際に動くところで見られます。実装は `demo/`、実行手順は [05_demo_runbook.md](05_demo_runbook.md) にあります。

## 1. 登場人物と権限

| 人・システム | 役割 | 持つ権限 | ポイント |
| --- | --- | --- | --- |
| alice | 顧客（口座 ACC-001、ACC-002） | 参照、更新、承認者ロールも保持 | 承認者ロールを持っていても、エージェント経由では承認できない |
| bob | 顧客（口座 ACC-101） | 参照のみ | 更新系のツールがエージェントに見えない |
| carol | 業務オペレーター | 参照、承認、監査 | 高額振込を承認する独立した人間 |
| agent-concierge | 顧客対応エージェント | 利用者の権限のうち参照・更新だけを委任される | 承認と監査の権限は、委任の対象外 |
| core-banking-mock | 基幹（勘定系）の模擬 | — | 障害注入で失敗させられる |

## 2. 構成

```mermaid
flowchart LR
    U[利用者 alice / bob] --> A[顧客対応エージェント<br/>LLM: qwen3:8b on Ollama]
    A -- "MCP /mcp/read<br/>banking-reader" --> T[agent-tools<br/>Quarkus + MCP Server]
    A -- "MCP /mcp/write<br/>banking-writer" --> T
    O[オペレーター carol] -- "/api/approvals<br/>transfer-approver" --> T
    T -- "参照: REST" --> C[(core-banking-mock)]
    T -- "更新: Outbox → Camel Saga<br/>hold → transfer / release" --> C
    K[Keycloak<br/>RHBK 相当] -. トークン .-> A
    K -. トークン .-> O
    A & T & C -. "OTLP（同じトレース ID）" .-> J[Tempo]
    J --> G[Grafana]
    T & C -. メトリクス .-> P[Prometheus → Grafana]
```

OpenShift で動かす場合は、エージェントと agent-tools の間に Connectivity Link のゲートウェイを置きます（`demo/openshift/`）。ローカルでは、同じ判断をアプリ側の多層防御で再現しています。

## 3. 振込の流れ（高額で障害が起きる場合）

```mermaid
sequenceDiagram
    autonumber
    participant A as エージェント
    participant T as agent-tools
    participant DB as DB（依頼・Outbox・監査）
    participant O as carol（承認者）
    participant C as 基幹
    A->>T: request_transfer(300,000円, 冪等キー)
    T->>T: ガードレール（回数・注入・個人情報）
    T->>DB: 依頼=承認待ち、監査記録（同一トランザクション）
    T-->>A: PENDING_APPROVAL
    O->>T: approve（本人以外のみ）
    T->>DB: 依頼=承認済み ＋ Outbox（同一トランザクション）
    T->>C: 資金の拘束（hold）
    T->>C: 振替（失敗 → 再試行2回）
    C--xT: 503（障害が続く）
    T->>C: 拘束の解除（補償）
    T->>DB: 依頼=COMPENSATED、Outbox 完了、監査記録
```

## 4. 場面と話す内容

| 場面 | 見せること | 統制 | 話す要点（30秒） |
| --- | --- | --- | --- |
| 1 | 自分の口座と明細。相手先の口座番号は伏せられる | 2・3 | 参照でも「見せすぎない」設計が要る。出力側のガードレールの例 |
| 2 | 他人の口座（ACC-101）は見られない | 2 | ゲートウェイの役割確認に加え、データ単位の所有者確認をツール側で行う |
| 3 | 参照権限だけの bob には、更新系のツール群自体が出てこない | 1・2 | 権限のないツールは、エージェントに選択肢として見せない。プロンプトで禁止するより確実 |
| 4 | 少額振込は即実行。同じ冪等キーで再送しても1回分しか動かない | 5 | LLM は同じ依頼を二度出すことがある。冪等キーはエージェント側で決め、LLM に任せない |
| 5 | 高額振込は承認待ち。エージェントのトークンでも、本人でも承認できない。carol が承認して実行 | 4 | 「人間の承認」は、エージェントの権限の外に置く。職務分掌もシステムで強制する |
| 6 | 基幹の障害1回は再試行で吸収。続く障害は補償（拘束の解除）で元に戻る | 5 | 差別化の核。エージェントが書き込んだ後の整合性は、統合の設計で守る |
| 7 | 「以前の指示を無視して…」やカード番号入りのメモを、ツールの手前で止める | 3 | ガードレールはモデルの外に置く。止めた記録もトレースと監査に残る |
| 8 | 更新系の連打を回数制限で止める | 4 | 暴走時の最大影響を事前に数値で言える。本番ではゲートウェイの RateLimitPolicy |
| 9 | 監査証跡のハッシュ連鎖。1件書き換えると検証で検出される | 7 | 監査部門が自分で検証できる。すべての記録にトレース ID が付き、Grafana（Tempo）で経緯を辿れる |

### 可観測性（統制6）を見せるタイミング

場面4と6のあとで Grafana の Explore（データソース Tempo）を開き、1本のトレースが **エージェント → LLM → ツール → Camel → 基幹** とつながっていることを見せます。場面6では、補償（`core-release`）のスパンと、エラーになった振替のスパンが並びます。Grafana のダッシュボード（`http://localhost:3000/d/agent-safe-connect`）では、ガードレールの遮断数、補償件数、承認待ち件数が増えるのが見えます。

実測のトレース（場面4に相当する LLM 経由の振込）は次のとおりです。

```
agent-concierge    invoke_agent concierge (25973 ms)
  agent-concierge    chat qwen3:8b (18725 ms)
  agent-concierge    execute_tool request_transfer (124 ms)
    agent-tools        execute_tool request_transfer (116 ms)
      agent-tools        GET /core/accounts/{id} (1 ms)
        core-banking-mock  GET /core/accounts/{id} (0 ms)
      agent-tools        dispatch (77 ms)
          agent-tools        transfer-saga (66 ms)
              agent-tools        core-hold (54 ms)
                    core-banking-mock  POST /core/holds (21 ms)
              agent-tools        core-transfer (7 ms)
                    core-banking-mock  POST /core/transfers (4 ms)
  agent-concierge    chat qwen3:8b (7122 ms)
```

所要時間の大半は LLM（ローカルの 8B モデル）で、ツールと基幹は 0.1 秒程度です。こうした内訳がすぐ見えること自体が、運用部門への説明材料になります。

## 5. LLM を使う版と使わない版

| 版 | 使う場面 | コマンド |
| --- | --- | --- |
| 台本版（LLM なし） | 説明しながら確実に見せたいとき。E2E テストとしても使う | `demo/agent/.venv/bin/python demo/agent/demo_scenario.py --pause` |
| 対話版（LLM あり） | 「本物のエージェント」を見せたいとき | `demo/agent/.venv/bin/python demo/agent/concierge.py --user alice "…"` |
| 評価版 | モデルを替えても安全かを見せるとき | `demo/agent/.venv/bin/python demo/agent/run_eval.py` |

評価版の注目点は、注入攻撃のケース（S1）です。モデルは高額の振込を実際に依頼してしまいましたが、統制によって承認待ちで止まりました。**安全性をモデルの善意に頼らず、統制で担保している** ことを示す場面として使えます。

## 6. デモで言わないこと・注意

- ローカル版の Keycloak は、簡単のためパスワード・グラントでトークンを取っています。本番では認可コード + PKCE と、トークン交換（RFC 8693）を使います。
- ローカル版は H2（インメモリ DB）です。本番では PostgreSQL などに Outbox と監査証跡を永続化します。
- 基幹は模擬です。実在の勘定系の仕様を示すものではありません。
