MemoryLake
すべての記事に戻る
News2026年9月10日·12 分で読了

Mistralがエージェントを活用して4万行のFortranを移行 — まずドキュメントを整理することが最優先だった (2026)

2026年9月9日、Mistralは、ほとんどの開発チームが不可能と呼ぶであろうタスクのエンジニアリングレポートを公開しました。それは、欧州のエネルギー事業者向けに、物理演算を多用する油層シミュレータをFortran 77からC++へと移行するプロジェクトです。Mistralの言葉を借りれば、そのコードベースには「テストスイートも一元化されたドキュメントも存在しない」状態でした。最初のスプリントでは、30万行のうち4万行が対象となりました。

見出しを飾るのはエージェントです。このプロジェクトでは100以上のエージェントが稼働しました。しかし、エージェントが役に立つようになる前にチームが何を構築しなければならなかったかについてレポートを読むと、物語の様相が変わってきます。Mistralが最後に挙げた3つの教訓のうち、2つはエージェントに関するものではありません。それらは「書かれた知識」、つまり知識を保有し、それを信頼できる状態にすることについてです。

この違いは、自身の在籍期間よりも古いコードベースでコーディングエージェントを動かそうとしているすべての人にとって重要です。本記事では、Mistralのレポートの後半部分、すなわちプロジェクトが何を書き残さなければならなかったのか、なぜ書くことが最優先だったのか、そしてプロジェクトが終了したときにその記録はどうなるのかについて掘り下げます。

Mistralが実際に公開した内容

このブログ記事は、ツールではなく人に関する一文から始まります。

「レガシーな科学技術計算コードベースは数十年にわたって蓄積され、オリジナルの開発者が去ると、コードに埋め込まれた知識を回復することは困難になります。」

Fortran 77は、記事で指摘されているように、「その名の通り1977年に標準化されたものであり、そこに書かれたコードはその制約を直接反映しています。モジュールはなく、名前空間もなく、構造化された型もありません。状態はCOMMONブロック(プログラム全体で共有されるグローバルメモリ)に存在します。」変数名は最大6文字に制限されています。名前のスペルミスは、エラーを発生させる代わりに、暗黙的に新しい変数を作成してしまいます。

Mistralは開始前に3つの問いを立てました。「移行されたコードベースがレガシーなものと数値的に一致することをどう証明するか」、「移行をどのように管理可能なチャンクに分割するか」、そして「プロセスを加速するために自律型エージェントをどのように最適に活用するか」です。この順序に注目してください。等価性の証明が最初に来て、エージェント戦略は3番目でした。

証明の仕組みは「パリティハーネス(同等性検証環境)」でした。チームは「Fortranコードベースの状態をエクスポートできるようにするサブルーチン」、「チェックポイントをC++にロードするためのテストフレームワーク」、そして「エージェントがそれらを正しく使用するように誘導するためのSkill.mdファイル」を追加しました。彼らの評価は次の通りです。「ハーネスのこの部分を最初に構築したことは、プロジェクトにとって純プラスの投資でした。これにより、エージェントの長期実行がより安全になり、数値的なパリティ(同等性)は、コードの一部が正常に移行されたことを示すための、検証が容易で説得力のある論拠となりました。」

次に、ドキュメント化のプロセスです。プロジェクトの既存のドキュメントは「古いPDFやFortran自体に埋もれたコメントに散在していました」。Mistralは「カスタムパーサーでコードベースを解析して」呼び出し元・呼び出し先のツリー(caller-callee tree)を生成し、その後「Vibe CLIを使用して100以上のエージェントを起動し、ドキュメント化を行いました」。ツリーの葉(末端)から上に向かって作業を進め、各ノードがプルリクエストを作成しました。そして、彼らはその結果を次のように説明しています。

「この取り組み全体の最大の副次的成果(side-win)の1つは、これらのドキュメントを整理統合し、コードのすぐ隣に移動できたことでした。」

移行自体は3回試行されました。最初の試み:「エージェントに完全な自律性を与えました。Fortranのサブルーチンごとに1つのエージェントを割り当て、それぞれが1週間にわたって独立して機能をC++に翻訳しました。結果は動作するものでしたが、コードの近代化(モダン化)とは呼べないものでした。COMMONブロックは1対1でグローバル構造体になりました。GOTO駆動の制御フローは、ループや早期リターンに再構築されることなく、そのまま残りました。それは近代化されたコードというよりも、C++の構文で書き直されただけのFortranのように見えました。」

