AIエージェント入門

レガシーシステム×AIエージェント|モダナイゼーションの実践アーキテクチャ3選

レガシーシステム×AIエージェント|モダナイゼーションの実践アーキテクチャ3選

この記事の結論

COBOLやメインフレームのモダナイゼーションにAIエージェントを活用する方法を解説。リバースエンジニアリング・ストラングラーフィグ・検証エージェントのコード例つき。

「ブラックボックス化したCOBOLシステム、どこから手をつければいいのか」

先日、ある製造業の情報システム部門と話す機会がありました。40年前に構築されたメインフレームシステムが今でも基幹業務の中核を担っており、担当していたエンジニアはすでに退職。ソースコードは100万行を超えているが、正確な設計書は存在しない――。これは特殊なケースではなく、日本の大手企業の多くが直面している現実です。

AIエージェントは、この問題に対して根本的に新しいアプローチをもたらしています。コードを「読んで理解する」のではなく、「エージェントが並列で解析し、段階的に置き換える」という発想の転換です。この記事では、AIエージェントを活用したレガシーシステムのモダナイゼーション手法を、実際に使えるコード・アーキテクチャパターンつきで解説します。

AIエージェントがモダナイゼーションにもたらす変化の全体像については、AIエージェント構築完全ガイドでも解説しています。

そもそも何が問題なのか — レガシーシステムの「3つの壁」

モダナイゼーションが難しい理由は、技術的な問題だけではありません。現場で頻繁に遭遇する3つの壁があります。

壁1: 暗黙知の喪失(ドキュメントの空洞化)

設計者が退職し、コードだけが残される。COBOLの場合、業務ロジックがコードに直接埋め込まれていることが多く、ソースを読まないとビジネスルールが分からない。AIエージェントが登場する前は、これを人間が手作業で解読するしかなかった。

壁2: 依存関係の複雑さ(スパゲッティ構造)

COBOLプログラム間のCALL関係、データ定義の共有(COPYBOOK)、JCLジョブの連鎖。これらが絡み合った「依存グラフ」を人間が追うのは限界がある。

壁3: 移行リスクへの恐怖(止められない基幹システム)

24時間365日稼働している銀行の勘定系システムや、物流の在庫管理システムは「一時停止して移行」という手順が取れない。段階的に移行するしか選択肢がないが、それには精密な依存関係の把握が必要になる。

課題 従来のアプローチ AIエージェントによるアプローチ
ドキュメント不在 人手でコードを読み、設計書を手書き エージェントがコードを解析し設計書を自動生成
依存関係の把握 図面を手動作成(数ヶ月かかる) 静的解析エージェントが依存グラフを数時間で構築
移行リスク ビッグバン移行(全部一度に切り替え) ストラングラーフィグパターンで段階的に置換
テスト工数 全機能を人手でリグレッションテスト テストエージェントが自動生成したテストケースで検証

AIエージェントを活用した3つのアーキテクチャパターン

レガシーモダナイゼーションにおけるAIエージェントの活用は、大きく3つのパターンに分類できます。

パターン1: リバースエンジニアリングエージェント(理解フェーズ)

まず既存コードを「理解する」フェーズです。AIエージェントがCOBOLソースコードを解析し、設計書・ER図・API定義を自動生成します。

以下は、LangChainを使ってCOBOLコードを解析し、業務ロジックの概要を日本語で抽出するエージェントの実装例です。

# 動作環境: Python 3.11+, langchain>=0.3.0, openai>=1.30.0
# pip install langchain langchain-openai

import os
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

def analyze_cobol_module(cobol_source: str) -> dict:
    """
    COBOLモジュールを解析し、業務ロジックのサマリーを返す
    """
    llm = ChatOpenAI(
        model="gpt-4o",
        temperature=0,
        api_key=os.environ["OPENAI_API_KEY"]
    )

    system_prompt = """あなたはCOBOLのエキスパートです。
    提供されたCOBOLソースコードを解析し、以下の情報を日本語で抽出してください:
    1. このプログラムの主な業務機能(2-3文)
    2. 入力データ形式(WORKING-STORAGEから)
    3. 出力データ形式
    4. 主要な業務ルール(条件分岐・計算ロジック)
    5. 他のプログラム/コピーブックへのCALL関係

    JSON形式で返してください。"""

    response = llm([
        SystemMessage(content=system_prompt),
        HumanMessage(content=f"以下のCOBOLコードを解析してください:nn{cobol_source}")
    ])

    # 実際の実装では json.loads() でパース処理を追加
    return {"analysis": response.content}


# 使用例
with open("ACCTMAIN.cbl", "r", encoding="shift-jis") as f:
    cobol_code = f.read()

