Claude Codeエージェント実践 Day 26|SQL 7本パイプラインを端から端まで通す — モックから本番コードへ
TL;DR
-
dashboard_generator.pyが v2 で止まっていたことに気づき、v3/v4 の SQL 3本 + HTML セクションを一括マージした - BigQuery → Python → HTML → Chrome の全工程を通し実行し、v4 ダッシュボードが実データで表示されることを確認した
- AIが速く作れる快感で設計上の役割分担を忘れていた。本来は分析エージェント経由の設計なのに、人間が直接改良し続けた反省
今日のゴール
Day 22〜25 で段階的に積み上げてきたダッシュボードの設計(SQL 7本・HTMLセクション追加)を、実際に動く dashboard_generator.py に一本化する。BigQuery → Python → HTML 出力 → ブラウザ表示の端から端まで通して、v4 ダッシュボードの完成形をレポートする。
前提条件
- Day 25 の v4 ダッシュボード設計(SQL 7本)が完了していること
- BigQuery に analytics データセット(sales, customers, products, budget)が存在すること(テスト用ダミーデータ)
- Python 3.12 + bq CLI がインストール済みであること
作ったもの
GitHub: akira-cloudjob-public/reporting-agent(Week 4 完了後に公開予定)
v4 ダッシュボード(実データ版)