2回目の試みでは、エージェントに構造を与えました。「プランナー、コーダー、テスター、およびコード品質レビュー担当者が各モジュールで連携して作業する」体制です。品質は向上しましたが、「最終的にはソースコードの複雑さがエージェントに追いつきました。彼らはバグに遭遇すると、いくつかの修正を試みた後に失速し、介入できる人間が誰もいない状態になってしまいました。」

最終的に採用されたのは、その中間案でした。「人間がコーダー、テスター、レビュー担当者のエージェントのワークフローを操作し、モジュールごとにコードベースを移行する」という方法です。

そして、3つの教訓は原文のまま以下の通りです。まずパリティハーネスを構築すること。なぜなら「数値的な一致は、モジュールが完了したことを示す最も安価で説得力のある証明だからです」。「エージェントに頼る前にドキュメントを整理すること。誰も読めないコードを移行することはできないからです」。そして「この規模では、人間のレビューゲートを設けた構造化されたワークフローが、完全な自律性と手動によるセッションの両方に勝る」ということです。

これによって何が変わり、何が変わらないのか

これは、エージェントがレガシーコードを移行できないと言っているわけではありません。実際に移行は行われましたし、Mistral自身の見解でも、構文の翻訳は「ほぼ解決された課題」とされています。難しかったのはアーキテクチャの部分です。手続き型コードからオブジェクト指向のC++への移行は、「チェックすべき行ごとの対応関係が存在しないため、移行の検証が困難になる」ことを意味していました。

また、これがすべてのレガシーシステムに一般化できるわけでもありません。Mistralは直接こう述べています。「Fortranのコードベースは自己完結しており、実行可能でした。これは好ましい開始条件です。外部システムに依存している移行、実行可能なベースラインがない移行、あるいはどこにも文書化されていない物理法則をコード化している移行は、この投稿では議論されていない追加の課題をもたらすでしょう。」

最後の句をゆっくり読んでみてください。どこにも文書化されていない物理法則。 Mistralは、自らの手法の限界として、知識が「一度も書き残されたことがない」ケースを挙げています。書き方が悪かったわけでも、古くなっていたわけでもありません。存在しないのです。

この投稿が変えるのは、優先順位(ランキング)です。このプロジェクトにおける最大の制約は、エージェントの能力ではありませんでした。コードの背後にある「理由」が、何らかの形で読み取れる状態で存在していたかどうか、そして回収されたそれらの理由が最終的にどこに配置されるかだったのです。

人々がこの件から誤って受け取りがちな解釈

すでに3つの解釈が世間に広まっていますが、そのどれもが重要な部分を見落としています。

「レガシーコードベースに100のエージェントを投入せよ」 100のエージェントが機能したのは、カスタムパーサーがすでに割り当て用の呼び出し元・呼び出し先ツリーを生成していたからであり、またMistralが手続き型コードの特性(「プログラム全体を単一の呼び出し元・呼び出し先ツリーとして描くことができる」)を利用できたからです。その構造がなければ、並列展開する対象がありません。エージェントは最初の一歩ではなく、最後のステップだったのです。

「ドキュメント化は嬉しい副産物だった」 Mistralはそれを「副次的成果(side-win)」と呼んでいますが、彼ら自身の教訓リストではそれを前提条件として位置づけています。つまり、エージェントに頼る前に整理しておくべきものです。最初に作成しなければならない副産物とは、実質的には「お行儀の良い前提条件」にほかなりません。

「エージェントは失われた知識を再構築できる」 彼らが再構築したのは、既存のPDFやコードコメントから得られるドキュメントでした。何も存在しない場所については、Mistralは対象外としています。これは、他の2つのベンダーが独自の言葉で描いている境界線と同じです。ClineはそのMemory Bankを「Clineをステートレスなアシスタントから永続的な開発パートナーへと変貌させるドキュメント化手法」と説明しています。これは「手法(methodology)」であり、ツールが導き出すものではなく、人間が行うことを意味します。OpenHandsは、この2つを明確に分けています。「リポジトリで作業するすべてのエージェントに向けた指示にはAGENTS.mdを維持し、メモリはエージェント自身が学習した内容のために使用する」。3つの独立したベンダーが、書かれた意図と導出された知識は異なる素材であると、3通りの方法で述べているのです。

