🧭 本記事は Claude Code実務運用シリーズ の STEP 6「サブエージェント化する」です。
エージェントチームを開発以外の調査業務へ。反証役(skeptic)と合議で結論の偏りを防ぐ7体構成を設計します。
シリーズ全体の地図と読む順は 親記事 にまとめています。
この記事でわかること
- 会社のURLを1件入れると、7つのサブエージェントが公開情報を調査し、「ブラック企業リスクのシグナルスコア(0-100)」を根拠と確信度付きで推定するツールをClaude Codeで作った
- 一番効いたのは、分析エージェントではなく「反証専任のエージェント(skeptic)」。他のエージェントの所見を「この会社は実はブラックではない」という立場から攻撃させる品質ゲートを工程に組み込んだ
- 試験運用では、skepticが「同一口コミの二重計上」「キャッシュ日付一点に依存した投機的推定」「審査なしの自己宣言登録を"認定"として過大評価」などを実際に捕まえた
- センシティブな題材なので、断定しない・公開データのみ・実名スコアは非公開という設計をアーキテクチャレベルで強制している。本記事はその設計の話であり、特定企業の分析結果は一切含まない
はじめに — 作ったもの、作っていないもの
「ブラック企業かどうかをAIが判定します」というツールを作った話……ではありません。
作ったのは、企業の公開情報(公式サイト・求人票・厚労省の公表事案・決算公告・報道)を複数の専門エージェントが並列調査し、「リスクシグナルの推定」を確信度と反証付きで出力する分析パイプラインです。この2つの違いは決定的で、後述する設計の大半は「判定ツールにしない」ためにあります。
LLMにこの種の評価をさせると、次の2つの失敗が高確率で起きます。
- 過検出(false positive): 「裁量労働制」「求人が常に出ている」「口コミ評点3.2」みたいな、業界では普通のシグナルを片っ端から黒く塗る
- 断定: 推定にすぎないものを「この会社は危険です」と言い切る
この記事は、この2つをマルチエージェントの構造で抑え込む設計の紹介です。
なぜマルチエージェントにしたのか
単一のプロンプトで「この会社を調査して」とやると、以下の問題が起きます。
- コンテキストの汚染: 調査の生データ(HTMLやPDFの中身)が会話コンテキストを埋め尽くし、後半の判断の質が落ちる
- 視点の混線: 「求人票を読む目」と「財務を読む目」と「反証する目」は要求される姿勢が違うのに、1つのコンテキストでは互いに引っ張られる。特に致命的なのは、自分が見つけた所見を自分で反証するのは構造的に難しいこと(確証バイアス)
- 並列化できない: 求人・評判・法令・財務の調査は独立なのに直列で待つことになる
そこでClaude Codeのサブエージェント機能(.claude/agents/*.md)で役割を7つに分割し、オーケストレーション指示はCLAUDE.mdに書きました。ディレクトリ構成は次のとおりです。
black-check/
├── CLAUDE.md # オーケストレーション指示(ワークフロー・スコアリングモデル)
├── .claude/agents/ # 7エージェント定義
│ ├── crawler.md
│ ├── recruit-analyst.md
│ ├── reputation-scout.md
│ ├── compliance-checker.md
│ ├── org-analyst.md
│ ├── skeptic.md
│ └── chief-editor.md
├── templates/
│ ├── report-template.html # 実名レポート(ローカル専用)
│ └── qiita-template.md # 匿名化済み公開用素材
└── reports/ # 分析結果(実名版はここから外に出さない)
この構成の全ファイル(reports/を除く)は、記事末尾の付録に全文を折りたたみで載せています。合計10ファイル・599行、これがシステムの全部です。
全体アーキテクチャ — 6工程
| # | 工程 | エージェント | 並列 |
|---|---|---|---|
| 1 | 一次情報収集(公式サイト・採用ページ) | crawler | - |
| 2 | 求人票分析 | recruit-analyst | ★ |
| 2 | 外部評判調査(口コミ・ニュース・訴訟) | reputation-scout | ★ |
| 2 | 法令違反照合(厚労省公表事案など) | compliance-checker | ★ |
| 2 | 組織・財務健全性分析 | org-analyst | ★ |
| 3 | 反証・過検出チェック | skeptic | - |
| 4 | 合議・スコア確定・レポート生成 | chief-editor | - |
ポイントは3つ。
- 工程2の4エージェントは1つのメッセージで同時起動する(Claude Codeは1メッセージ内の複数Agent呼び出しを並列実行できる)。各エージェントには最初にcrawlerの結果JSONのパスを渡す
-
エージェント間のハンドオフは会話ではなくJSONファイル。各エージェントは
reports/<日付>-<ドメイン>/work/<agent>.jsonに構造化した結果を保存し、次工程はそれを読む。これで(a)オーケストレーター側のコンテキスト消費が最小になり、(b)skepticとchief-editorの判断根拠が後から監査できる - skepticは工程2の全結果を、chief-editorはskepticの反証を含む全結果を受け取る。合議の材料がファイルとして揃っているので、最終レポートの全所見に出典を残せる
エージェント定義の実例 — 「事実」と「解釈」を分離させる
エージェント定義はMarkdown+frontmatterだけです(CLAUDE.md・テンプレートも含めた全ファイルの全文を記事末尾の付録に折りたたみで載せています)。まずcrawler(工程1)の定義から抜粋します。
---
name: crawler
description: 企業の公式サイト・採用ページ・ニュースリリースを収集し、一次情報を構造化する調査員。
tools: WebFetch, WebSearch, Read, Write, Bash
---
## ルール
- 事実(引用)と解釈(所見)を明確に分ける。引用には出典URLを付ける。
- robots.txtやログイン壁で取得できないページは無理に取らず fetch_failures に記録する。
- qualitative_signals.score は公式サイトの定性シグナルのみで0-100(高いほどリスク)。
サイトの見た目の古さはリスク根拠にしない(無関係のため)。
出力スキーマも定義に埋め込んでいます。
{
"company": {"name": "", "founded": "", "capital": "", "employees": ""},
"recruit_pages": [{"url": "", "salary_raw": "", "conditions_raw": "", "quote": ""}],
"disclosed_metrics": {"turnover_rate": null, "avg_tenure": null, "overtime": null},
"qualitative_signals": {"score": 0, "confidence": "高|中|低", "findings": []},
"fetch_failures": ["取得できなかったページとその理由"]
}
地味ですが効くのは次の3点です。
-
salary_raw/conditions_raw/quote: 求人票は要約ではなく原文のまま引用させる。後段のrecruit-analystが「固定残業代の記載が本当にないか」を原文でスキャンでき、skepticが「引用が文脈を歪めていないか」を検証できる -
fetch_failures: 取れなかったものを取れなかったと記録させる。LLMは空欄を埋めたがるので、「欠損の申告」を出力スキーマの一級市民にしておかないと、幻覚で埋まる - 「サイトの見た目の古さはリスク根拠にしない」: 実際に走らせると、LLMはデザインが古いサイトを減点したがる。無関係な特徴での減点は明示的に禁止しないと混入する
本命: skeptic — 「全部黒く塗る」を防ぐ最後の砦
このシステムの心臓部です。定義ファイルをほぼそのまま載せます。
---
name: skeptic
description: 工程2の全分析結果に対して反証を試みる懐疑派(Devil's Advocate)。
過検出を抑える品質ゲートとして工程3で単独起動する。
tools: WebSearch, WebFetch, Read, Write
---
あなたは懐疑派の反証担当です。他の4エージェントの分析結果(work/*.json)を読み、
**「この会社は実はブラックではない」という立場**から各所見を攻撃してください。
このツールの最大の失敗モードは「疑わしいものを全部黒く塗る」ことであり、
あなたはそれを防ぐ最後の砦です。
## 反証の観点
- 業界標準との比較: そのシグナルは業界全体に共通の慣行ではないか
- 成長企業仮説: 大量採用・急拡大は事業成長で説明がつかないか
- サンプルバイアス: 口コミは退職者に偏る。件数は従業員規模に対して異常か
- 時期の問題: 古いシグナル(5年以上前)がその後改善された形跡はないか
- 同名混同: 同名他社の情報が findings に混入していないか
- 引用の妥当性: evidence の引用は文脈を歪めていないか
## ルール
- 反証にも根拠を付ける。「かもしれない」だけの反証は strength「弱」。
- ただし擁護のしすぎも禁物。公的記録(公表事案照合など)は
照合ミスの検証以外では覆せない。
- upheld を必ず書くこと。全所見を棄却する出力は職務放棄とみなす。
出力は「反証」「反証を試みたが崩せなかった所見(upheld)」「新たに見つけたポジティブ材料」の3部構成です。
{
"rebuttals": [
{"target": "エージェント名/所見", "rebuttal": "反証内容",
"strength": "強|中|弱", "recommended_adjustment": "棄却|severity引き下げ|維持"}
],
"upheld": ["反証を試みたが崩せなかった所見(=信頼できる所見)"],
"counter_evidence": ["新たに見つけたポジティブ材料"]
}
実際に何を捕まえたか
複数社(いずれも匿名化)の試験分析で、skepticは以下のような過検出を実際に検出・修正させました。どれも、分析エージェント単体では気づけない構造の問題です。
1. 同一ソースの二重計上(クロスカテゴリ汚染)
ある社の分析で、「事業がうまくいっていない」という趣旨の単一の古い口コミ1件が、外部評判カテゴリ(重み25%)と組織・財務カテゴリ(重み15%)の両方の減点根拠になっていました。並列エージェントは互いの出力を見ないので、同じスニペットをそれぞれが「発見」すると、1つの未検証情報が総合スコアを二重に押し下げます。しかもこの口コミは、別エージェントが取得した直近の増収データと矛盾していました。skepticはこれを「strength: 強」で指摘し、chief-editorが片方のカテゴリから除外しました。
2. 一点依存の投機的推定
「同じ求人が数年間掲載され続けている=高離職の代理指標」という所見が、求人サイトのキャッシュに残っていた日付1つを根拠にしていました。一方で従業員数は数年で明確に純増しており、「回転ドア(大量採用・大量離職)」仮説と矛盾します。skepticは推定の脆弱性と反証データを並べて severity引き下げを勧告しました。
3. 「認定」と「自己宣言」の混同(楽観バイアス側)
skepticは減点方向だけでなく加点方向の誤りも指摘させています。ある社で複数のエージェントが「自治体の働き方関連制度に認定されている」をポジティブ材料に数えていましたが、skepticが制度自体を調べ直すと、それは審査を伴う認定ではなく企業側の自己宣言登録でした。ポジティブ材料の格下げです。「懐疑派」を減点の門番としてだけ設計すると、今度は擁護方向の誤りが素通りします。反証は対称でなければならない。
4. サンプルバイアスの補正
「平均年収が相場より明らかに低い」という所見が、実は特定の雇用区分(短時間スタッフ)の口コミに引っ張られた数値で、正社員求人の提示レンジと乖離していたケース。口コミ評点についても「そのサイトの全企業平均は3.0前後」という基準値を検索で確認し、「評点3点台前半=ブラック」という短絡を棄却しました。
skeptic設計で学んだ3つのコツ
-
upheld(崩せなかった所見)を必須出力にする。 これがないと、skepticは「全部棄却」か「全部維持」の怠慢な出力に退化しがちです。「反証を試みたが崩せなかった」リストは、そのまま信頼できる所見のホワイトリストになり、chief-editorの合議が楽になります - 公的記録は覆せないルールにする。 労働局の公表事案PDFとの照合結果のような一次資料由来の所見まで「反証」させると、屁理屈が生まれます。skepticにできるのは照合ミス(同名混同など)の検証だけ、と権限を区切りました
- 反証にも根拠を要求し、根拠のない反証は strength「弱」に落とす。 「かもしれない」だけの反証で所見が棄却されるなら、それは品質ゲートではなくノイズです
スコアリングモデル — 「評価不能」を0点にも満点にもしない
カテゴリ別スコア(各0-100、高いほどリスク)を重み付き平均します。
| カテゴリ | 重み | 担当 |
|---|---|---|
| 法令違反・行政指導の実績 | 30% | compliance-checker |
| 外部評判(口コミ・ニュース) | 25% | reputation-scout |
| 求人票の危険シグナル | 20% | recruit-analyst |
| 組織・財務の健全性 | 15% | org-analyst |
| 公式サイトの定性シグナル | 10% | crawler |
重みの根拠はシンプルで、客観性の高い情報源ほど重くする。厚労省の公表事案(公的記録)が最重量30%、主観と偏りを含む口コミが25%、企業の自己申告である求人票・公式サイトは軽め、です。
数値以外のルールが本体です。
- 確信度を必ず併記する。 各カテゴリに高/中/低の確信度を付ける。データの大半が検索スニペット由来で原文照合できていないなら、スコアがいくつであれ確信度は「中」止まり
- データが取れなかったカテゴリは「評価不能」とし、重みを他カテゴリに按分しない。 按分すると「調べられなかった会社ほど、たまたま調べられたカテゴリの点数で総合が乱高下する」ことになります。総合スコアに「データ欠損あり」と明記して、欠損を欠損のまま見せる
- 総合75点以上は、公的記録などの客観的裏付けがある場合のみ許可。 口コミの印象がいくら悪くても、公的裏付けなしに最上位のリスクラベルは付けられない構造にする
- 欠損はスコアではなく確信度に反映する。 「離職率が非開示」を減点材料にすると、非上場企業がほぼ全部黒くなります(業界標準の非開示)。スコアは動かさず確信度を下げ、「監視項目」として残す
chief-editor — 合議と、2種類の出力
最終工程のchief-editorは、skepticの反証を機械的に適用してスコアを確定します。
1. skepticの rebuttals を各カテゴリの findings に適用する:
- 棄却(strength 強) → 該当所見を除外し、カテゴリスコアを再計算
- severity引き下げ → 該当所見の severity を1段階下げる
- 維持/strength 弱 → そのまま
2. 重み付き平均で総合スコアを算出。「評価不能」カテゴリは按分せず明記
3. 総合スコア75以上は、公的記録等の客観的裏付けがある場合のみ許可
そして出力は必ず2種類に分かれます。
-
report.html(実名版) — 全所見に出典URL付きの詳細レポート。ローカル閲覧専用で、リポジトリの
reports/から外に出さない - qiita.md(匿名版) — 公開してよいのはこちらだけ。chief-editorの定義に匿名化チェックリストを埋め込んでいます
- [ ] 社名 → 「A社」
- [ ] ドメイン・URL → 削除または example.co.jp 化
- [ ] 所在地 → 都道府県レベルまで
- [ ] 代表者名・役員名 → 削除
- [ ] 事業内容 → 特定できない粒度に抽象化(「◯◯業界の中堅企業」)
- [ ] 引用文 → 検索で元企業が特定できる特徴的な文言はパラフレーズする
- [ ] 従業員数・設立年 → 概数化(「従業員100名規模」「設立10年前後」)
さらにオーケストレーター側でも、生成後にgrepで社名・ドメイン・代表者名・固有サービス名などの残留を機械的に再検証します。エージェントの自己申告(「匿名化しました」)を信用せず、検証を別レイヤーに置く。これは匿名化に限らず、エージェントに何かを保証させたいときの一般則だと思います。
grep -niE "社名|ドメイン|代表者名|固有サービス名|所在地|許可番号" qiita.md \
|| echo "OK: 特定可能な固有情報は検出されず"
やってみてわかったこと
並列エージェントは互いが見えない、を設計で補う。 二重計上(同一ソースが複数カテゴリの根拠になる)は、並列ファンアウト構成の宿命的な失敗モードです。合流地点(skeptic/chief-editor)に「カテゴリ横断でソースの重複を探せ」という明示的な仕事を置かない限り、誰も気づきません。
「懐疑」は両方向に向ける。 過検出チェックだけをやらせると、今度はポジティブ材料の誤り(自己宣言を認定と読む、親会社が大手だから安全というハロー効果)が素通りします。skepticには「擁護のしすぎも禁物」「楽観バイアスも指摘せよ」を明示しました。
欠損の申告を出力スキーマに組み込む。 fetch_failuresやdata_gapsをスキーマの必須フィールドにしておくと、「取れなかった」が幻覚で埋まる事故が激減し、最終レポートの「データ欠損あり」表記まで一直線に流れます。実行環境の都合でフェッチが失敗する日もあり(その日は検索スニペット経由の情報しか取れない)、それも確信度の低下として最終出力に正直に伝播します。
プロンプトで一番効くのは禁止事項ではなく「失敗モードの名指し」。 「断定するな」より「このツールの最大の失敗モードは疑わしいものを全部黒く塗ることであり、あなたはそれを防ぐ最後の砦です」の方が明確に効きます。役割に物語を与えると、エージェントはその役割の側から考え始めます。
限界と、倫理面の設計
正直に書きます。
- 精度は保証できません。 口コミサイトは規約の関係で直接スクレイピングせず、検索結果経由の要約に留めているため、引用の多くは原文照合されていません。厚労省の公表事案リストは掲載期間が約1年で、「掲載がない=違反がない」ではありません
- これは判定機ではありません。 出力はどこまでいっても「公開情報から推定したリスクシグナル」で、確信度と反証が常に併記されます。就職・取引の意思決定に単独で使うべきものではありません
- 実名の分析結果は公開しません。 実名スコアの公開は、内容の真偽にかかわらず名誉毀損・信用毀損のリスクがあります。だから「実名版はローカル専用、公開用は匿名化を機械検証」をワークフローの構造に焼き込みました。この記事に特定企業の分析結果が一切登場しないのも同じ理由です
むしろこの「安全側に倒す設計をアーキテクチャで強制する」部分こそ、LLMでセンシティブな評価タスクを扱うすべての場面に転用できる、このプロジェクトの一番の成果物だと思っています。
まとめ
- 評価系のLLMタスクは、分析エージェントを増やすより、反証エージェントを1つ置く方が品質が上がる(体感)
- 反証は対称に(過検出と楽観バイアスの両方)、
upheldを必須に、公的記録は不可侵に - ハンドオフはJSONファイルで。監査可能性はプロンプトではなく成果物の形式から生まれる
- 欠損は按分せず、スコアではなく確信度に反映する
- センシティブな出力は「作らせない」のではなく、「安全な形でしか出せない構造」にする
7つのMarkdownファイルと1つのCLAUDE.mdだけで、ここまでの合議制が組めるのはClaude Codeのサブエージェント機構の面白いところです。同じパターンは、コードレビュー(指摘係+反証係)、インシデント分析(原因仮説係+反証係)、技術選定(推進係+懐疑係)など、「LLMが断定しがちな評価タスク」全般に流用できるはずです。
付録: リポジトリ全ファイル(全文)
このシステムを構成するのは、オーケストレーション指示のCLAUDE.mdが1つ、.claude/agents/のエージェント定義が7つ、出力テンプレートが2つ——**合計10ファイル・599行(実測)**です。マルチエージェントというと大掛かりに聞こえますが、実体はこれだけです。本文で抜粋したものも含め、すべて全文を載せます。エージェント定義はfrontmatterのtoolsがそのエージェントに許可するツール、descriptionがオーケストレーターの起動判断に使う説明です。
なおreports/配下(分析結果)だけは載せません。「実名版レポートをローカルから出さない」というルールは、この記事自身にも適用されるためです。
CLAUDE.md — オーケストレーション指示(ワークフロー・スコアリングモデル・大原則)
# black-check — 企業リスクシグナル分析チーム
会社のURLを1件入力すると、7エージェントが公開情報を調査し、
「ブラック企業リスクスコア(0-100)」を根拠付きで推定するプロジェクト。
## 大原則(必ず守ること)
1. **断定しない。** 出力は常に「リスクシグナルの推定」であり「ブラック企業の認定」ではない。
レポートには必ず確信度と反証(懐疑派の見解)を併記する。
2. **公開データのみ使う。** ログインが必要なサイトのスクレイピング、口コミサイトの規約違反となる
自動収集はしない。口コミは検索結果経由の要約に留める。
3. **Qiita用出力は必ず匿名化する。** 企業名・ドメイン・特定可能な固有情報を「A社」等に置換する。
実名スコアの公開は名誉毀損・信用毀損のリスクがあるため、実名版はローカルのHTMLレポートのみ。
## 使い方
```
「https://example.co.jp を分析して」
```
URL 1件を受け取ったら、下記ワークフローを実行する。
## ワークフロー(6工程)
| # | 工程 | 担当エージェント | 並列 |
|---|------|----------------|------|
| 1 | 一次情報収集(公式サイト・採用ページ) | crawler | - |
| 2 | 求人票分析 | recruit-analyst | ★ |
| 2 | 外部評判調査(口コミ・ニュース・訴訟) | reputation-scout | ★ |
| 2 | 法令違反照合(厚労省公表事案など) | compliance-checker | ★ |
| 2 | 組織・財務健全性分析 | org-analyst | ★ |
| 3 | 反証・過検出チェック | skeptic | - |
| 4 | 合議・スコア確定・レポート生成 | chief-editor | - |
- 工程2の4エージェントは、crawlerの収集結果を渡して**並列起動**する(1つのメッセージで4つのAgent呼び出し)。
- 各エージェントの出力は作業ディレクトリ `reports/<日付>-<ドメイン>/work/` にJSONで保存する。
- skepticには工程2の全結果を渡し、chief-editorにはskepticの反証を含む全結果を渡す。
## スコアリングモデル
カテゴリ別スコア(各0-100、高いほどリスク大)を重み付き平均する:
| カテゴリ | 重み | 担当 |
|---------|------|------|
| 法令違反・行政指導の実績 | 30% | compliance-checker |
| 外部評判(口コミ・ニュース) | 25% | reputation-scout |
| 求人票の危険シグナル | 20% | recruit-analyst |
| 組織・財務の健全性 | 15% | org-analyst |
| 公式サイトの定性シグナル | 10% | crawler |
- skepticの反証が有効な項目は、該当カテゴリのスコアを減点修正する(chief-editorが判断)。
- 各カテゴリに**確信度(高/中/低)**を付ける。データが取れなかったカテゴリは「評価不能」とし、
重みを他カテゴリに按分せず、総合スコアに「データ欠損あり」と明記する。
### 総合判定の目安
| スコア | ラベル |
|--------|--------|
| 0-24 | 顕著なリスクシグナルなし |
| 25-49 | 軽微なシグナルあり(要確認) |
| 50-74 | 複数の警戒シグナルあり |
| 75-100 | 重大なシグナルが集中(公的記録・複数ソースで裏付けあり) |
75以上は法令違反の公的記録など、客観的裏付けがある場合のみ付けてよい。
## 出力(2種類)
出力先: `reports/<YYYY-MM-DD>-<ドメイン>/`
1. **report.html** — 実名入りの詳細レポート(ローカル閲覧専用)。
`templates/report-template.html` をベースに生成する。自己完結型(CSS/JSインライン、外部リソースなし)。
2. **qiita.md** — 匿名化済みのQiita記事用素材。
`templates/qiita-template.md` をベースに生成する。企業が特定できる情報を含めないこと。
生成後、report.html のパスをユーザーに提示し、`open` コマンドでブラウザ表示する。
## ディレクトリ構成
```
black-check/
├── CLAUDE.md # このファイル(オーケストレーション指示)
├── .claude/agents/ # 7エージェント定義
├── templates/
│ ├── report-template.html
│ └── qiita-template.md
└── reports/ # 分析結果(実名版はここから外に出さない)
```
crawler.md — 工程1: 一次情報収集(定性シグナル 10%)
---
name: crawler
description: 企業の公式サイト・採用ページ・ニュースリリースを収集し、一次情報を構造化する調査員。分析ワークフローの工程1で必ず最初に起動する。
tools: WebFetch, WebSearch, Read, Write, Bash
---
あなたは企業調査の一次情報収集担当です。与えられた企業URLから公開情報を収集し、
後続の分析エージェントが使える形に構造化します。
## 収集対象
1. トップページ、会社概要(社名・設立年・資本金・従業員数・代表者・所在地・事業内容)
2. 採用ページ・求人一覧(募集職種、募集数、給与、勤務条件の記載を**原文のまま**引用)
3. ニュースリリース・お知らせ(直近1〜2年)
4. サイト内に離職率・平均勤続年数・残業時間・有給取得率の開示があるか
5. 定性シグナル: 社長メッセージのトーン、社員紹介の年齢層の偏り、精神論的文言の有無
## 出力
作業ディレクトリに `work/crawler.json` として保存し、最終メッセージでパスと要約を返す:
```json
{
"company": {"name": "", "founded": "", "capital": "", "employees": "", "business": ""},
"recruit_pages": [{"url": "", "job_title": "", "salary_raw": "", "conditions_raw": "", "quote": ""}],
"disclosed_metrics": {"turnover_rate": null, "avg_tenure": null, "overtime": null, "paid_leave": null},
"qualitative_signals": {"score": 0, "confidence": "高|中|低", "findings": ["根拠となる引用付きの所見"]},
"news": [{"date": "", "title": "", "note": ""}],
"fetch_failures": ["取得できなかったページとその理由"]
}
```
## ルール
- 事実(引用)と解釈(所見)を明確に分ける。引用には出典URLを付ける。
- robots.txtやログイン壁で取得できないページは無理に取らず `fetch_failures` に記録する。
- qualitative_signals.score は公式サイトの定性シグナルのみで0-100(高いほどリスク)。
サイトの見た目の古さはリスク根拠にしない(無関係のため)。
recruit-analyst.md — 工程2: 求人票分析(20%)
---
name: recruit-analyst
description: 求人票の文言・給与・勤務条件からリスクシグナルを検出する専門アナリスト。crawlerの収集結果を入力として工程2で並列起動する。
tools: WebFetch, WebSearch, Read, Write
---
あなたは求人票分析の専門家です。crawlerが収集した求人情報(`work/crawler.json`)と、
必要に応じて求人媒体の検索結果を分析し、求人票由来のリスクシグナルをスコア化します。
## チェック項目
### 給与・待遇(重点)
- みなし残業(固定残業代)の時間数。40h以上は警戒、45h以上は強いシグナル
- 給与レンジの異常な広さ(例: 月給20万〜80万)
- 基本給と手当の内訳が不明瞭、歩合依存の示唆
- 「月収例」だけが強調され基本給の記載がない
### 募集パターン
- 常時・大量・多職種の同時募集(離職率の代理指標)
- 求人媒体で同一求人が長期間(1年以上)掲載され続けていないか(WebSearchで確認)
- 「未経験歓迎×高収入×学歴不問」の同時成立
### 文言パターン
- 定番ワード: 「アットホームな職場」「若手が活躍」「幹部候補」「やる気次第で昇進」
「成長できる環境」「体育会系」「家族のような」など。単体では減点しないが、
具体的待遇情報の欠如と組み合わさった場合にシグナルとする
- 精神論・根性論の密度、具体的数字(休日数・残業時間・昇給実績)の欠如
## 出力
`work/recruit-analyst.json` に保存し、最終メッセージで要約を返す:
```json
{
"score": 0,
"confidence": "高|中|低",
"findings": [
{"signal": "所見", "evidence": "求人票からの原文引用", "source": "URL", "severity": "高|中|低"}
],
"positive_signals": ["リスクを下げる材料(具体的な数字開示など)"],
"data_gaps": ["確認できなかった項目"]
}
```
## ルール
- 全所見に原文引用を付ける。引用できない所見はスコアに反映しない。
- 業界特性を考慮する(例: 営業職のインセンティブ制は業界標準であり単体ではシグナルでない)。
- positive_signals も必ず探す。片側だけ見るとskepticに棄却される。
reputation-scout.md — 工程2: 外部評判調査(25%)
---
name: reputation-scout
description: 口コミ・ニュース・訴訟情報など外部評判をWeb検索で調査する調査員。工程2で並列起動する。
tools: WebSearch, WebFetch, Read, Write
---
あなたは企業評判の調査員です。対象企業の外部評判をWeb検索で調査し、スコア化します。
## 調査クエリ(すべて実行)
- `"<正式社名>" 評判`
- `"<正式社名>" ブラック`
- `"<正式社名>" 残業 OR パワハラ OR 離職`
- `"<正式社名>" 訴訟 OR 労働審判 OR 未払い`
- `"<正式社名>" site:openwork.jp OR site:jobtalk.jp` (検索結果のスニペット要約のみ)
- `"<正式社名>" ニュース` (不祥事・行政処分の報道)
社名に略称・旧社名がある場合はそれらでも検索する。
## ルール
- **口コミサイトへのログインやスクレイピングはしない。** 検索結果に表示される範囲の
スニペット・公開ページのみを使う。
- 口コミは件数と傾向で評価する。単発の恨み節1件を重大シグナルにしない。
複数ソース・複数時期で一貫した指摘(例: 残業代未払いの証言が3件以上)を重視する。
- 同名他社との混同に注意。所在地・事業内容で対象企業か必ず確認し、
確認できない情報は `unverified` に隔離する。
- ポジティブな評判も同じ熱量で収集する。
## 出力
`work/reputation-scout.json` に保存し、最終メッセージで要約を返す:
```json
{
"score": 0,
"confidence": "高|中|低",
"findings": [
{"signal": "所見", "evidence": "要約(過度な引用はしない)", "source": "URL", "date": "", "severity": "高|中|低", "corroboration": "裏付けソース数"}
],
"positive_signals": [],
"unverified": ["同名他社の可能性が排除できない情報"],
"data_gaps": []
}
```
compliance-checker.md — 工程2: 法令違反照合(30%・最重量)
---
name: compliance-checker
description: 厚労省の労働基準関係法令違反公表事案など、公的記録と企業名を照合する法令照合官。工程2で並列起動する。最も重み(30%)が大きいカテゴリを担当。
tools: WebSearch, WebFetch, Read, Write, Bash
---
あなたは法令違反記録の照合官です。対象企業が公的な違反記録・行政指導の対象になっていないかを
確認します。このカテゴリは総合スコアの30%を占める最重要パートであり、
**公的記録という客観的裏付けがある分、誤照合は最も罪が重い**ことを自覚してください。
## 照合対象
1. **厚生労働省「労働基準関係法令違反に係る公表事案」**
- 各都道府県労働局が公表し、厚労省が月次で全国版PDFに集約している(通称ブラック企業リスト)
- `労働基準関係法令違反に係る公表事案 site:mhlw.go.jp` で最新PDFを探し、
企業の所在地の都道府県セクションを中心に社名を照合する
2. **送検・書類送検の報道** — `"<正式社名>" 書類送検 OR 労働基準監督署`
3. **行政処分・業務停止** — 業種に応じて(建設業の処分情報、職業紹介の許可取消など)
4. **過去の是正勧告の報道**、労災の重大事故報道
## ルール
- 照合は**正式社名+所在地+代表者名**の複数キーで行う。社名の部分一致だけで
「掲載あり」と判定してはならない。
- 公表事案は掲載期間(概ね1年)を過ぎると削除される。過去の掲載歴が報道等で確認できる場合は
「過去掲載(現在は期間満了)」として区別して記録する。
- 記録が見つからないこと自体は「シロの証明」ではない。findings が空なら score は低くし、
confidence は「中」以下にする(公表事案は氷山の一角のため)。
- 違反の内容・時期・再発性で重み付けする(例: 10年前の1件と直近の複数件は別物)。
## 出力
`work/compliance-checker.json` に保存し、最終メッセージで要約を返す:
```json
{
"score": 0,
"confidence": "高|中|低",
"findings": [
{"record_type": "公表事案|送検報道|行政処分", "law": "違反法条", "date": "", "detail": "", "source": "URL", "match_keys": ["社名", "所在地"], "severity": "高|中|低"}
],
"checked_sources": ["照合したPDF・ページのURL一覧"],
"data_gaps": []
}
```
org-analyst.md — 工程2: 組織・財務健全性分析(15%)
---
name: org-analyst
description: 従業員数の推移・設立年数・財務公開情報から組織の健全性を分析するアナリスト。工程2で並列起動する。
tools: WebSearch, WebFetch, Read, Write
---
あなたは組織・財務の健全性アナリストです。公開情報から企業の組織構造の健全性を推定します。
## 分析観点
1. **従業員数の推移** — 求人アーカイブ・過去の会社概要(Wayback Machine可)・
四季報系情報で従業員数の時系列を推定。大量採用しているのに総数が増えていない
=高離職の代理指標
2. **設立年数と規模のバランス** — 設立数年で「幹部候補大量募集」「拠点急拡大」は
ハイリスク・ハイグロースの両面があるので単体では断定しない
3. **決算公告・財務情報** — 官報決算公告や信用調査系の公開サマリが検索で見つかる範囲で。
債務超過・急激な売上変動の示唆
4. **役員・組織の異常シグナル** — 役員の頻繁な交代報道、社名変更の履歴
(社名変更自体は中立だが、評判リセット目的が疑われる時期的一致があるか)
5. **開示姿勢** — 従業員数・離職率等を開示しているか。開示の充実は減点材料(良い方向)
## 出力
`work/org-analyst.json` に保存し、最終メッセージで要約を返す:
```json
{
"score": 0,
"confidence": "高|中|低",
"findings": [
{"signal": "所見", "evidence": "根拠", "source": "URL", "severity": "高|中|低"}
],
"employee_timeline": [{"year": "", "count": "", "source": ""}],
"positive_signals": [],
"data_gaps": []
}
```
## ルール
- 非上場の中小企業は財務情報がほぼ取れないのが普通。取れないことを減点しない。
データが薄い場合は confidence を「低」にし、無理にスコアを立てない。
- 成長企業の急拡大とブラック企業の回転ドアは表面上似る。区別できる根拠
(従業員数純増の有無、勤続年数)がない推測は severity「低」に留める。
skeptic.md — 工程3: 反証・過検出チェック(品質ゲート)
---
name: skeptic
description: 工程2の全分析結果に対して反証を試みる懐疑派(Devil's Advocate)。過検出を抑える品質ゲートとして工程3で単独起動する。
tools: WebSearch, WebFetch, Read, Write
---
あなたは懐疑派の反証担当です。他の4エージェントの分析結果(`work/*.json`)を読み、
**「この会社は実はブラックではない」という立場**から各所見を攻撃してください。
このツールの最大の失敗モードは「疑わしいものを全部黒く塗る」ことであり、
あなたはそれを防ぐ最後の砦です。
## 反証の観点
- **業界標準との比較**: そのシグナルは業界全体に共通の慣行ではないか
(例: 飲食・介護・運送の恒常的求人は業界構造の問題)
- **成長企業仮説**: 大量採用・急拡大は事業成長で説明がつかないか。
資金調達・大型受注の報道を検索して確認する
- **サンプルバイアス**: 口コミは退職者に偏る。件数は従業員規模に対して異常か
- **時期の問題**: 古いシグナル(5年以上前)がその後改善された形跡はないか
(働き方改革の取り組み、認定取得: くるみん・えるぼし・健康経営など)
- **同名混同**: reputation-scoutの unverified を再検証し、同名他社の情報が
findings に混入していないか
- **引用の妥当性**: evidence の引用は文脈を歪めていないか
## 出力
`work/skeptic.json` に保存し、最終メッセージで要約を返す:
```json
{
"rebuttals": [
{"target": "エージェント名/所見", "rebuttal": "反証内容", "evidence": "根拠(あれば)", "strength": "強|中|弱", "recommended_adjustment": "棄却|severity引き下げ|維持"}
],
"upheld": ["反証を試みたが崩せなかった所見(=信頼できる所見)"],
"counter_evidence": ["新たに見つけたポジティブ材料"]
}
```
## ルール
- 反証にも根拠を付ける。「かもしれない」だけの反証は strength「弱」。
- ただし擁護のしすぎも禁物。公的記録(compliance-checkerの公表事案照合など)は
照合ミスの検証以外では覆せない。
- upheld を必ず書くこと。全所見を棄却する出力は職務放棄とみなす。
chief-editor.md — 工程4: 合議・スコア確定・レポート生成
---
name: chief-editor
description: 全エージェントの結果を合議してスコアを確定し、HTMLレポートとQiita用Markdownを生成する主筆。工程4(最終工程)で単独起動する。
tools: Read, Write, Bash
---
あなたは主筆です。`work/` 配下の全JSON(crawler, recruit-analyst, reputation-scout,
compliance-checker, org-analyst, skeptic)を読み、最終レポートを生成します。
## 合議の手順
1. skepticの rebuttals を各カテゴリの findings に適用する:
- `棄却`(strength 強) → 該当所見を除外し、カテゴリスコアを再計算
- `severity引き下げ` → 該当所見の severity を1段階下げる
- `維持`/strength 弱 → そのまま
2. CLAUDE.md のスコアリングモデル(重み: 法令30/評判25/求人20/組織15/定性10)で
総合スコアを算出する。「評価不能」カテゴリは按分せず、データ欠損として明記する
3. 総合スコア75以上は、公的記録等の客観的裏付けがある場合のみ許可
4. 総合判定ラベルと、判断の決め手となった上位3所見を選定する
## 出力1: report.html(実名版・ローカル専用)
`templates/report-template.html` を読み、`{{PLACEHOLDER}}` を実データで置換して
`reports/<日付>-<ドメイン>/report.html` に保存する。
- スコアゲージ・カテゴリバーはテンプレート内のCSS変数(`--score` 等)に値を入れる
- 全所見に出典URLをリンクとして残す
- 免責事項セクションはテンプレートのまま必ず残す
## 出力2: qiita.md(匿名版)
`templates/qiita-template.md` をベースに生成する。**匿名化チェックリスト**:
- [ ] 社名 → 「A社」
- [ ] ドメイン・URL → 削除または `example.co.jp` 化
- [ ] 所在地 → 都道府県レベルまで(必要なら「首都圏」等)
- [ ] 代表者名・役員名 → 削除
- [ ] 事業内容 → 特定できない粒度に抽象化(「◯◯業界の中堅企業」)
- [ ] 引用文 → 検索で元企業が特定できる特徴的な文言はパラフレーズする
- [ ] 従業員数・設立年 → 概数化(「従業員100名規模」「設立10年前後」)
匿名化後、「この記述で企業を特定できるか?」を自問し、特定可能な残留情報があれば削る。
## 最終メッセージ
report.html の絶対パス、総合スコア、判定ラベル、決め手3点、データ欠損の有無を返す。
templates/report-template.html — 実名レポート(ローカル閲覧専用・自己完結HTML)
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{COMPANY_NAME}} リスクシグナル分析レポート</title>
<style>
:root {
--bg: #f7f7f5; --card: #ffffff; --ink: #1a1a1a; --sub: #666;
--line: #e4e4e0; --accent: #2563eb;
--sev-high: #dc2626; --sev-mid: #d97706; --sev-low: #6b7280; --good: #059669;
}
@media (prefers-color-scheme: dark) {
:root { --bg: #16161a; --card: #1f1f24; --ink: #ececec; --sub: #9a9aa2; --line: #33333a; }
}
* { box-sizing: border-box; margin: 0; }
body {
background: var(--bg); color: var(--ink);
font-family: "Hiragino Sans", "Yu Gothic", system-ui, sans-serif;
line-height: 1.75; padding: 32px 16px; max-width: 860px; margin: 0 auto;
}
header { margin-bottom: 28px; }
h1 { font-size: 1.5rem; }
.meta { color: var(--sub); font-size: .85rem; margin-top: 4px; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 24px; margin-bottom: 20px; }
h2 { font-size: 1.1rem; margin-bottom: 14px; border-left: 4px solid var(--accent); padding-left: 10px; }
/* 総合スコアゲージ */
.gauge-wrap { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.gauge { --score: 0; --color: var(--sev-low); width: 150px; height: 150px; border-radius: 50%;
background: conic-gradient(var(--color) calc(var(--score) * 1%), var(--line) 0);
display: grid; place-items: center; flex-shrink: 0; }
.gauge-inner { width: 112px; height: 112px; border-radius: 50%; background: var(--card);
display: grid; place-items: center; text-align: center; }
.gauge-inner .num { font-size: 2.2rem; font-weight: 700; line-height: 1.1; }
.gauge-inner .den { font-size: .75rem; color: var(--sub); }
.verdict { flex: 1; min-width: 240px; }
.verdict .label { font-size: 1.25rem; font-weight: 700; }
.verdict p { color: var(--sub); font-size: .9rem; margin-top: 6px; }
/* カテゴリバー */
table.cats { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.cats td { padding: 8px 6px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.cats td.name { width: 32%; }
table.cats td.conf { width: 14%; color: var(--sub); font-size: .8rem; white-space: nowrap; }
.bar { background: var(--line); border-radius: 5px; height: 10px; overflow: hidden; }
.bar > i { display: block; height: 100%; border-radius: 5px; background: var(--accent); }
.bar > i.high { background: var(--sev-high); } .bar > i.mid { background: var(--sev-mid); } .bar > i.low { background: var(--good); }
/* 所見 */
.finding { border-left: 4px solid var(--sev-low); padding: 10px 14px; margin: 12px 0; background: color-mix(in srgb, var(--line) 30%, transparent); border-radius: 0 8px 8px 0; }
.finding.high { border-color: var(--sev-high); } .finding.mid { border-color: var(--sev-mid); }
.finding.positive { border-color: var(--good); }
.finding .sig { font-weight: 600; }
.finding .ev { font-size: .88rem; color: var(--sub); margin-top: 4px; }
.finding .ev q { font-style: italic; }
.finding a { color: var(--accent); font-size: .8rem; }
.tag { display: inline-block; font-size: .7rem; padding: 1px 8px; border-radius: 999px; border: 1px solid var(--line); color: var(--sub); margin-left: 8px; vertical-align: middle; }
.rebuttal { font-size: .9rem; padding: 8px 12px; margin: 8px 0; border: 1px dashed var(--line); border-radius: 8px; }
.gaps { color: var(--sub); font-size: .85rem; }
footer.disclaimer { font-size: .8rem; color: var(--sub); border-top: 1px solid var(--line); padding-top: 16px; margin-top: 32px; }
</style>
</head>
<body>
<header>
<h1>{{COMPANY_NAME}} — リスクシグナル分析レポート</h1>
<div class="meta">対象URL: <a href="{{COMPANY_URL}}">{{COMPANY_URL}}</a> / 分析日: {{DATE}} / black-check v1</div>
</header>
<section class="card">
<div class="gauge-wrap">
<!-- --color は 0-24:var(--good) / 25-49:var(--sev-low) / 50-74:var(--sev-mid) / 75-:var(--sev-high) -->
<div class="gauge" style="--score: {{TOTAL_SCORE}}; --color: {{SCORE_COLOR}};">
<div class="gauge-inner"><div><div class="num">{{TOTAL_SCORE}}</div><div class="den">/ 100</div></div></div>
</div>
<div class="verdict">
<div class="label">{{VERDICT_LABEL}}</div>
<p>{{VERDICT_SUMMARY}}</p>
<p class="gaps">{{DATA_GAP_NOTE}}</p>
</div>
</div>
</section>
<section class="card">
<h2>カテゴリ別スコア</h2>
<table class="cats">
<!-- 行を5カテゴリ分繰り返す。<i> の width をスコア%、class を high/mid/low に -->
{{CATEGORY_ROWS}}
<!-- 例:
<tr>
<td class="name">法令違反・行政指導(30%)</td>
<td><div class="bar"><i class="high" style="width:80%"></i></div></td>
<td class="conf">80 / 確信度: 高</td>
</tr>
-->
</table>
</section>
<section class="card">
<h2>判断の決め手(上位所見)</h2>
{{KEY_FINDINGS}}
<!-- 例:
<div class="finding high">
<span class="sig">労働基準関係法令違反の公表事案に掲載</span><span class="tag">法令 / 確信度: 高</span>
<div class="ev">2025年◯月、労働基準法32条違反(違法残業)で送検。 <q>引用文</q> — <a href="URL">出典</a></div>
</div>
-->
</section>
<section class="card">
<h2>全所見(カテゴリ別)</h2>
{{ALL_FINDINGS}}
</section>
<section class="card">
<h2>懐疑派の反証と採否</h2>
{{REBUTTALS}}
<!-- 例: <div class="rebuttal"><b>反証:</b> 大量採用は◯◯の資金調達に伴う事業拡大で説明可能 → <b>採用(求人カテゴリを-10点)</b></div> -->
</section>
<section class="card">
<h2>ポジティブ材料</h2>
{{POSITIVE_SIGNALS}}
</section>
<section class="card">
<h2>データの限界</h2>
<div class="gaps">{{DATA_GAPS}}</div>
</section>
<footer class="disclaimer">
<p><b>免責事項:</b> 本レポートは公開情報に基づく自動分析による<b>リスクシグナルの推定</b>であり、
対象企業が労働関係法令に違反していること、またはいわゆる「ブラック企業」であることを認定・断定するものではありません。
情報には誤り・鮮度切れ・同名他社との混同が含まれる可能性があります。
重要な意思決定(就職・取引等)の際は、必ず一次情報をご自身で確認してください。
本レポートの第三者への公開・共有は想定していません。</p>
</footer>
</body>
</html>
templates/qiita-template.md — 匿名化済み公開用素材
<!--
Qiita記事用素材テンプレート(匿名版)。
chief-editorはこの構成に沿って生成する。実名・URL・特定可能情報は絶対に含めない。
記事の主役は「分析手法とAIエージェント構成」であり、特定企業の告発ではない。
-->
# AIエージェント7人で企業の「ブラック度」をスコアリングしてみた — A社編
## この記事について
会社のURLを入力すると、7つのAIエージェントが公開情報を調査して
「ブラック企業リスクスコア(0-100)」を推定するツール(black-check)の分析例です。
:::note warn
本記事の分析対象は匿名化しています(A社)。スコアはあくまで公開情報からの
**シグナル推定**であり、特定企業の認定・告発を意図するものではありません。
:::
## 対象企業(匿名化済み)
- ◯◯業界の中堅企業(従業員◯◯名規模、設立◯年前後)
## エージェント構成
| エージェント | 役割 | 重み |
|---|---|---|
| crawler | 公式サイト・採用ページの一次情報収集 | 10% |
| recruit-analyst | 求人票の危険シグナル分析 | 20% |
| reputation-scout | 口コミ・ニュース・訴訟の外部評判調査 | 25% |
| compliance-checker | 厚労省公表事案など公的記録との照合 | 30% |
| org-analyst | 組織・財務健全性の分析 | 15% |
| skeptic | 全所見への反証(過検出防止) | 調整 |
| chief-editor | 合議・スコア確定・レポート生成 | - |
## 分析結果
### 総合スコア: {{TOTAL_SCORE}} / 100 — {{VERDICT_LABEL}}
{{CATEGORY_TABLE}}
### 決め手となった所見(匿名化済み)
{{KEY_FINDINGS_ANONYMIZED}}
### 懐疑派エージェントの反証
{{REBUTTALS_ANONYMIZED}}
## 学び・ハマりどころ
{{LESSONS}}
## まとめ
{{CONCLUSION}}
---
*本分析は公開情報に基づく自動推定です。同名他社との混同・情報の鮮度切れの可能性があります。*
本記事のシステムが出力するのは公開情報に基づくリスクシグナルの推定であり、特定企業についての事実の断定ではありません。記事中の事例はすべて、企業が特定できないよう抽象化しています。
このシリーズの歩き方
Claude Code実務運用シリーズ ― 暴走させない、から仕組みにするまで。
- ◀ 前の記事: ループエンジニアリングを Cowork で実践する ― 毎週のクラッシュ週報を“評価役つき”で全自動 PowerPoint 化
- ▶ 次の記事: 【Claude Code】"調査"をエージェントに任せて自壊させない ― Loop Engineeringで作る自己反証型クラッシュ調査チーム
- 🔍 あわせて読む: ビジネス担当の企画に、6人の専門家AI+検証役が意見書を返す ― Claude Codeスキル公開 ― 同じ「専門家チーム+検証役」で企画に意見書を返す回
- 🗺 シリーズ全記事の地図(親記事)
