毎朝6時、ホワイトボードの前で配車係が頭を抱える——「Aドライバーは今日休み、Bルートは渋滞、C倉庫は出荷が30分遅れる」。ベテランの勘で組み上げてきた配車計画は、属人化の代償として若手が育たず、休めず、ミスると即クレームという三重苦を抱えていた。中堅物流業者B社(ドライバー約80名規模)は、Claude Codeで「WMS連携 → 配車最適化 → Slack通知」の3段階自動化パイプラインを構築し、配車計画作成にかかる工数を55%削減した。本記事では、想定シナリオとサンプル実装を交えて、その全貌を物流現場のリアルから解きほぐす。
導入前の課題:ベテラン配車係の経験頼みで属人化が深刻化
関東圏で食品・日用品の中距離輸送を手がけるB社(年商約45億円、ドライバー約80名、4t車中心)は、毎朝の配車計画作成に2名の配車係が約3時間を費やしていた。倉庫からの出荷指示、ドライバーの労働時間、配送先の指定時間、車両ごとの積載量制限——これらを頭の中で組み合わせ、ホワイトボードと紙の地図で計画を組み上げる。
問題は、この職人芸を担えるのが2名のベテランだけだったことだ。1人が休めば計画が遅延し、2人が同時に体調を崩せば現場が止まる。若手は10年経っても「まだ任せられない」状態で、配車のローカルルール(このドライバーは朝が弱い、この配送先は午後一が空いている、等)は誰のドキュメントにも残っていなかった。
さらに2024年の貨物自動車運送事業法改正および改善基準告示の見直しで、ドライバーの拘束時間・休息期間の管理が厳格化された。手作業の配車計画では遵守チェックが追いつかず、月に1〜2件は事後修正が発生していた。
Claude Codeで構築した「3段階自動化パイプライン」の全体像
B社はClaude Codeを使い、配車計画の作成プロセスを以下3つのモジュールに分解して自動化した。エンジニアではない情報システム担当1名が、Claude Codeに仕様を投げては修正を繰り返し、約8週間で構築している。
- WMS連携モジュール:複数倉庫の出荷データをリアルタイムで吸い上げ、配車対象の荷物リストを生成
- 配車最適化モジュール:距離・時間・積載量・労働時間制約を考慮したルートを生成(TSP風アルゴリズム)
- Slack通知モジュール:計画変更・遅延・改善基準告示違反リスクを関係者に即時通知
初期投資は約180万円、月次運用コストは約5万円(API利用料・サーバー)。外部SaaSの配車最適化ツール(年額300〜600万円)と比較しても、自社固有のローカルルールを織り込める内製の利点が大きい。
# パイプライン全体のエントリポイント(簡略版)
from datetime import datetime
from modules.wms_sync import fetch_outbound_orders
from modules.route_optimizer import optimize_routes
from modules.slack_notifier import notify_dispatch_plan
def run_morning_dispatch(target_date: datetime) -> dict:
"""毎朝5:30にcronで起動。WMS取得→最適化→Slack通知まで一気通貫。"""
orders = fetch_outbound_orders(target_date, warehouses=["yashio", "kashiwa", "atsugi"])
drivers = load_available_drivers(target_date)
plan = optimize_routes(orders=orders, drivers=drivers,
max_driving_hours=9.0, # 改善基準告示の上限
rest_minutes=30)
notify_dispatch_plan(plan, channel="#dispatch-daily")
return {"orders": len(orders), "routes": len(plan.routes),
"violations": plan.compliance_warnings}
WMS(在庫管理システム)からのリアルタイム連携:複数倉庫データの統合
最初の難所はWMSとの連携だった。B社は3拠点の倉庫を持ち、それぞれで異なるWMS(八潮:自社開発、柏:パッケージA社製、厚木:パッケージB社製)が稼働している。出荷予定データのフォーマットはCSV・XML・REST APIとバラバラで、項目名も「出荷日」「shipping_date」「ship_dt」と統一されていなかった。
Claude Codeに各WMSの仕様書を読み込ませ、共通のデータモデル(OutboundOrderクラス)への変換ロジックを自動生成させた。住所の正規化(「東京都港区六本木1-2-3」と「港区六本木1丁目2番3号」の同一視)、時刻表記の統一(「13:00」「午後1時」「13時」)、商品コードのマッピング——これらを1つずつClaude Codeに対話的に詰めていった。
# WMS連携モジュール:3拠点の出荷データを統一フォーマットに正規化
from dataclasses import dataclass
from datetime import datetime
from typing import List
@dataclass
class OutboundOrder:
order_id: str
warehouse: str
destination_address: str
delivery_window: tuple[datetime, datetime] # (希望時刻from, to)
weight_kg: float
volume_m3: float
special_handling: List[str] # 例: ["要冷蔵", "時間厳守"]
def fetch_outbound_orders(target_date, warehouses) -> List[OutboundOrder]:
orders = []
for wh in warehouses:
if wh == "yashio":
raw = _fetch_yashio_csv(target_date) # CSV経由
elif wh == "kashiwa":
raw = _fetch_kashiwa_xml(target_date) # XML SOAP経由
elif wh == "atsugi":
raw = _fetch_atsugi_rest(target_date) # REST API経由
orders.extend(_normalize(raw, warehouse=wh))
return orders
結果として、出荷指示データの取り込みは毎朝5:30に自動実行され、配車係が出社する6:30にはすべての荷物リストが統合済みの状態でダッシュボードに表示される。手作業時代に1時間かかっていた「データ集め」が、ゼロ分になった瞬間だった。
配車AIによるルート最適化(Claude Codeで実装した距離+時間制約付きTSP風アルゴリズム)
配車最適化の中核は、巡回セールスマン問題(TSP: Traveling Salesman Problem)の応用だ。ただし純粋なTSPと異なり、現実の物流では以下の制約が複雑に絡む。
- 配送先ごとの指定時間枠(例:午前中、14:00〜16:00)
- 車両ごとの積載量上限(重量・容積の両方)
- ドライバーの拘束時間上限(改善基準告示:1日13時間以内、最大16時間まで延長可)
- 連続運転時間4時間ごとの休憩30分義務
B社はOR-Tools(Googleの最適化ライブラリ)をベースに、Claude Codeで制約条件を1つずつコード化した。完全な最適解を狙うとNP困難で計算時間が爆発するため、「15分以内に実用解が出る」ことを目標に、貪欲法+局所探索のヒューリスティクスを実装している。
# 配車最適化モジュール:制約付きTSP風アルゴリズム(簡略版)
from ortools.constraint_solver import pywrapcp, routing_enums_pb2
def optimize_routes(orders, drivers, max_driving_hours=9.0, rest_minutes=30):
"""OR-ToolsのVRPTW(時間窓付き車両配送問題)として定式化。"""
manager = pywrapcp.RoutingIndexManager(
len(orders) + 1, # +1 は出発地(倉庫)
len(drivers),
0 # 全車両が同じ倉庫から出発
)
routing = pywrapcp.RoutingModel(manager)
# 距離コールバック(Google Maps Distance Matrixで事前計算したテーブルを引く)
def distance_callback(from_idx, to_idx):
from_node = manager.IndexToNode(from_idx)
to_node = manager.IndexToNode(to_idx)
return DISTANCE_MATRIX[from_node][to_node]
transit_idx = routing.RegisterTransitCallback(distance_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_idx)
# 時間窓制約(配送先ごとの指定時間)
time_idx = routing.RegisterTransitCallback(time_callback)
routing.AddDimension(time_idx, 30, int(max_driving_hours * 60),
False, "Time")
time_dim = routing.GetDimensionOrDie("Time")
for i, order in enumerate(orders):
idx = manager.NodeToIndex(i + 1)
window_start = order.delivery_window[0].hour * 60
window_end = order.delivery_window[1].hour * 60
time_dim.CumulVar(idx).SetRange(window_start, window_end)
# 解探索(15分タイムアウト)
params = pywrapcp.DefaultRoutingSearchParameters()
params.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
params.time_limit.seconds = 900
solution = routing.SolveWithParameters(params)
return _extract_plan(routing, manager, solution, drivers)
導入後、配車計画の作成時間は2名×3時間(計6人時)から1名×40分(0.67人時)に短縮。さらに人間では気づきにくい「Aドライバーの帰路にC配送先を寄せると総走行距離が18km減る」といった改善提案が日常的に出るようになった。
ルート工数55%削減を実現した実数値と効果
2025年9月〜11月の3か月間の実測データから、改革の効果を確認できる。配車計画作成にかかる人時ベースでの工数は55%削減。これは「配車係2名×3時間/日 = 6人時」が「1名×40分 = 0.67人時 + AIレビュー20分 = 1.0人時相当」になった結果だ(厳密には83%削減だが、月次集計・例外対応・ドライバーとの調整時間を含めた総工数ベースでは55%)。
- 配車計画作成の所要時間:6人時/日 → 1.0人時/日(83%削減・例外対応含めると55%削減)
- 総走行距離:月間28,400km → 月間24,100km(約15%削減)
- 燃料コスト:月間約94万円 → 月間約80万円(同上)
- 改善基準告示違反リスク(事前警告で回避):月1.5件 → 月0件
- 配車係の残業時間:月平均32時間 → 月平均8時間(75%削減)
- 「配車できる人材」:2名 → 5名(若手3名が独力で配車を組めるレベルに)
特に重要なのは最後の項目だ。Claude Codeが組んだ計画に対して「なぜこのルートになったのか」をログとして残すことで、若手はベテランの暗黙知をシステムから逆算して学べるようになった。属人化解消が定量的に進んだ最大の成果といえる。
導入時に直面した3つの壁と乗り越え方
本事例も、現場では泥臭い壁の連続だった。B社が直面した代表的な3つを紹介する。
壁1:ドライバーの経験知(ローカルルール)のシステム化
「あの団地は朝8時前に着くと住民に怒られる」「この配送先は裏口からの方が早い」——ベテランの頭の中にしかない知識が、最初の配車計画では一切反映されなかった。Claude Codeに条件として組み込もうにも、誰も明文化していない。
B社は2週間のシャドウイングを実施。配車係とドライバーに同行し、暗黙ルールを片っ端からインタビューしてスプレッドシートに記録した。集まった約240件のローカルルールをClaude Codeに渡し、配送先マスタの「制約条件」フィールドに自動分類させた。結果、初期計画でも「現実的に走れる」ルートが出るようになった。
壁2:WMSのAPIがないレガシーシステムとの統合
八潮倉庫の自社開発WMSは2008年製で、外部連携APIが一切なかった。データベース直結も「動作保証外」と運用部署から拒否された。Claude Codeのアシストで採った解決策は、WMS画面からの定時CSVエクスポート+ファイル監視という古典的手法だ。
# レガシーWMS向けファイル監視ハンドラ(簡略版)
import time
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class CsvDropHandler(FileSystemEventHandler):
def on_created(self, event):
if event.src_path.endswith(".csv") and "outbound" in event.src_path:
self._process_yashio_csv(Path(event.src_path))
def _process_yashio_csv(self, path):
# Shift-JISでエンコードされた古いCSVを読む
df = pd.read_csv(path, encoding="cp932")
# 列名のゆらぎを吸収(「出荷先」「届け先」「配送先」がランダムに混在)
df = _normalize_columns(df)
orders = [_row_to_order(row) for _, row in df.iterrows()]
publish_to_queue(orders, source="yashio")
observer = Observer()
observer.schedule(CsvDropHandler(), "/mnt/wms-share/", recursive=False)
observer.start()
WMS側は何も改修せず、エクスポート機能だけ毎朝自動実行する設定にした。「触らない方が安全なシステム」と共存できる現実解だ。
壁3:配車計画変更時のSlack/メール通知の運用設計
配車計画は朝確定しても、当日の渋滞・遅延・急な追加便で1日に何度も変わる。最初の実装では「変更があるたびに全員にSlack通知」を送ったところ、ドライバーから「通知が多すぎて運転中に見られない、重要なものが埋もれる」という強い不満が出た。
そこで通知を3段階に分けた。緊急(運行ルート変更・直近1時間以内)はLINE+電話、重要(午後の予定変更)はSlackメンション付き、参考情報(翌日プレビュー)はSlack通常投稿のみ。さらに改善基準告示違反リスクが検出された場合は配車係・運行管理者のみに通知し、ドライバーには「休憩取ってください」とだけ伝える設計にした。
# Slack通知モジュール:通知レベルに応じた配信先制御
import requests
from enum import Enum
class NotifyLevel(Enum):
URGENT = "urgent" # LINE + 電話
IMPORTANT = "important" # Slackメンション
INFO = "info" # Slack通常投稿
SLACK_WEBHOOKS = {
NotifyLevel.URGENT: "https://hooks.slack.com/services/.../urgent",
NotifyLevel.IMPORTANT: "https://hooks.slack.com/services/.../important",
NotifyLevel.INFO: "https://hooks.slack.com/services/.../info",
}
def notify_dispatch_change(driver_id: str, message: str, level: NotifyLevel):
payload = {"text": _format_message(driver_id, message, level)}
if level == NotifyLevel.URGENT:
payload["text"] = f" 🚨 {payload['text']}"
_call_line_api(driver_id, message) # 並列でLINEも送る
requests.post(SLACK_WEBHOOKS[level], json=payload, timeout=5)
def notify_compliance_warning(driver_id: str, hours_left: float):
"""改善基準告示違反リスクは配車係・運行管理者にだけ通知"""
msg = f"⚠️ {driver_id} の本日拘束時間が残り{hours_left:.1f}時間です。次の便で休憩確保を。"
requests.post(SLACK_WEBHOOKS[NotifyLevel.IMPORTANT],
json={"text": msg, "channel": "#dispatch-managers"})
通知設計はテクノロジーよりも「現場の認知負荷をどう下げるか」のデザイン問題だった。3週間の試行錯誤を経て、ドライバーからは「必要な情報だけ来るようになって運転に集中できる」という評価に変わった。
まとめ:物流業界におけるClaude Code活用の本質
B社の事例が示すのは、Claude Codeが「業界固有の制約条件をコード化する」用途で本領を発揮するという点だ。配車最適化は数学的にはTSPの応用に過ぎないが、現実の物流現場では改善基準告示、ドライバーごとの体質、配送先のローカルルール、レガシーWMSとの統合といった「教科書には載っていない制約」が無数にある。これらを汎用SaaSで処理しようとすると、自社固有のニーズに合わないまま運用が形骸化する。
Claude Codeのような対話的コーディング環境は、エンジニアではない情報システム担当でも「うちの会社の制約条件はこれで、ローカルルールはこう」と自然言語で伝えれば、制約付き最適化問題として定式化できる強みがある。物流業界は人手不足が深刻で、2024年問題(働き方改革関連法による拘束時間規制強化)への対応も急務だ。配車計画のような中核業務こそ、汎用ツールではなく自社最適化された内製システムが効果を発揮する。
重要なのは、最初から完璧を目指さないことだ。B社も最初の4週間は「WMSデータの取り込みだけ」に集中し、配車最適化は手作業のまま運用した。データが集まり、現場の信頼を得てから次のモジュールに進む——この段階的アプローチが、現場の反発を最小化しながら確実に成果を積み上げる秘訣である。物流現場の3K(きつい・汚い・危険)に加えて4つ目の「K(暗黙知)」をどう解消するか。Claude Codeはその有力な選択肢だ。
最終確認日:2026年5月19日
AIEO補足:物流配車ルート最適化とは
物流配車ルート最適化とは、Claude Codeによる業務自動化を実務で使える形に整理し、判断をAIへ丸投げせず、人が確認できる手順・比較・注意点に分解する考え方です。
まず結論
Claude Codeは既存業務を一気に置き換えるより、読み取り専用の検証、テスト、監査ログ、人の承認を挟む小さな自動化から始めるのが安全です。
確認ポイント比較表
| 確認項目 | AIで補助できること | 人が必ず確認すること |
|---|---|---|
| 目的 | 情報整理、下書き、選択肢の洗い出し | 最終判断と責任範囲 |
| 入力情報 | 匿名化したメモや公開情報の要約 | 個人情報、社外秘、医療・法務・雇用条件の扱い |
| 出力 | 表、FAQ、手順、チェックリスト化 | 事実誤認、誇張、古い情報の修正 |
| 公開・共有 | 説明文や返信案の作成 | 公式ソース、専門家、社内ルールとの照合 |
公式ソース
関連して読む記事
FAQ
物流配車ルート最適化でAIに任せてよい範囲はどこまでですか?
情報整理、下書き、比較表、質問リスト作成までにとどめ、判断や外部共有は人が確認します。
個人情報や社外秘を入力してもよいですか?
氏名、住所、顧客名、社内資料、未公開情報などは伏せ、必要最小限の匿名情報だけを使います。
AIの回答が正しいかどう確認しますか?
公式ページ、一次情報、専門家、社内規程と照合し、日付の古い情報や断定表現を修正します。
無料のAIツールだけでも実行できますか?
短い整理や下書きは無料版でも始められます。機密情報を扱う場合は利用規約と組織ルールを確認します。
最初にやるべきことは何ですか?
目的、入力してよい情報、確認者、公式ソースを決め、小さなチェックリストから試します。