これは彼らの誰に対する批判でもありません。それが問題の本質的な形状なのです。

すでに私たちが取り上げた関連するケースに興味がある場合、「人が去ると知識も去る」の一般的なバージョンは誰かが辞めたときにAIのコンテキスト(文脈)はどうなるかに、既存のドキュメントをエージェントが実際に参照する形に変換する仕組みはプロジェクトドキュメントをAIメモリに変換するに記載されています。今回の記事はそれらよりも範囲が狭く、「移行」が作成する記録と、その記録が移行後も生き残るかどうかについて焦点を当てています。

解決策:次のプロジェクトが読める場所に意思決定を書き残す

Mistralのドキュメント化プロセスは、コードとPDFにまだ含まれていたものを回収しました。回収できなかったカテゴリ(そして彼ら自身が限界として挙げたカテゴリ)こそ、計画を立てる価値があるものです。開始前にこの2つを分類する方法は以下の通りです。

ステップ 1:パーサーが再生成できるかどうかで知識を分類する

1つのモジュールを取り上げ、新しいエンジニアが必要とするすべての情報をリストアップします。次に、リポジトリのみを読み取るツールで各項目を生成できるかどうかに応じて、印を付けます。

コールグラフ、型シグネチャ、どの関数がどれを呼び出しているか、サブルーチンが機械的に何を行うか:これらは「再生成可能」です。Mistralは、一元化されたドキュメントがないコードベースから、カスタムパーサーとエージェントを使用して、まさにこのクラスの知識を大規模に再構築できることを証明しました。

次に、もう一方の列です。なぜこのソルバーを採用し、明らかな代替案を採用しなかったのか。これら2つのループのうち、油層エンジニアがビット単位で同一でなければならないと指摘したのはどちらか。2019年の前回の移植の試みがなぜ断念されたのか。「クライアントの油層エンジニアによって指摘された中間点」のうち、どれが重要でどれが偶発的なものか。Mistralは、これらのチェックポイントはコードからではなく、エンジニアから得られたものであると言及しています。リポジトリ内のどこにも、そのようなことは書かれていません。

この2番目の列こそが、あなたの真のインベントリ(資産)です。最初の列にあるものはすべて、ビルド成果物にすぎません。

ステップ 2:理由が語られたその瞬間に捉える

2番目の列にある理由は、作業の前にではなく、作業中に表面化します。それらはレビューコメント、ドメインエキスパートとの通話、あるいはエージェントが失速したときに誰かが口にする言葉の中に現れます。Mistral'sの2回目の試みは、これが最も顕著に現れた部分です。エージェントは「バグに遭遇し、いくつかの修正を試みた後に失速し、介入できる人間が誰もいない状態」になりました。失速を解消する介入は、まさに2番目の列の事実であり、それはコミットされるのではなく、口頭で語られるものです。

したがって、その瞬間に捉えてください。人間がエージェントの失速を解消したときは、エージェントが何を結論づけ、実際には何が正しく、それはなぜなのかを1行で書き留めます。ドメインエキスパートが設計を拒否(ベト)したときは、その拒否と理由を設計のすぐ隣に記録し、1週間でクローズされるプルリクエストのスレッドに放置しないでください。

これは、ベンダー自身の説明の信頼性が低下したときに書き留めておくべきことで説明したのと同じ規律です。永続的な成果物は、意思決定とその正当性であり、それを生み出した対話の文字起こしではありません。

ステップ 3:記録にプロジェクト以外の場所(ホーム)を与える

Mistralのドキュメントは「コードの隣」に置かれました。これは最初のステップとしては正しい動きです。元のリポジトリへのプルリクエストであり、cronスケジュールでエージェントによってレビューされます。リポジトリファイルは耐久性があり、バージョン管理され、持ち運びが可能です。

しかし、移行は寿命の異なる2種類の記述を生み出します。モジュールドキュメントはコードを説明するものなので、コードに付随し、コードが再び置き換えられれば一緒に消え去ります。一方で、意思決定(なぜこのアーキテクチャなのか、どの制約が譲れなかったのか、ドメインエキスパートが何を排除したのか)は、FortranとC++の両方よりも長生きします。それらは、次のプロジェクトが問いかけるであろう質問への回答です。

