Claude Codeでマルチエージェント自律運用システムを作った話 ── Blue/Red Team を5体のサブエージェントで回す
はじめに
Claude Code の Task ツール(サブエージェント機能) を使って、Windows PC の自律運用システムを構築しました。Blue Team(防御/運用)4体と Red Team(攻撃シミュレーション)1体、計5体のサブエージェントを Lead Agent が指揮する構成です。
この記事では、実装の全体像からエージェント定義の書き方、Red Team 攻撃チェーンの設計、そして26項目のテスト結果までを解説します。
何ができるシステムか
- 1分ごとにシステム監視(CPU/メモリ/ディスク/サービス/イベントログ/ネットワーク)
- 異常検知時に自動障害対応(サービス再起動、ディスク解放、エスカレーション)
- 定期的なバックアップ、ログ・テンプクリーンアップ、レポート生成
- Red Team による自動攻撃シミュレーション → Blue Team が検知できるかの自動テスト
全てが Windows Task Scheduler から claude -p で起動され、人間の介入なしに回り続けます。
アーキテクチャ
全体構成
Windows Task Scheduler
├── AutoOps-Monitor (1分間隔) → claude -p "Run the monitoring cycle mode."
├── AutoOps-DailyOps (5分間隔) → claude -p "Run the daily-ops cycle mode."
├── AutoOps-Infra (10分間隔) → claude -p "Run the infra cycle mode."
└── AutoOps-RedTeam (3分間隔) → claude -p "Run the redteam cycle mode."
│
Lead Agent (CLAUDE.md)
Task ツールでサブエージェントを起動
│
┌───────┬───────┼───────┬────────┐
▼ ▼ ▼ ▼ ▼
monitor ops infra incident redteam
-agent -agent -agent -agent -agent
3層アーキテクチャ
| 層 | 役割 | ファイル |
|---|---|---|
| エージェント層 | 判断・調整・結果パース |
.claude/agents/*.md (5ファイル) |
| スキル層 | 手順書(何をどの順で実行するか) |
.claude/skills/*.md (5ファイル) |
| スクリプト層 | 実際の処理(PowerShell, JSON出力) |
scripts/**/*.ps1 (22ファイル) |
設計上の重要ルール: サブエージェントは他のサブエージェントを起動できない。全ての調整は Lead Agent が行う。
ディレクトリ構成
auto_ops/
├── .claude/
│ ├── agents/ # サブエージェント定義(5体)
│ │ ├── monitor-agent.md
│ │ ├── ops-agent.md
│ │ ├── infra-agent.md
│ │ ├── incident-agent.md
│ │ └── redteam-agent.md
│ ├── skills/ # スキルファイル(手順書)
│ │ ├── monitor.md
│ │ ├── ops.md
│ │ ├── infra.md
│ │ ├── incident.md
│ │ └── redteam.md
│ └── settings.local.json # 権限設定
├── CLAUDE.md # Lead Agent の指示書
├── scheduler/
│ └── setup-tasks.ps1 # Task Scheduler 登録スクリプト
├── scripts/
│ ├── monitor/ # 監視スクリプト(4本)
│ ├── ops/ # 運用スクリプト(4本)
│ ├── infra/ # インフラスクリプト(3本)
│ ├── incident/ # 障害対応スクリプト(3本)
│ └── redteam/ # 攻撃スクリプト(8本)
├── config/ # 設定ファイル
├── logs/ # ログ
└── reports/ # レポート・スコアカード
サブエージェントの定義方法
エージェント定義ファイルの構造
.claude/agents/ にマークダウンファイルを配置します。YAML フロントマターでメタデータを定義し、本文にエージェントへの詳細指示を書きます。
---
name: monitor-agent
description: Run system health monitoring checks and detect anomalies
tools: Bash, Read, Write, Grep, Glob
model: haiku
skills:
- monitor
---
| フィールド | 説明 |
|---|---|
name |
エージェント名。Task ツールの subagent_type で指定する |
description |
1行説明。Lead Agent がどのエージェントを使うか判断する材料 |
tools |
このエージェントが使えるツール |
model |
使用モデル。定型タスクなので haiku でコスト最適化 |
skills |
.claude/skills/ のスキルファイルを読み込む |
monitor-agent の定義例(抜粋)
---
name: monitor-agent
description: Run system health monitoring checks and detect anomalies
tools: Bash, Read, Write, Grep, Glob
model: haiku
skills:
- monitor
---
# Monitor Agent - System Health Monitoring (Blue Team)
You are the Monitor Agent for Auto Ops. Your job is to run all
monitoring scripts, parse results, check thresholds, and report anomalies.
## Execution Steps
1. Run all four monitoring scripts in sequence:
powershell -ExecutionPolicy Bypass -File ".../check-system-health.ps1"
powershell -ExecutionPolicy Bypass -File ".../check-services.ps1"
powershell -ExecutionPolicy Bypass -File ".../check-eventlog.ps1"
powershell -ExecutionPolicy Bypass -File ".../check-network.ps1"
2. Parse each script's JSON output and determine overall status.
3. Read config/thresholds.json and compare results against thresholds.
4. Log results to logs/ops-YYYY-MM-DD.log
5. Identify anomalies exceeding thresholds.
6. Check for Red Team attack indicators.
## Output Format
Return a JSON-structured summary to the Lead Agent:
{
"status": "OK|WARNING|CRITICAL",
"checks": { ... },
"anomalies": [...],
"redteam_indicators": [...]
}
ポイント: 出力フォーマットを JSON で明確に定義すること。Lead Agent がパースして次のアクションを判断するため、構造化された出力が必須です。
5体のエージェント一覧
| エージェント | チーム | 担当スクリプト | 判断ロジック |
|---|---|---|---|
| monitor-agent | Blue | check-system-health, check-services, check-eventlog, check-network | 閾値比較、RT検知 |
| ops-agent | Blue | backup, cleanup-logs, cleanup-temp, generate-report | 結果集約 |
| infra-agent | Blue | manage-services, check-updates, check-firewall | サービス状態判定 |
| incident-agent | Blue | restart-service, free-disk-space, escalate | 復旧判断、エスカレーション |
| redteam-agent | Red | random-attack, cleanup-attack + 6攻撃スクリプト | 安全チェック、クールダウン |
Lead Agent(CLAUDE.md)の設計
Lead Agent はスクリプトを直接実行しない指揮官です。Task ツールでサブエージェントを起動し、返ってきた結果を見て次のアクションを決めます。
監視サイクルの例
### `monitoring` - Monitoring Cycle (every 1 minute)
1. Launch monitor-agent:
Task(monitor-agent, "Run a full monitoring cycle.")
2. Parse the monitor-agent's returned JSON result.
3. If anomalies detected (status WARNING or CRITICAL):
- Launch incident-agent with the anomaly details:
Task(incident-agent, "Respond to anomaly: <anomaly details>")
4. Log the cycle summary to logs/ops-YYYY-MM-DD.log
これが意味すること: Lead Agent は自然言語で書かれた「指揮マニュアル」に従い、状況に応じて適切なエージェントを呼び出します。if 文もループも PowerShell ではなく、CLAUDE.md の自然言語で表現されています。
Red Team チェーン ── 最も複雑なフロー
Red Team サイクルは、5体中4体のエージェントが連携する最も複雑なフローです。
Step 1: Lead → Task(redteam-agent, "Execute a random Red Team attack")
→ 結果: { attack_type: "tamper_files", attack_timestamp: "..." }
Step 2: Lead → powershell Start-Sleep -Seconds 30
(Blue Team に検知チャンスを与える)
Step 3: Lead → Task(monitor-agent, "Run monitoring. RT attack 'tamper_files' at ...")
→ 結果: { anomalies: [...], redteam_indicators: [...] }
Step 4: Lead → 検知判定
detected = redteam_indicators.length > 0
detection_time = monitor_timestamp - attack_timestamp
Step 5: Lead → Task(incident-agent, "Respond to anomaly: ...")
→ 結果: { recovery_action: "logged" }
Step 6: Lead → Task(redteam-agent, "Run cleanup")
→ 結果: { items_cleaned: 3 }
Step 7: Lead → reports/redteam-scorecard.md を更新
攻撃シナリオ(6種類)
| 攻撃タイプ | 内容 | 検知方法 |
|---|---|---|
stress_cpu |
バックグラウンドで計算負荷 | CPU使用率の閾値超過 |
stress_memory |
大容量バイト配列確保 | メモリ使用率の閾値超過 |
fill_disk |
ダミーファイル大量作成 | ディスク空き容量低下 |
kill_service |
許可されたサービスを停止 | サービス状態異常 |
tamper_files |
config/ に不審ファイル作成 | 不審ファイル検出 |
inject_log_errors |
偽エラーログ注入 | エラーログ急増検知 |
全ての攻撃ファイルには [REDTEAM-TEST] マーカーが含まれ、クリーンアップスクリプトで完全に除去されます。
安全設計
## Safety Rules (MANDATORY)
1. NEVER modify files under C:\Windows or C:\Program Files
2. NEVER stop or modify protected services: wuauserv, WinDefend, EventLog
3. NEVER execute more than 1 concurrent Red Team attack
4. ALWAYS cleanup after Red Team attacks
5. Red Team files must contain [REDTEAM-TEST] marker
Red Team エージェントは攻撃と後片付けだけを担当。30秒待機、検知判定、スコアカード更新は全て Lead Agent が行います。これにより、Red Team エージェントが暴走しても被害範囲が限定されます。
権限設定
settings.local.json
{
"permissions": {
"allow": [
"Bash(powershell:*)",
"Bash(dir:*)",
"Read(*)",
"Write(logs/*)",
"Write(reports/*)",
"Write(scripts/*)",
"WebSearch",
"Task(monitor-agent)",
"Task(ops-agent)",
"Task(infra-agent)",
"Task(incident-agent)",
"Task(redteam-agent)"
]
}
}
Task(<agent-name>) の形式で、Lead Agent が起動できるサブエージェントを明示的にホワイトリスト登録します。
スケジューラの --allowedTools
$allowedTools = @(
'"Bash(powershell:*)"',
'"Read(*)"',
'"Write(logs/*)"',
'"Write(reports/*)"',
'"Task(monitor-agent)"',
'"Task(ops-agent)"',
'"Task(infra-agent)"',
'"Task(incident-agent)"',
'"Task(redteam-agent)"'
) -join ' '
$actionArgs = "-p `"$($TaskDef.Prompt)`" --allowedTools $allowedTools"
claude -p でヘッドレス実行するとき、--allowedTools で許可するツールを制限できます。これにより、スケジューラ経由で起動された Claude が意図しない操作を行うリスクを軽減します。
スケジューラ設定
Windows Task Scheduler に4つのタスクを登録します。
# setup-tasks.ps1 -TestMode で登録
$tasks = @(
@{
Name = "AutoOps-Monitor"
Prompt = "Run the monitoring cycle mode. Launch monitor-agent..."
Interval = if ($TestMode) { 1 } else { 5 } # 分
},
@{
Name = "AutoOps-DailyOps"
Prompt = "Run the daily-ops cycle mode. Launch ops-agent..."
Interval = if ($TestMode) { 5 } else { 1440 } # 分
},
@{
Name = "AutoOps-Infra"
Prompt = "Run the infra cycle mode. Launch infra-agent..."
Interval = if ($TestMode) { 10 } else { 60 } # 分
},
@{
Name = "AutoOps-RedTeam"
Prompt = "Run the redteam cycle mode. Launch redteam-agent..."
Interval = if ($TestMode) { 3 } else { 60 } # 分
}
)
| タスク | テストモード | 本番 |
|---|---|---|
| Monitor | 1分 | 5分 |
| DailyOps | 5分 | 24時間 |
| Infra | 10分 | 1時間 |
| RedTeam | 3分 | 1時間 |
テスト結果
26項目のテストを実施し、全てPASS(1件の不具合を検出し即時修正)。
テスト概要
| カテゴリ | テスト数 | PASS | FAIL |
|---|---|---|---|
| エージェント定義検証 | 5 | 5 | 0 |
| 設定ファイル検証 | 5 | 5 | 0 |
| 監視スクリプト実行 | 4 | 4 | 0 |
| 運用スクリプト実行 | 4 | 4 | 0 |
| インフラスクリプト実行 | 3 | 3 | 0 |
| RedTeamスクリプト実行 | 2 | 2 | 0 |
| 障害対応スクリプト実行 | 3 | 3 | 0 |
| 合計 | 26 | 26 | 0 |
監視スクリプトの実行結果
{
"timestamp": "2026-02-07 22:24:03",
"check": "system_health",
"status": "CRITICAL",
"cpu": { "percent": 36.3, "status": "OK" },
"memory": {
"total_mb": 32472,
"used_mb": 31827,
"used_percent": 98,
"status": "CRITICAL"
},
"disks": [{
"drive": "C:",
"free_gb": 691.3,
"used_percent": 25.8,
"status": "OK"
}]
}
メモリ 98% は実環境の状態をそのまま反映しています。閾値チェックで CRITICAL 判定 → incident-agent が自動起動される流れが確認できました。
Red Team 攻撃→クリーンアップ チェーン
1. random-attack.ps1 実行
→ 攻撃タイプ: tamper_files
→ config/ に不審ファイル2つ作成
2. cleanup-attack.ps1 実行
→ 3アイテム削除(ファイル2 + マーカー1)
→ [REDTEAM-TEST] マーカー付きファイルを完全除去
// 攻撃実行結果
{
"action": "random_attack",
"selected_attack": "tamper_files",
"status": "EXECUTED",
"result": {
"attack_id": "REDTEAM-FILE-20260207222602",
"files_created": [
"config/[REDTEAM-TEST]-...-suspicious.json",
"config/[REDTEAM-TEST]-...-hidden.dat"
]
}
}
// クリーンアップ結果
{
"action": "cleanup_attack",
"status": "OK",
"items_cleaned": 3
}
検出した不具合と修正
テスト中に1件の不具合を発見しました。
問題: infra-agent.md がサービス一括チェック時に manage-services.ps1 -Action "status" を -ServiceName パラメータなしで呼び出す指示になっていた。スクリプト側は [Parameter(Mandatory=$true)] でエラーになる。
修正: config/monitored-services.json からサービス一覧を読み取り、各サービスを個別にチェックする手順に変更。
# 修正前(エラー)
powershell ... manage-services.ps1 -Action "status"
# 修正後(正常動作)
1. Read config/monitored-services.json to get service list
2. For each service:
powershell ... manage-services.ps1 -Action "status" -ServiceName "<name>"
こうした不具合はテストを回す前にエージェント定義だけレビューしても見つけにくいものです。実際にスクリプトを実行するテストの重要性を再認識しました。
コスト設計
サブエージェントに model: haiku を指定することで、コストを大幅に削減しています。
| 層 | モデル | 理由 |
|---|---|---|
| Lead Agent | Sonnet / Opus | ルーティング判断、結果パース、スコアカード更新 |
| サブエージェント5体 | Haiku | 定型スクリプト実行、JSON出力の集約 |
サブエージェントの仕事は「指定されたスクリプトを実行し、結果をJSONで返す」という定型タスクです。高度な推論は不要なので、最も安価な Haiku で十分です。
コスト比の目安:
- 監視サイクル1回 = Lead Agent (Sonnet) 1ターン + monitor-agent (Haiku) 数ターン
- Haiku は Sonnet の約 1/10 のコスト → サブエージェント部分のコストは非常に小さい
設計で意識したこと
1. 責務の明確な分離
Lead Agent に全権限を集中させず、各サブエージェントに最小限の責務を持たせました。
- monitor-agent: 見るだけ。システム状態を変更しない
- incident-agent: 復旧するだけ。監視はしない
- redteam-agent: 攻撃と片付けだけ。検知判定はしない
2. サブエージェントは他のサブエージェントを呼べない
全ての調整を Lead Agent に集約することで、エージェント間の依存関係が単純になり、デバッグが容易になります。
× monitor-agent → incident-agent(直接呼び出し)
○ monitor-agent → Lead Agent → incident-agent(Lead 経由)
3. JSON による構造化通信
サブエージェントの出力フォーマットを JSON で厳密に定義しました。自然言語だけのやり取りでは、Lead Agent の判断が曖昧になりがちです。
{
"status": "CRITICAL",
"anomalies": ["Memory usage 98% exceeds threshold 90%"],
"redteam_indicators": []
}
Lead Agent はこの JSON を見て「anomalies が空でない → incident-agent を起動」と判断します。
4. 安全境界の多層防御
Layer 1: settings.local.json → 許可されたツールのみ使用可能
Layer 2: --allowedTools → スケジューラ経由の実行を制限
Layer 3: CLAUDE.md → Safety Rules で禁止操作を明示
Layer 4: エージェント定義 → 各エージェントの Safety Rules
Layer 5: スクリプト内 → protected services リスト照合
Layer 6: config ファイル → monitored-services.json でホワイトリスト
まとめ
Claude Code の Task ツールを使ったマルチエージェントシステムは、以下のパターンで構築できます。
- スクリプト層: 実際の処理を PowerShell で実装(JSON 出力)
-
スキル層:
.claude/skills/*.mdに手順書を記述 -
エージェント層:
.claude/agents/*.mdにエージェント定義(YAML フロントマター + 詳細指示) -
Lead Agent:
CLAUDE.mdにルーティングロジックを自然言語で記述 -
権限:
settings.local.jsonと--allowedToolsで多層的に制御 -
スケジューラ: Windows Task Scheduler →
claude -pでヘッドレス実行
人間が書くのはマークダウンと PowerShell だけ。コーディネーションのロジックは自然言語で表現され、Claude が解釈・実行します。
リポジトリ構成の最終状態
| 種別 | ファイル数 |
|---|---|
| エージェント定義 | 5 |
| スキルファイル | 5 |
| PowerShell スクリプト | 22 |
| 設定ファイル | 4 |
| スケジューラスクリプト | 1 |
| Lead Agent 指示書 | 1 |
| 合計 | 38 |
テスト結果: 26/26 PASS、1件の不具合を検出・修正済み。
本記事のシステムは教育・検証目的で構築されたものです。Red Team の攻撃シミュレーションは全て安全で可逆的な操作に限定されています。
Discussion