DigestAI news desk
OpenAI board member warns company is not on track to prevent catastrophic AI loss of control OpenAI launches Agents API beta for long-running cloud agents OpenAI Unveils GPT‑6 Astra: Record‑Breaking 3D Rendering, Loop‑Transformer Architecture OpenAI solves Navier-Stokes problem, sparking academic controversy over data use OpenAI Introduces ChatGPT for Financial Services Anthropic releases 150-page report on global Claude misuse and distillation RTK Token Savings Debunked: Cost Benchmarks Disagree The Waymo effect: AI making research less collaborative
Enterprise & Industry updated 6 min read

Modernizing Legacy Code with AI Agents

Mistral AI successfully modernized 40,000 lines of Fortran 77 code to C++ for a European energy operator. The project involved building a parity harness for numerical verification, documenting the codebase with AI agents, and using structured workflows with human oversight. Key lessons included prioritizing numerical agreement, organizing documentation before migration, and balancing agent…

1 source primary source

Key points

  • Mistral AI modernized 40,000 lines of Fortran 77 code to C++.
  • Used AI agents for documentation and code modernization.
  • Structured workflows with human oversight ensured numerical accuracy.
Full story from Mistral AI primary source Open source ↗

Modernizing complex legacy code with AI agents.

Mistral AI · 9 September 2026

Thinking

Summary

Legacy code modernization is challenging, especially when migrating complex Fortran 77 systems to modern C++. Mistral successfully migrated 40,000 lines of a physics-intensive reservoir simulator by building a parity harness for numerical verification, documenting the codebase with AI agents, and using structured workflows with human oversight to ensure high-quality, maintainable code. Key lessons include prioritizing numerical agreement, organizing documentation before migration, and balancing agent autonomy with human review.

Legacy scientific codebases accumulate over decades, and when original authors leave, the knowledge embedded in the code becomes hard to recover. Moreover, using languages with no active developer ecosystem means missing out on the opportunity to build on top of others’ work. Mistral helped a European energy operator migrate 40,000 lines of Fortran 77 to C++, a physics-intensive reservoir simulator with no test suite and no centralized documentation.

Moving beyond code translation in legacy code modernization.

Translating syntax from one language to another is a largely solved task. Asking any recent model to translate a snippet from a non-completely-obscure language to another, will likely converge to an acceptable outcome in few iterations. However, migrating a full system from a procedural language to object-oriented C++ creates the need for architectural refactors that make the task non-trivial.

Fortran 77 was standardized in 1977, as the name may suggest, and code written in it reflects those constraints directly: no modules, no namespaces, no structured types. State lives in COMMON blocks—global memory shared across the entire program. Variables are implicitly typed by their first letter, so a misspelled name silently creates a new variable instead of raising a compiler error.

For a simple but illustrative example, take the following implementation of a first-degree Taylor expansion. Inputs and outputs are globals in a COMMON block, and IC is an integer only because its name starts with a letter between I and N. Variable names are quite cryptic, as their length is capped to 6 characters.

In C++, one will be able to leverage explicit types, write object-oriented code, and return a value returned instead of a global write:

The scattered COMMON arrays become a single GasProperties parameter and the grid loop moved out to the caller, so there's no line-for-line correspondence to check, which is what makes verifying the migration hard.

These structural differences, plus the requirement to integrate modern scientific computing frameworks such as PetSc, raised a few important questions even before starting the migration:

  • How to prove the migrated codebase matches the legacy one numerically
  • How to split the migration into manageable chunks
  • How to best use autonomous agents to speed up the process

Building a parity harness before migrating legacy code.

Before letting agents loose, we needed a way to prove the two codebases agreed. Here, "agreement" meant numerical equality of the outputs—both the final results and a set of critical intermediate points flagged by the client's reservoir engineers.

We added:

  • subroutines allowing to export the state of the Fortran codebase
  • a test framework to load the checkpoints into C++
  • Skill.md files to steer agents into using them correctly

In the migration workflows, agents successfully instrumented the Fortran codebase to dump state snapshots and used the C++ test framework to verify correctness of migrated modules.