これらには、単一のリポジトリ内のディレクトリではない「ホーム」が必要です。スキルファイルは手順を記述するのに適した手段であり、だからこそMistralは「エージェントがそれらを正しく使用するように誘導するためのSkill.mdファイル」を書きました。しかし、手順は理由ではありません。この点については、なぜエージェントのスキルはメモリではないのかで詳しく説明しています。また、指示ファイルには独自のスコープがあります。コーディングエージェントが実際に読んでいるもので判明したように、エージェントはドキュメントツリーではなく、自身の指示ファイルを読みます。

MemoryLakeでの設定方法

共有された意思決定レイヤーは、どの単一のリポジトリにも属さない部分です。MemoryLakeは、2番目の列の事実(決定事項、制約、断念されたアプローチとその理由)を保持するため、移行作業を行うすべてのエージェントが同じセットを読み取ることができ、プロジェクトが終了した後もそのセットが残ります。セットアップは3つのステップで行えます。ここから開始してください

ステップ 1:APIキーを作成する

移行用のワークスペースを作成し、APIキーを生成します。1つのワークスペースのスコープを、単一のリポジトリではなくプログラム全体に設定します。ソースツリーとターゲットツリーは2つの異なるリポジトリであり、意思決定はその両方に適用されるためです。

新しいキーが作成され、エージェントで使用するためにコピーされるAPIキー画面を表示するMemoryLakeコンソール
新しいキーが作成され、エージェントで使用するためにコピーされるAPIキー画面を表示するMemoryLakeコンソール

ステップ 2:最初のメモリをアップロードする

まずは介入(インターベンション)から始めましょう。人間がエージェントの失速を解消するたびに、そのやり取りにはコードには記載されていない事実が含まれています。次にドメインエキスパートの決定事項を追加し、続いてチェックポイントのリストと各チェックポイントが選ばれた理由を追加します。PDF、ミーティングノート、レビューのスレッドは直接投入できます。事前にマークダウンに変換する必要はありません。

最初のドキュメントがアップロードされ、各ファイルが検索可能なメモリとしてリストされているMemoryLakeワークスペース
最初のドキュメントがアップロードされ、各ファイルが検索可能なメモリとしてリストされているMemoryLakeワークスペース

ステップ 3:AIとエージェントを接続する

実際に作業を行うエージェント(コーダー、テスター、レビュー担当者)を接続します。それぞれが同じ意思決定セットを読み取るため、レビュー担当者エージェントは、コーダーエージェントが見たことのない制約に矛盾する変更を指摘できます。これは、構造化されたワークフローが人間を介在させて手動で埋めているギャップですが、共有レイヤーは人間が介入する前にその一部を自動的に埋めることができます。

メモリレイヤーに接続可能なAIクライアントとエージェントフレームワークをリストしたMemoryLakeの統合画面
メモリレイヤーに接続可能なAIクライアントとエージェントフレームワークをリストしたMemoryLakeの統合画面

実務において何が変わるのか

最初のスプリントで、3人の頭の中にしか存在しない知識が生み出されるのを防ぐことができます。モジュールが新しいエージェントワークフローに渡されるとき、制約も一緒に引き継がれます。

2回目の試みで発生した失敗モードのコストが下がります。エージェントは、数値の慣例、暗黙の契約、物理的な仮定など、同じクラスの問題で繰り返し失速します。最初の失速には人間の介入コストがかかりますが、同じ事実に関するその後の失速はコストゼロになります。なぜなら、その事実がすでに読み取り可能な状態になっているからです。

そして、記録はプロジェクト終了後も生き残ります。Mistralの最初のスプリントは30万行のうち4万行をカバーしたに過ぎず、これは今後さらに5回のスプリントが控えており、おそらく異なるメンバーが担当することを意味します。第6スプリントが「理由」からスタートできるか、それとも理由を再発見することになるかは、今それらをどこに置くかによって決まります。

移行から得た教訓を維持するためのベストプラクティス

移行コードを書く前にパリティハーネスを構築してください。Mistralの最も強力な主張は、数値的な一致が「モジュールが完了したことを示す最も安価で説得力のある証明である」ということです。ハーネスはまた、「正しい」とは何かを示す書かれた記録でもあり、プロジェクトが生成する最も再利用可能なドキュメントとなります。