result = analyze_cobol_module(cobol_code)
print(result["analysis"])

動作環境: Python 3.11+, langchain>=0.3.0, GPT-4o API
ポイント: `temperature=0` にすることで決定論的な出力を得られます。大規模なCOBOLプログラム(10,000行超)の場合はチャンク分割が必要です。

パターン2: ストラングラーフィグ × AIエージェント(段階的置換フェーズ)

ストラングラーフィグパターンは、Martin Fowlerが提唱した段階的移行手法です。レガシーシステムを一度に置換するのではなく、新システムが少しずつ機能を引き継ぎながら、最終的にレガシーを廃止します。AIエージェントを組み合わせると、このプロセスを大幅に加速できます。

以下は、AIエージェントが「どのモジュールを先に移行すべきか」を依存関係グラフから判定するコード例です。

# 依存関係グラフを構築し、移行優先度を計算するエージェント
# 動作環境: Python 3.11+, networkx>=3.0

import networkx as nx
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage

def build_dependency_graph(call_map: dict) -> nx.DiGraph:
    """
    CALLマップからCOBOLモジュール依存グラフを構築
    call_map: {"MODULE_A": ["MODULE_B", "MODULE_C"], ...}
    """
    G = nx.DiGraph()
    for caller, callees in call_map.items():
        for callee in callees:
            G.add_edge(caller, callee)
    return G

def get_migration_priority(G: nx.DiGraph) -> list[str]:
    """
    依存されていない(他から呼ばれていない)末端モジュールを優先候補として返す
    これがストラングラーフィグの「最初に置き換えるべき部分」
    """
    leaf_nodes = [n for n in G.nodes() if G.in_degree(n) == 0]
    # 依存先の数(out_degree)が少ない順に並べる(移行コストが低い順)
    return sorted(leaf_nodes, key=lambda n: G.out_degree(n))

# 使用例
call_map = {
    "ACCTMAIN": ["ACCTCALC", "ACCTIO"],
    "ACCTCALC": ["TAXCALC"],
    "ACCTIO":   ["DBWRITE"],
    "TAXCALC":  [],
    "DBWRITE":  []
}

G = build_dependency_graph(call_map)
priority = get_migration_priority(G)
print("移行優先順位:", priority)
# 出力例: ['TAXCALC', 'DBWRITE'](依存先がゼロの末端モジュールが先)

動作環境: Python 3.11+, networkx>=3.0
ポイント: 依存されていない末端から移行を始めることで、他のモジュールへの影響を最小化できます。これがストラングラーフィグの本質です。

実際の移行フローと各フェーズでのエージェントの役割

理論だけでなく、実際のプロジェクトではどう進めるかを整理します。

フェーズ1: 現状把握(2-4週間)

  • 解析エージェント: ソースコードを全スキャンし、モジュール一覧・依存関係・データ定義を抽出
  • ドキュメント生成エージェント: 設計書・ER図・API定義の初版を自動生成
  • 成果物: モジュール依存グラフ(networkxで可視化)、業務ロジックサマリー

フェーズ2: 移行計画(1-2週間)

  • 優先度計算エージェント: 依存グラフから移行順序を算出(上記パターン2のコード)
  • テスト設計エージェント: 各モジュールのテストケースを自動生成(正常系・異常系)
  • 成果物: 移行ロードマップ、テストスイート初版

フェーズ3: 段階的移行(モジュールごとにスプリント)

  • コード変換エージェント: COBOLからPython/Java/Goへの変換候補を生成(人間が最終確認)
  • APIブリッジエージェント: 新旧システム間のデータ変換レイヤーを構築
  • 検証エージェント: 新旧システムの出力を比較し、差異を検出

以下は、新旧システムの出力を比較する検証エージェントの実装例です。

# 新旧システムの出力比較エージェント
# 動作環境: Python 3.11+, requests>=2.31.0

import requests
import json

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

def compare_system_outputs(
    legacy_endpoint: str,
    new_endpoint: str,
    test_cases: list[dict],
    tolerance: float = 0.001  # 数値の許容誤差
) -> dict:
    """
    レガシーシステムと新システムの出力を比較検証する
    """
    results = []

    for case in test_cases:
        legacy_resp = requests.post(legacy_endpoint, json=case["input"]).json()
        new_resp    = requests.post(new_endpoint,    json=case["input"]).json()

        # 数値フィールドは許容誤差内かチェック
        mismatches = []
        for key in legacy_resp:
            if key not in new_resp:
                mismatches.append(f"missing_key: {key}")
            elif isinstance(legacy_resp[key], (int, float)):
                if abs(legacy_resp[key] - new_resp.get(key, 0)) > tolerance:
                    mismatches.append(
                        f"{key}: legacy={legacy_resp[key]}, new={new_resp[key]}"
                    )
            elif legacy_resp[key] != new_resp.get(key):
                mismatches.append(
                    f"{key}: legacy={legacy_resp[key]}, new={new_resp[key]}"
                )

        results.append({
            "test_case": case["id"],
            "passed":    len(mismatches) == 0,
            "mismatches": mismatches
        })

    passed = sum(1 for r in results if r["passed"])
    return {
        "total": len(results),
        "passed": passed,
        "failed": len(results) - passed,
        "details": results
    }

