投稿する

ホームページ制作に使える補助金情報収集

全国の自治体や国が提供する「ホームページ制作に使える補助金」を、24時間自律して収集・解析・情報発信するためのAIエージェントシステムです。情報が散在し、更新頻度も高い補助金情報の追跡コストを、AIによる自動化で極限まで下げることを目的としています。 7つのエージェントが連携し、ウェブ上からの新規補助金の発見、スクレイピング、構造化データの抽出、情報の整合性チェック、さらには地域別ランディングページの自動生成までを一気通貫で行います。 特に強力なのは「自己修復機能(Healer)」です。リンク切れを検知するとAIが自ら代替URLを再捜査して更新し、情報の鮮度を人間不在で維持し続けます。自治体情報のウォッチングを自動化したい、または最新データを活用したメディア運営を効率化したい用途に最適です。
zip未取得

Grant Radar

ホームページ制作に使える補助金情報を、AI が 24 時間自律で収集・解析・LP 化する自己進化型システム。

![Daily Grant Check](https://github.com/Ippei4114/grant-radar/actions/workflows/daily_check.yml)

![Daily Discovery](https://github.com/Ippei4114/grant-radar/actions/workflows/daily_discover.yml)

なぜ作るか

中小企業・個人事業主のための「ホームページ制作に使える補助金」は全国で数百種類存在しますが:

  • 自治体ごとに散在し、検索が困難
  • 制度が頻繁に更新され、追跡コストが高い
  • 民間アグリゲータは情報が古い・不正確なケースが多い

このシステムは 7 つの AI エージェントが連携し、収集 → 構造化 → 品質監査 → 自己修復まで自動で回します。最終ゴールは地域別 LP を量産して月 100 万円 MRR の事業化。

詳細な設計方針は CLAUDE.md を参照。

現在の状況(Phase 0 完了)

項目状態
登録補助金15 件(毎日 daily_discover で増加中)
カバー地域6 都府県(東京・新潟・愛知・静岡・石川・長野)
稼働エージェント7 種(自己進化ループ完成、L1+L2+L3 自動化済)
自律実行毎朝 06:00 JST(daily_check)+ 07:00 JST(daily_discover)
月間運用コスト$4〜$6(収集 + 監査 + 発見 + 自己修復、Tier 1)
完全自動度約 80%(残: L4 publisher / Q1 evaluator v2 / Q4 hp-no archive / S2 Brave)

カバー中の補助金(一部)

地域制度名上限額補助率
東京都中央区中小企業ホームページ作成費補助金¥300,0001/2
東京都足立区ホームページ作成・更新補助金¥200,0001/2
東京都荒川区ホームページ作成補助金¥200,0001/2
東京都江東区中小企業ホームページ作成費補助金¥100,0001/2
東京都葛飾区ホームページ作成費補助金交付事業¥50,0001/2
東京都練馬区ネリサポ HP 作成費補助事業¥50,0001/2
愛知県商業振興事業費補助金¥900,000—
石川県金沢市外国語版 HP 整備補助¥400,000—
新潟県新潟市新規採用活動支援事業補助金¥200,000—
全 15 件のリアルタイム状況は Streamlit ダッシュボードで確認可能(後述)。

7 エージェントの自己進化ループ

   06:00 JST 毎日 → collector → analyzer → grants ──┬→ evaluator
                                            ↑      │      │
                                            │      ↓      ↓
                                            │ diff_detector  reject なら hash 削除
                                            │      │      │
                                            │      ↓      └─ 翌朝再抽出
                                            │ Discord 通知
                                            │
                                            └─ http_error 検知 → healer 自動起動
                                                                  ↓
                                                          sources.yaml を自動更新

   07:00 JST 毎日 → discoverer ─→ 曜日別スコープを少量探索 → sources.yaml に自動追加

   人間トリガ → writer ─→ 地域別 LP の HTML を生成
#エージェント役割発火モデル
1collector/scraperHTTP 取得 + 本文抽出。robots.txt 尊重、1 秒/ドメイン rate limit、Accept-Language ja毎朝—
2analyzer/extractor構造化抽出(金額・補助率・期間・HP 制作対象判定)。プロンプト v1→v2→v3 で精度改善毎朝(hash 不一致時)Sonnet 4.6
3detector/diff_detector前後スナップショット比較 → ChangeReport(new/updated/expired/removed)毎朝純関数
4evaluatorrule + AI 整合性チェック → スコア + issue list + recommendation毎朝Haiku 4.5
5writer/lp_generatorLP 構造化 JSON 生成 + HTML レンダリング(インライン CSS、レスポンシブ)手動Sonnet 4.6
6discovererweb_search + filter + extract で新 URL を自動発見 → sources.yaml 追記毎日 07:00 JST(曜日別スコープ)Haiku 4.5
7healer404 検知 → 同一管轄の代替 URL 探索 → 自動置換daily_check 中(http_error 検知時)Haiku 4.5

Healer の実例

金沢市の補助金 URL(zyoseiseido/foreignhp.html)が突然 404 に。Healer が:

  1. ✅ 404 を 3 回リトライ後検知
  2. ✅ web_search で「金沢市 海外販路開拓支援事業」を検索
  3. ✅ 同じドメインの新 URL(gyomuannai/3/4/6584.html)を発見・検証
  4. ✅ sources.yaml を自動更新、healing_actions に履歴記録

人間の手介入ゼロで URL 移行が完了。

完全自動運用フロー

2 つの cron + 4 つのフィードバックループで、人手介入ゼロで補助金データが日々増殖・改善・修復されます。

24 時間のサイクル

┌────────────────────────────────────────────────────────────────┐
│                       1 日のループ                              │
├────────────────────────────────────────────────────────────────┤
│                                                                  │
│  06:00 JST  daily_check.yml ─────────────────────────────────  │
│             │                                                    │
│             ├─ collector が 15 ソースを取得(並列 3)           │
│             ├─ ハッシュ比較 → 変化なしならスキップ              │
│             ├─ 変化分は extractor (Sonnet) で構造化抽出          │
│             ├─ diff_detector で new / updated / expired を分類  │
│             │                                                    │
│             │  ⚙ ループ #1: 自己修復                            │
│             ├─ http_error 検知 → healer を自動起動              │
│             │                  → web_search で代替 URL 探索      │
│             │                  → sources.yaml を自動更新         │
│             │                                                    │
│             ├─ evaluator (Haiku) が全件再評価                   │
│             │                                                    │
│             │  ⚙ ループ #2: 品質フィードバック                  │
│             ├─ reject 判定 → content_hash を削除                │
│             │              → 翌朝 daily_check で再抽出される    │
│             │                                                    │
│             ├─ Discord に通知(INFO/NOTICE/WARNING/ERROR)      │
│             └─ SQLite を [skip ci] で main に auto-commit       │
│                                                                  │
│  07:00 JST  daily_discover.yml ──────────────────────────────  │
│             │                                                    │
│             │  ⚙ ループ #3: 範囲拡張                            │
│             ├─ 曜日別スコープを選択                              │
│             ├─ discoverer (Haiku + web_search) が候補 URL を発見│
│             ├─ filter (Haiku) で HP focused を判定              │
│             ├─ extract (Sonnet) で構造化抽出                    │
│             └─ sources.yaml + grants に自動追記、main に commit │
│                                                                  │
│  ⚙ ループ #4: プロンプト改善 (将来 Phase 1)                    │
│     evaluation_logs の issues を集計 → extractor v4 へ反映      │
│                                                                  │
└────────────────────────────────────────────────────────────────┘

4 つのフィードバックループ詳細

ループ #1: 自己修復(Healer、daily_check 内自動発火)

scraper → 404 / Connection error → 3 回リトライ全失敗
                                    ↓
                                healer.heal_source(source)
                                    ↓
                                Claude + web_search で「同一管轄の代替 URL」を検索
                                    ↓
                                候補を validate (HEAD 200 を確認)
                                    ↓
                                sources.yaml を新 URL に書き換え(notes に履歴)
                                    ↓
                                healing_actions テーブルに行追加
                                    ↓
                                Discord 🔥 NOTICE
                                    ↓
                                **翌朝 daily_check で新 URL を scrape**

実例: 金沢市 URL zyoseiseido/foreignhp.html が 404 → 自動で gyomuannai/3/4/6584.html に書き換え、人手介入ゼロで復旧。

ループ #2: 品質フィードバック(Evaluator → Extractor 再実行)

evaluator.evaluate_grant(extraction, raw_text)
  ↓
score < 0.4 → recommendation = "reject"
  ↓
clear_content_hash(url_hash)
  ↓
**翌朝 daily_check が hash 不一致と判断 → extractor が再抽出**
  ↓
新しい抽出が evaluator に渡される → 品質が高ければ ok、低ければまた reject
  ↓
(無限ループにならないよう、extractor prompt のバージョンアップで根本対処)

ループ #3: 範囲拡張(Discoverer、曜日別スコープ)

07:00 JST 毎日:
  date +%u で曜日番号取得
  → スコープ決定(後述の表)
  → discoverer で 3〜5 件まで自動追加
  → 翌日は別スコープへ

1 週間で全スコープを一巡:

曜日スコープ残り対象(参考)
月tokyo-23ku --remaining23 区中 16 区が未カバー
火chubu-prefectures --remaining9 県中 7 県が未カバー
水kinki-prefectures --remaining7 府県すべて未カバー
木chubu-kinki-ordinance-cities8 政令市
金chubu-kinki-core-cities28 中核市
土tokyo-23ku --remaining(再試行)rate limit でこぼれた分を救済
日chubu-kinki-prefectures --remaining中部+近畿合計

→ 1〜2 ヶ月で東京 + 中部 + 近畿が埋まる想定。

ループ #4: プロンプト改善(Phase 1 構想)

evaluation_logs.issues を週次集計
  ↓
頻出フィールド・指摘パターンを抽出
  ↓
(現状は手動で v3 prompt を v4 に更新、将来は AI が prompt diff を提案)

1 週間のサンプルタイムライン

月 06:00  daily_check    変化なし    → 📊 INFO「15 件確認、変化なし」
月 07:00  daily_discover tokyo-23ku  → 🔥 NOTICE「新宿区 中小企業支援補助金を追加」

火 06:00  daily_check    1 件更新   → 🔥 NOTICE「新宿区 申請締切が更新」
火 07:00  daily_discover chubu-pref → 📊 INFO「3 件評価、追加 0 件」

水 06:00  daily_check    404 検知   → 🔥 NOTICE「Healer 自動起動: 港区 URL を修復」
水 07:00  daily_discover kinki-pref → 🔥 NOTICE「京都府 デジタル化補助金を追加」

木 06:00  daily_check    reject あり → ⚠️ WARNING「Evaluator: 要再抽出 1 件」
木 07:00  daily_discover ord-cities → 🔥 NOTICE「京都市 EC 補助金を追加」

金 06:00  daily_check    前日 reject 分を再抽出 → 📊 INFO「品質改善」
金 07:00  daily_discover core-cities → 📊 INFO「5 件評価、追加 0 件」

土 06:00  daily_check    変化なし    → 📊 INFO
土 07:00  daily_discover tokyo-23ku  → 🔥 NOTICE「文京区 商業活性化補助金を追加」

日 06:00  daily_check    変化なし    → 📊 INFO
日 07:00  daily_discover chubu-kinki → 📊 INFO

Discord 通知サンプル

📊 [INFO] 日次チェック完了
変化なし。15 ソースを確認しました。
🔥 [NOTICE] 補助金データに変化を検知(15 ソース)
🆕 新規 1 件
  • 新宿区中小企業支援補助金
🔄 更新 1 件
  • 中央区中小企業ホームページ作成費補助金 (application_period_end)
新規: 1 / 更新: 1 / 期限切れ: 0 / 削除: 0
🔥 [NOTICE] Healer: 1 件の URL を自動修復
• https://www4.city.kanazawa.lg.jp/.../foreignhp.html →
  https://www4.city.kanazawa.lg.jp/.../6584.html
⚠️ [WARNING] Evaluator: 要レビュー 2 件
• www.city.uonuma.lg.jp (score=0.65)
• minato-sansin.com (score=0.55)
review: 2 / ok: 13

障害時の自動復旧シナリオ

障害自動対応通知人手介入
URL が 404Healer が代替 URL を探索・置換🔥 NOTICE不要(代替が見つかった場合)
URL が 403 / 5xxリトライ 3 回後 http_error として記録、翌朝再試行⚠️ WARNING永続的なら手動調査
Anthropic rate limit22 秒間隔の自動 pacing、超過時は次回リトライ⚠️ WARNING不要(次の minute window で復旧)
抽出失敗(low_confidence)content_hash に書き込まれず、翌朝再試行含まれず永続的なら prompt 改善
評価で rejectcontent_hash 削除 → 翌朝再抽出⚠️ WARNING持続するなら prompt v4 検討
GitHub Actions タイムアウト25 分でジョブが kill、artifact アップロード🚨 ERROR原因調査
Sonnet API ダウンリトライ 3 回後失敗、daily_check 全体は継続🚨 ERRORAnthropic 復旧待ち

通知レベルの意味

レベル絵文字用途例
INFO📊ルーチン完了、変化なし「15 件確認、変化なし」
NOTICE🔥注目すべきポジティブ変化「新規補助金 1 件追加」「URL 修復成功」
WARNING⚠️部分失敗、要レビュー「2 ソースで HTTP エラー」「評価低スコア 1 件」
ERROR🚨パイプライン全体失敗「全 15 ソース失敗」「タイムアウト」

人手介入が必要なこと(残り 15%)

現在自動化されていない領域:

  1. 新地域スコープの追加: 関東以外の地方を追加する場合、SCOPES 辞書への追記が必要
  2. prompt 改善: evaluator の指摘が累積した時の prompt v4 作成(Phase 1 で半自動化予定)
  3. LP の生成・公開: 現状 python scripts/generate_lp.py を手動で叩く(Phase 1 で自動化予定)
  4. 完全廃止された補助金の論理削除: Healer は代替 URL を探すが、制度自体が消えた場合は手動で sources.yaml から削除推奨
  5. API キーの更新: Anthropic / Discord Webhook のローテーション

それ以外は全て自動:

  • スクレイプ、抽出、評価、変化検知、通知、URL 修復、新ソース発見、SQLite 履歴管理

ディレクトリ構成

grant-radar/
├── .github/workflows/        # daily_check.yml, daily_discover.yml, healthcheck.yml
├── agents/
│   ├── collector/scraper.py  # 1️⃣ HTTP + 本文抽出
│   ├── analyzer/extractor.py # 2️⃣ 構造化抽出(プロンプト v3)
│   ├── detector/diff_detector.py # 3️⃣ 変化検知(純関数)
│   ├── evaluator/evaluator.py    # 4️⃣ 品質監査
│   ├── writer/lp_generator.py    # 5️⃣ LP 生成
│   ├── discoverer/discoverer.py  # 6️⃣ 新 URL 自動発見
│   └── healer/healer.py          # 7️⃣ 死 URL 自動修復
├── lib/
│   ├── claude_client.py    # Anthropic SDK ラッパ + Sonnet rate limiter
│   ├── orchestrator.py     # daily_check のビジネスロジック
│   ├── db.py               # SQLite スキーマ + helpers
│   ├── migrations.py       # schema_migrations 管理
│   ├── notifier.py         # Discord webhook + ファイルフォールバック
│   ├── scraping.py         # RobotsCache + RateLimiter
│   └── sources_yaml.py     # sources.yaml の安全な読み書き
├── prompts/
│   ├── extractor_v1.txt / v2.txt / v3.txt  # 抽出プロンプト世代
│   ├── evaluator_v1.txt
│   ├── discoverer_search_v1.txt / discoverer_filter_v1.txt
│   ├── healer_search_v1.txt
│   └── lp_v1.txt
├── config/sources.yaml     # 情報源リスト(自動 + 手動追加)
├── scripts/
│   ├── daily_check.py      # 日次オーケストレータ CLI
│   ├── run_evaluation.py   # 品質監査 CLI
│   ├── run_healer.py       # URL 自動修復 CLI
│   ├── discover_grants.py  # 新ソース発見 CLI
│   ├── generate_lp.py      # LP 生成 CLI
│   ├── run_batch.py        # 手動バッチ抽出
│   ├── test_daily_check.py # ローカル dry-run
│   ├── run_migrations.py   # マイグレーション適用
│   └── migrations/         # 002〜006 SQL マイグレーション
├── dashboard/app.py        # Streamlit 4 タブダッシュボード
├── data/
│   ├── grant_radar.sqlite  # 唯一の真実(main にコミットされる)
│   ├── raw/                # スクレイプ生テキスト(gitignore)
│   ├── extracted/          # 抽出 JSON 履歴(gitignore)
│   ├── llm_logs/           # LLM 入出力全量(gitignore)
│   └── lp/                 # 生成 LP HTML(gitignore)
└── tests/                  # (Phase 1 で整備予定)

クイックスタート

必要要件

  • Python 3.11 以上(推奨: 3.12)
  • macOS / Linux
  • Anthropic API キー(Tier 1 以上推奨、web_search 機能利用のため)
  • Discord Webhook URL(任意、未設定時は data/notifications.log にフォールバック)

セットアップ

# 1. リポジトリのクローン
git clone https://github.com/Ippei4114/grant-radar.git
cd grant-radar

# 2. 仮想環境の作成と有効化
python3.12 -m venv .venv
source .venv/bin/activate

# 3. 依存関係のインストール
pip install -e ".[dev]"

# 4. 環境変数の設定
cp .env.example .env
# .env に ANTHROPIC_API_KEY と DISCORD_WEBHOOK_URL を設定

# 5. マイグレーション適用
python scripts/run_migrations.py

GitHub Actions で自律実行を有効化

  1. GitHub repo の Settings → Secrets and variables → Actions で登録:
  • ANTHROPIC_API_KEY
  • DISCORD_WEBHOOK_URL
  1. Actions タブ → Health Check → Run workflow で接続確認
  • Discord に ✅ メッセージが届けば OK
  1. 各ワークフローを 1 度ずつ手動実行で動作確認:
  • Daily Grant Check → 全 15 ソースを処理、Discord に結果通知
  • Daily Discovery → 曜日別スコープで新ソース探索
  1. 翌朝から自動実行開始

cron 設定:

  • daily_check.yml: 0 21 * * * UTC(= 06:00 JST 毎日)
  • daily_discover.yml: 0 22 * * * UTC(= 07:00 JST 毎日)

CLI の使い方

日次チェック

python scripts/daily_check.py            # 全 15 ソースを処理
python scripts/daily_check.py --dry-run  # DB 書き込み・通知なし
python scripts/daily_check.py --limit 2  # 先頭 2 件だけ

品質監査

python scripts/run_evaluation.py             # 全 grants を再評価
python scripts/run_evaluation.py --url <URL> # 1 件だけ
python scripts/run_evaluation.py --no-notify # Discord 通知なし

新ソースの自動発見

python scripts/discover_grants.py --scope chubu-kinki-prefectures
python scripts/discover_grants.py --cities 名古屋市 京都市
python scripts/discover_grants.py --scope tokyo-23ku --remaining

利用可能スコープ: tokyo-23ku / chubu-prefectures / kinki-prefectures /

chubu-kinki-prefectures / chubu-kinki-ordinance-cities / chubu-kinki-core-cities

⚠️ Anthropic Tier 1 の場合、web_search ヘビーな処理で rate limit に当たります。
一度に 3〜5 件に絞るか、Tier 2 へのアップグレードを検討。

死んだ URL の自動修復

python scripts/run_healer.py             # 全 URL をプローブ、404 を修復
python scripts/run_healer.py --url <URL> # 特定 URL のみ

LP 生成

python scripts/generate_lp.py --region "東京23区" --slug tokyo-23ku
# → data/lp/tokyo-23ku.html  + tokyo-23ku.json

# ブラウザで開く
open data/lp/tokyo-23ku.html

Streamlit ダッシュボード(4 タブ)

streamlit run dashboard/app.py
# → http://localhost:8501
  • 📊 概要: 件数 metric、地域別棒グラフ、フィルタ可能な一覧、詳細パネル
  • 🔍 評価: evaluation_logs の最新スコア、要レビュー / 要再抽出リスト、個別 issue
  • 🤖 メタエージェント: Discoverer / Healer 実行履歴と判定内訳
  • ⚙️ 実行ログ: daily_check の cron 履歴と変化サマリー

データレイヤ

data/grant_radar.sqlite がシステムの唯一の真実。GitHub Actions が毎朝 main にコミットするので、Git の履歴 = データの進化の証拠。

テーブル役割レコード数
grants補助金構造化データ正本(url_hash キー)15
source_hashesスクレイプ本文ハッシュ(AI 抽出スキップ判定)15
execution_logsdaily_check 実行履歴日次 +1
evaluation_logs評価結果履歴日次 +15
discovery_runs / discovered_urlsDiscoverer 監査手動
healing_actionsHealer 修復履歴手動
schema_migrations適用済みマイグレーション5

LLM 入出力は data/llm_logs/{ts}_{uuid}.json に全件保存(プロンプト改善・コスト追跡用、gitignore)。

コスト試算(実測ベース)

シナリオAPI callコスト
daily_check 全 15 件 hash 一致15 Haiku(evaluator のみ)~$0.03
daily_check 1 件のみ更新1 Sonnet + 15 Haiku~$0.05
daily_check 全 15 件再抽出15 Sonnet + 15 Haiku~$0.35
daily_discover(曜日別、3〜5 件)5×(web_search+Haiku+Sonnet)~$0.10/日
Healer 自動発火(404 検知時)1 Haiku + 1 fetch~$0.01
LP 1 件生成(手動)1 Sonnet(max_tokens=8192)~$0.05
月次運用(典型)daily_check + daily_discover + evaluator$4〜$6

プロンプトのバージョン管理

Promptバージョン主な変更点
extractorv1 → v2 → v3v2: 通常枠優先 / v3: 補助額 vs 経費額の判別ルール、reasoning の創作禁止、期限の混同防止
evaluatorv1rule + AI 二層チェック
discovererv1検索 prompt + filter prompt 2 段階
healerv1同一管轄の代替 URL 探索
lpv1中小企業診断士視点のコピー

各バージョンは prompts/{agent}_v{N}.txt として履歴保持。grants テーブルの prompt_version カラムでどの世代で抽出されたか追跡可能。

ロードマップ(Phase 1 構想)

優先度項目目的
高publisher エージェント (L4)grants 更新 → LP 自動再生成 → GitHub Pages デプロイ
高Evaluator v2 (Q1)extractor v3 ポリシーを理解させ false positive を半減
中extractor v4compound 補助金の HP-tier 専用 amount 抽出
中Brave Search API 統合 (S2)Discoverer の大規模化(Anthropic web_search 制限から解放)
中hp_eligible=no の自動 archive (Q4)LP に誤って混入するのを防止
中テストスイートtests/ 整備(diff_detector の単体テスト等)
低LP の SEO 最適化meta タグ・OGP・サイトマップ

開発

# Lint
ruff check .

# Format
ruff format .

# テスト(Phase 1 で整備予定)
pytest

セキュリティ

  • API キーは .env のみ。コードへのハードコード、ログ出力、他ファイル書き込みは禁止
  • LLM 入出力ログには API キーを含めない設計
  • Discord Webhook URL も同様に環境変数経由のみ
  • スクレイピングは robots.txt を尊重、1 秒/ドメインの rate limit
  • 詳細は CLAUDE.md のセキュリティルールセクション参照

設計の自慢ポイント

  1. 疎結合: 各エージェントは pydantic モデル経由で I/O 交換。1 つコケても他は動く
  2. 冪等性: SQLite への書き込みは UPSERT のみ、再実行で副作用が雪だるま化しない
  3. 段階的自動化: 手動 → 半自動 → 自動 の順で構築、リスクを最小化
  4. 思考の保存: 全 LLM 入出力を data/llm_logs/ に保存、後でプロンプト改善に活用
  5. メタ自己進化: discoverer(範囲拡張)/ evaluator(品質監査)/ healer(自己修復)が外輪で回る
  6. Git をデータ層に: SQLite を main にコミット、変化の歴史が git log で追える

ライセンス

未設定(Phase 1 で検討)

謝辞