再生成可能な知識と再生成不可能な知識は別々の場所に保管してください。これらを混ぜてしまうと、再生成を行うたびに、再生成できない部分が上書きされるリスクが生じます。これは、大規模な証明作業中にエージェントがすでに真実であったことをどのように記録したかで説明したのと同じ罠です。永続的な価値は、それを生成した実行プロセスではなく、書かれた記録にありました。

単なる決定事項だけでなく、拒否(ベト)された事項も記録してください。「PetScを選択した」という記述は、「これら2つの代替案を検討し、以下の理由で除外した上で、PetScを選択した」という記述よりも説得力が劣ります。除外された選択肢を記録しておくことで、次のエージェントがそれを再び提案するのを防ぐことができます。

ドメインの事実に日付を付けてください。9月時点での油層エンジニアの制約は、3月には上書きされている可能性があります。日付のない制約は、永遠に従われ続けるか、あるいは完全に無視されるかのどちらかになります。

人間のレビューゲートを、単なるコントロール(管理手段)ではなく、情報源(ソース)として扱ってください。Mistralの3つ目の教訓は、ゲートが完全な自律性に勝るということです。各ゲートは、リポジトリに含まれていない内容を人間が表明する瞬間でもあります。その瞬間を捉えて記録してください。

結論

Mistralのレポートは、エージェントがレガシーコードを移行する物語として読まれるでしょうし、あるレベルにおいてはその通りです。しかし、彼ら自身の3つの教訓は、エージェント戦略よりもハーネスの構築とドキュメント化のプロセスを優先させており、彼らが自らの手法の限界として引いた境界線は、「どこにも文書化されていない物理法則をコード化している」コードです。

エージェントは機械的な作業を安価にしました。しかし、文書化されていない意図を回復可能にしたわけではなく、Mistralもそう主張してはいません。移行はいずれ終わります。C++も最終的にはレガシーになるでしょう。将来に引き継がれるのは、誰かが書き残すことを選択した部分であり、それをどこに置いたかです。

よくある質問

Mistralのエージェントは単独で移行を完了したのですか?

いいえ。Mistralは3つのアプローチを説明しています。完全な自律性を持たせたアプローチでは、「近代化されたコードというよりも、C++の構文で書き直されただけのFortranのように見える」コードが生成されました。構造化されたマルチエージェントチームは品質を向上させましたが、複雑なバグに遭遇すると「介入できる人間が誰もいない状態で」失速しました。最終的に採用されたのは、「人間がコーダー、テスター、レビュー担当者のエージェントのワークフローを操作する」方法でした。

コードベースのどれくらいが移行されたのですか?

Mistralは「最初のスプリントでコア機能である30万行のうち4万行をカバーした」と報告しています。この記事では、「Fortranのコードベースが自己完結しており、実行可能であった」ため、これが好ましいケースであったと位置づけています。

パリティハーネス(同等性検証環境)は何のためのものだったのですか?

新旧のコード間で数値的な等価性を証明するためです。移行によってアーキテクチャが再構築されたため、「チェックすべき行ごとの対応関係が存在しない」状態でした。そのため、チームはFortranから状態のスナップショットをエクスポートし、それらをC++テストフレームワークの参照チェックポイントとしてロードしました。

なぜエージェントの前にドキュメント化のプロセスを行う必要があったのですか?

Mistralの2つ目の教訓で直接述べられています。「エージェントに頼る前にドキュメントを整理すること。誰も読めないコードを移行することはできないからです」。チームはカスタムパーサーで呼び出し元・呼び出し先のツリーを生成し、エージェントにその末端から上に向かってドキュメント化を行わせ、元のリポジトリにプルリクエストを作成させました。

これは、エージェントが一度も書き残されたことのない知識を回復できるという意味ですか?

Mistral自身が挙げた限界事例によれば、答えはノーです。彼らは、自らの手法がカバーしないケースとして「どこにも文書化されていない物理法則をコード化している」移行を挙げています。ドキュメント化エージェントは、既存の古いPDFやコードコメントを基に作業を行いました。

パーサーが後から再生成できない情報として、チームは何を書き残すべきですか?

設計の却下とその理由、ドメインエキスパートによって表明された制約、どの中間結果が正確に一致しなければならないかとその理由、および失速したエージェントを人間が救い出した際に提供したすべての事実です。コールグラフ、シグネチャ、機械的な説明はリポジトリから再構築できますが、上記の情報は再構築できません。