Building this part of the harness first was a net-positive investment for the project: it made long agent runs safer, and numerical parity is an easy-to-verify and compelling argument to show a piece of code has been successfully migrated. We believe this should be one of the first steps for any code modernization engagement.

The example below illustrates this. We first inserted a line into the Fortran code to dump the value of the RHOG variable (42.71834 in this run), and then used that same value as the reference checkpoint when testing the migrated C++ module.

Using AI agents to understand and document legacy codebases.

The project’s documentation was scattered across old PDFs and comments buried in the Fortran itself, and one of the largest side-wins of the whole effort was reconciling this documentation and moving it next to the code.

Luckily, procedural code like Fortran has a convenient property: the whole program can be drawn as a single caller-callee tree. We generated that tree by parsing the codebase with a custom parser, then used Vibe CLI to spawn over a hundred agents to document it. Each agent could pull in the relevant PDFs through document libraries and Mistral OCR.

Starting from the leaves of the tree and working upward, each node spawned a subagent to document it and open a PR to the original repository. A reviewer agent running in a loop on a cron schedule looked for newly opened PRs, reviewing them and scheduling fix tasks when necessary.

Utilizing the AI agents for code modernization.

On our first attempt, we gave agents full autonomy: one agent per Fortran subroutine, each translating its function to C++ independently over the course of a week. The result was functional, but it couldn't be called code modernization. COMMON blocks became global structs, one-to-one. GOTO-driven control flow stayed intact instead of being restructured into loops or early returns. It looked like Fortran retyped in C++ syntax rather than modernized code.

In the second attempt, we addressed this by giving agents structure instead of just autonomy: a planner, a coder, a tester and a code quality reviewer working together on each module. Code quality improved substantially over the first attempt. But the source code's complexity caught up with the agents eventually. They would hit a bug, attempt a few fixes, and stall, with no one available to intervene.

We landed on a middle ground: a human operating a workflow of coder, tester, and reviewer agents, migrating the codebase module by module. This preserved the code quality of the second attempt while adding a human checkpoint to unblock agents when they got stuck. The next section covers this workflow in detail.

Running structured AI agent workflows for complex code migration.

With the codebase documented and the parity harness in place, the remaining fun bit was tuning how much autonomy we could hand the agents while still getting mergeable code out. We tried both extremes, from fully autonomous runs to closely supervised manual sessions. The structured workflow below is where we landed for this use case.

Working with the client's reservoir engineers, we used the caller-callee tree to identify independent modules—self-contained subtrees of manageable size (empirically, less than ~10’000 lines of Fortran). Each module ran through the same workflow:

  1. Generate the target C++ architecture.
  2. Review it with a reservoir engineer.
  3. On approval, break it into a task queue.
  4. Run an implementation sub-workflow per task: plan → implement → test → repeat.
  5. A human reviews the resulting PRs and requests changes until they merge.

Recognizing the limits of AI assisted legacy code modernization.

The first sprint covered core functionality: 40,000 of 300,000 lines. The Fortran codebase was self-contained and runnable, which is a favorable starting condition. Migrations that depend on external systems, lack a runnable baseline, or encode physics documented nowhere would bring additional challenges not discussed in this post.

Applying three principles for modernizing complex legacy systems.

Three lessons from this project should carry over to any large legacy migration.

  1. Build the parity harness before you write migration code—numerical agreement is the cheapest, most convincing proof that a module is done.
  2. Get the documentation in order before you lean on the agents, because you can't migrate code nobody can read.
  3. And at this scale, structured workflows with human review gates beat both full autonomy and hand-driven manual sessions.

We are hiring!

Mistral's Applied AI team is a group of engineers building full-stack solutions around Mistral models and Enterprise platform. We ship high-stakes, domain-specific solution to solve some of the world’s hardest problems.

If this is the kind of work you want to be involved in, apply to join our team.

This text was published by Mistral AI . It is reproduced here with attribution so you can read it in full; the rights remain with the publisher. Read it at the source ↗

Topics · follow one to build your own front page

The headline, key points and digest above were generated by Digest AI's editorial model from the linked sources. Automated summaries can contain errors: the sources are the record. Spotted a mistake? Tell us.

Comments

via GitHub Discussions

Related stories