# 使用例
report = compare_system_outputs(
    legacy_endpoint="http://legacy-system/api/calc",
    new_endpoint="http://new-system/api/calc",
    test_cases=[
        {"id": "TC-001", "input": {"amount": 100000, "rate": 0.05}},
        {"id": "TC-002", "input": {"amount": 500000, "rate": 0.03}},
    ]
)
print(json.dumps(report, ensure_ascii=False, indent=2))

動作環境: Python 3.11+, requests>=2.31.0
ポイント: 数値フィールドには許容誤差(tolerance)を設定します。COBOL特有の固定小数点演算とPythonの浮動小数点演算では微小な誤差が生じることがあるためです。

【要注意】よくある失敗パターンと回避策

失敗1: AIに全てのコード変換を任せる

❌ 「AIが自動変換したコードをそのままデプロイする」
⭕ 「AIが変換した候補コードを人間がレビューし、テストでも検証してからデプロイする」

なぜ重要か: COBOLの業務ロジックにはコメントに残っていない暗黙のルールが埋め込まれていることがあります。「月末処理では端数切り捨てではなく四捨五入」といったルールは、AIが変換コードに正しく反映できないケースがあります。現時点では、AIは「下書きを作る」役割に限定し、必ず人間がレビューするフローが必要です。

失敗2: ビッグバン移行を選択する

❌ 「全機能を一気に新システムに切り替える」
⭕ 「ストラングラーフィグパターンで、末端モジュールから順番に移行する」

なぜ重要か: 基幹システムを一度に切り替えると、移行直後に問題が発生した場合のロールバックが非常に困難になります。段階的移行なら、問題が発生したモジュールだけを切り戻せます。

失敗3: テストケースを人手で全量作成しようとする

❌ 「既存のCOBOLプログラムのリグレッションテストを手動で全量作成する」
⭕ 「既存の入出力ログからAIエージェントにテストケースを自動生成させ、重要箇所のみ人間が追加・確認する」

なぜ重要か: 100万行規模のCOBOLシステムのテストを人手で全量作成するのは現実的に不可能です。AIエージェントにテスト生成を任せることで、カバレッジを維持しながら工数を大幅に削減できます。

失敗4: LLMのハルシネーションを見落とす

❌ 「AIが生成した設計書をそのまま正として扱う」
⭕ 「AIが生成した設計書を元のソースコードと照合して、不一致を人間がチェックする」

なぜ重要か: LLMはCOBOLコードの解析で稀に「存在しない変数名」や「誤った計算ロジック」を生成することがあります。生成ドキュメントを「下書き」として扱い、必ずソースとの照合ステップを設けてください。

セキュリティとデータプライバシーの考慮点

レガシーシステムには顧客の個人情報・口座情報・医療情報が含まれることが多いため、AIエージェントによる解析時にはデータプライバシーへの配慮が必須です。

  • マスキング処理: 実データをAIに渡す前に、PII(氏名・口座番号・社会保障番号等)をマスキングする
  • ローカルLLM活用: 機密性の高いコードはクラウドAPIではなく、オンプレミスで動かせるLLM(例: Llama系)を使う
  • アクセス制御: 解析エージェントがアクセスできるコードリポジトリの範囲を最小限に限定する
  • ログ管理: エージェントの解析ログには機密データが含まれる可能性があるため、保存期間と暗号化を厳格に設定する

参考・出典

まとめ:今日から始める3つのアクション

  1. 今日やること: 自社のレガシーシステムの「ブラックボックス度」を測定する。設計書の有無、担当者の在籍状況、依存するモジュール数を棚卸しするだけで、移行コストの大まかな見積もりが立てられます
  2. 今週中: 上記のリバースエンジニアリングエージェント(パターン1のコード)を試しに1モジュールに適用してみる。GPT-4o APIキーがあれば今日から動かせます
  3. 今月中: ストラングラーフィグの「移行候補モジュール」を特定する。まず依存関係グラフを作り、末端モジュールをリストアップするところから始めましょう

あわせて読みたい:


この記事はAIgent Lab編集部がお届けしました。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年4月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事