モックの決め打ち数字が、BigQuery の実データに置き換わった瞬間は気持ちいい。
全体像
Day 22 の v1 は「テーブル3つ × SQL 3本 → セクション4つ」だった。4日間で「テーブル4つ × SQL 7本 → セクション8つ」に成長した。しかしこの全体像が実際にコードとして動くのは、今日が初めてだ。
問題を発見する — v2 止まりのコード
昨日の記事を書き終えて、ふと dashboard_generator.py を開いた。
# v2 の fetch_data() — 4クエリで止まっている
def fetch_data():
summary = run_bq_query("SELECT SUM(amount)...") # SQL 1
by_region = run_bq_query("SELECT region...") # SQL 2
monthly_trend = run_bq_query("SELECT FORMAT_DATE...") # SQL 3
by_category = run_bq_query("SELECT p.category...") # SQL 4
return {
"summary": summary[0],
"by_region": by_region,
"monthly_trend": monthly_trend,
"by_category": by_category,
}
v3 と v4 で追加した機能はすべてモック HTML(dashboard-v3-mock.html、dashboard-v4-mock.html)に直接書いていた。本番コードには SQL 5〜7 も、予算比 KPI もドーナツチャートもトップ顧客もない。
普段のバックエンド開発なら、まず設計書を書いて TDD で進めるからこんなことは起きない。しかし今回はエージェントに「こういうセクションを追加して」と依頼して、出てきたモック HTML をブラウザで確認する——というサイクルを繰り返していた。動くものが速く出てくるので満足してしまい、本番コードへの統合を後回しにした結果、4日分の乖離がたまっていた。
v2 → v4 の差分を整理する
マージ前に何を追加するか整理した。
| 追加内容 | 変更箇所 | 由来 |
|---|---|---|
| SQL 1 改修: products JOIN で粗利を追加 | fetch_data() |
v3 |
| SQL 2 改修: 地域別に原価・粗利を追加 | fetch_data() |
v3 |
| SQL 3 改修: 月次推移に粗利を追加 | fetch_data() |
v3 |
| SQL 4 改修: カテゴリ別に粗利を追加 | fetch_data() |
v3 |
| SQL 5 新規: 予算合計 | fetch_data() |
v3 |
| SQL 6 新規: トップ顧客ランキング | fetch_data() |
v4 |
| SQL 7 新規: 離反顧客検出 | fetch_data() |
v4 |
| KPI カード刷新(予算比・粗利) | generate_html() |
v3 |
| 月次推移 2本折れ線 | <script> |
v3 |
| ドーナツチャート新規 | <script> |
v3 |
| 地域別テーブルに粗利列 | generate_html() |
v3 |
| 顧客ランキングテーブル + CSS | generate_html() |
v4 |
| 離反ワーニングカード + CSS | generate_html() |
v4 |
リストにすると 13項目。多く見えるが、各パーツはモックで動作確認済み。未知の実装はない。
マージ作業 — fetch_data() の統合
作業で一番大きかったのは fetch_data() の更新だ。v2 が返していたデータと v4 が返すデータを並べると、差が明確になる。
# v2 の return
return {
"generated_at": str(date.today()),
"period": "先月",
"summary": summary[0],
"by_region": by_region,
"monthly_trend": monthly_trend,
"by_category": by_category,
}
# v4 の return
return {
"generated_at": str(date.today()),
"period": "先月",
"summary": summary[0],
"budget": budget[0], # v3 追加
"by_region": by_region,
"monthly_trend": monthly_trend,
"by_category": by_category,
"top_customers": top_customers, # v4 追加
"churn": churn, # v4 追加
}
3つのキーが増えただけに見えるが、裏では SQL のクエリが3本増え、既存4本も products テーブルとの JOIN を追加して粗利を取れるように改修している。
7本のクエリを順に実行すると時間がかかるので、進捗表示を追加した。
def fetch_data():
print(" [1/7] KPI summary...", end=" ", flush=True)
summary = run_bq_query(SQL_SUMMARY)
print("done")
print(" [2/7] Budget total...", end=" ", flush=True)
budget = run_bq_query(SQL_BUDGET)
print("done")
# ... 以下同様
4本のときは「まとめて待つ」で問題なかったが、7本になると「今どこ?」が気になる。小さな改善だが、デバッグのときに「SQL 7 の離反クエリで止まっている」とすぐ分かるのは助かる。
通しで動かす — 実行ログ
いよいよ、パイプラインを端から端まで動かす。
$ cd outputs/REQ-2026-002/reporting-agent
$ export PYTHONUTF8=1
$ python src/dashboard_generator.py
Fetching data from BigQuery...
[1/7] KPI summary... done
[2/7] Budget total... done
[3/7] Monthly trend... done
[4/7] By category... done
[5/7] By region... done
[6/7] Top customers... done
[7/7] Churn detection... done
Generating HTML dashboard v4...
Generated: src/output/dashboard_2026-02-26.html
File size: 24,382 bytes
Self-check passed.
ファイルサイズが v2 の 7,460 bytes から 24,382 bytes に増えた。 3.3倍。これが4日間で積み上げたものの物理的な量だ。CSS、Canvas コード、HTML セクション——すべてが1つのファイルに凝縮されている。
ブラウザで開くと、モックで見慣れたレイアウトが実データで埋まっている。KPI カードの予算達成率、折れ線グラフの売上と粗利の乖離、ドーナツチャートの構成比、顧客ランキング、離反ワーニング——全セクションが揃った。
ハマったところ
モック HTML の変数名と bq の辞書キーのズレ
モック HTML では prev_amount と手書きしていたが、Python の run_bq_query() が返す辞書キーは BigQuery の列名エイリアスそのまま。離反クエリの SQL で prev.total_amount AS prev_amount と AS をつけ忘れると、キーが total_amount になって他のクエリの戻り値と衝突する。
# モックでは手書きだったので気づかなかった
amount = ch["prev_amount"] # SQL の AS エイリアスが正しければ OK
# AS をつけ忘れると → KeyError: 'prev_amount'
モックは「見た目の確認」が目的なので、データ構造の正確さは後回しになる。合流時にこのズレを検出できたのは、通しテストの価値そのものだ。
CSS クラス名の競合
v2 の .bar-fill はカテゴリ別売上の横棒グラフで青系(#4a90d9)に設定していた。v4 で追加したインラインバーも棒の見た目だが、こちらは半透明(rgba(74, 144, 217, 0.15))にしたい。
最初は同じ .bar-fill を使おうとして色が変わってしまった。v4 のインラインバーは .inline-bar として別クラスに分離することで解決。単一 HTML の中で CSS がグローバルスコープなので、命名の衝突は常に気をつける必要がある。
v1 → v4 の進化を振り返る
4日間の累積変化を並べてみる。
| 指標 | v1(Day 22) | v2(Day 23) | v3(Day 24) | v4(Day 25→26) |
|---|---|---|---|---|
| SQL 本数 | 3本 | 4本 | 5本 | 7本 |
| HTML サイズ | 7.4KB | 9.1KB | 14KB | 24KB |
| グラフ種類 | CSS棒 | CSS棒+折れ線 | +ドーナツ | 同左 |
| 表示対象 | 金額 | 金額 | 金額+利益 | 金額+利益+人 |
| KPI カード | 売上・数量・顧客・注文 | 同左 | 売上比・粗利・粗利率・顧客 | 同左 |
「表示対象」の行が一番重要だと思っている。 v1 は「いくら売れたか」だけだった。v3 で「利益はいくらか」が加わり、v4 で「誰が買い、誰が離れたか」まで見えるようになった。SQL の本数やファイルサイズは結果にすぎない。ダッシュボードが答えられる「問い」が深くなったことが、4日間の本当の成果だ。
学んだこと
「作ること」に没頭すると設計を忘れる
本来のアーキテクチャを振り返る。レポーティングエージェントへの要求は、データ分析エージェントのアウトプットから自動的に流れてくる設計だった。人間が「ドーナツチャートを追加して」「顧客ランキングも入れて」と直接指示するものではない。
ところが Day 23 あたりから、自分がレポーティングエージェントに直接「この機能を足して」と依頼するようになっていた。AI が速く作ってくれるから楽しくなり、「もう少し足そう」「ここも改善しよう」とエスカレートした。気づけば4日間、設計上の役割分担を完全に無視して人間が直接ダッシュボードを改良し続けていた。
普段のバックエンド開発なら設計書と TDD がブレーキになる。しかし AI との開発では「動くものが数分で出てくる」快感がブレーキを外してしまう。本来の目的を忘れて作ることに没頭するリスクは、AI開発ならではの落とし穴だと思う。
通しテストでしか見つからないバグがある
モックでは見つからず、通しテストで初めて発覚する問題がある。SQL のエイリアスと Python の辞書キーのズレ、CSS クラス名の競合——どちらも「実データが流れる一連のパイプライン」でしか再現しない。
モックの世界では、データは手書きの JSON や HTML のハードコードだ。そこでは「型」も「キー名」も自分で決められる。しかし BigQuery から返ってくるデータは SQL が決める。モックは「見た目」を確認するもの。通しテストは「データの流れ」を確認するもの。 両方やって初めて完成と言える。
まとめ
- v2 止まりのコードに v3/v4 を合流させ、SQL 7本の完全なパイプラインが動いた。 ファイルサイズ 7.4KB → 24KB は4日間の積み上げの証拠
- AIが速く作れるからこそ、設計上の役割分担を忘れやすい。 本来は分析エージェント経由で要求が流れる設計だったのに、人間が直接改良し続けてしまった
- ダッシュボードの本当の進化は SQL 本数ではなく「問いの深さ」。 金額 → 利益 → 人へと視点が広がったことが4日間の成果
次回 Day 27 では、4日間で育てたレポーティングエージェントの全体像を振り返り、「道具を作るエージェント」の設計パターンを整理する。
検証環境
| 項目 | バージョン |
|---|---|
| OS | Windows 11 Pro |
| Shell | Git Bash |
| Python | 3.12 |
| Claude Code | 1.0.x |
| BigQuery | Standard SQL |
| ブラウザ | Chrome |
シリーズを追いかける
→ 著者ページ(Zenn)
→ GitHub
コメント・質問歓迎です。「モックと本番コードの乖離をどう管理している?」「通しテストのチェックリストが見たい」など、パイプライン開発のアイデアがあればぜひ教えてください。
Discussion