Legacy Modernization Agents
AI-powered COBOL to Java Quarkus modernization agents using Microsoft Agent Framework. Automates legacy mainframe code modernization with intelligent agents for analysis, conversion, and dependency mapping.
Install / Use
npx skills add Azure-Samples/Legacy-Modernization-AgentsInstalls into whichever agent you are using.
README
Legacy Modernization Agents - COBOL to Java/C# Migration
This open source migration framework was developed to demonstrate AI Agents capabilities for converting legacy code like COBOL to Java or C# .NET. Each Agent has a persona that can be edited depending on the desired outcome. The migration uses Microsoft Agent Framework with a multi-provider architecture supporting Azure OpenAI (Responses API + Chat Completions), GitHub Copilot (PAT or CLI-based SDK), and direct OpenAI to analyze COBOL code and its dependencies, then convert to either Java Quarkus or C# .NET (user's choice).
🎬 Portal Demo

The web portal provides real-time visualization of migration progress, dependency graphs, and AI-powered Q&A.
[!TIP] Ways to use this framework:
| Command | What it does | |---|---| |
./doctor.sh setup| Configure the framework — set up the AI provider, credentials, models, and local services | |./doctor.sh rekt-full| Run deterministic static analysis (optional but recommended) — parse COBOL sources deterministically and ingest the resulting artifacts into the REKT Neo4j graph | |./doctor.sh reverse-eng| Extract business logic only — runs RE analysis, persists results to DB, launches the portal | |./doctor.sh run| Run a full migration — analyze COBOL, convert to Java/C#, generate reports, and launch the portal | |./doctor.sh portal| Open the portal only — browse previous migration results, dependency graphs, and chat with your codebase at http://localhost:5028 |The doctor script handles dependency checks and required service startup automatically.
📋 Table of Contents
- Quick Start
- Usage: doctor.sh
- Reverse Engineering Reports
- Folder Structure
- Customizing Agent Behavior
- File Splitting & Naming
- Architecture
- Smart Chunking & Token Strategy
- Build & Run
🚀 Quick Start
Prerequisites
| Requirement | Version | Notes |
|-------------|---------|-------|
| .NET SDK | 10.0+ | Download |
| Docker Desktop | Latest | Must be running for Neo4j |
| AI Endpoint | — | Azure endpoint + az login, or GitHub gh auth login, or API Key |
Supported AI Providers
This project supports four AI providers with automatic model capability detection:
| Provider | ServiceType | Models | Auth | Interface |
|----------|------------|--------|------|-----------|
| Azure OpenAI | AzureOpenAI | gpt-5.1-codex-mini, gpt-5.2-chat | API Key or az login (Entra ID) | ResponsesApiClient (Codex) + IChatClient |
| GitHub Copilot | GitHubCopilot | Claude Opus/Sonnet, Codex, GPT, Grok | GitHub PAT (GITHUB_TOKEN) | IChatClient via models.github.ai |
| GitHub Copilot SDK | GitHubCopilotSDK | All Copilot models | gh auth login (CLI) | CopilotChatClient via stdio |
| OpenAI | OpenAI | GPT-4o, o3, etc. | OpenAI API key | IChatClient |
Model-Aware Reasoning — The framework auto-detects model capabilities from the model ID and adapts its reasoning strategy:
| Model Family | Detection | Reasoning Strategy | Applied Via |
|-------------|-----------|-------------------|-------------|
| Codex/o-series | codex, o1, o3 in model ID | reasoning.effort (low/medium/high) | Responses API or AdditionalProperties |
| Claude | claude in model ID | Extended thinking with budget_tokens | AdditionalProperties["thinking"] |
| GPT | gpt-4, gpt-5 in model ID | Standard (temperature=0.1) | ChatOptions.Temperature |
| Grok | grok in model ID | Standard (temperature=0.1) | ChatOptions.Temperature |
All models get the same three-tier content-aware complexity scoring — COBOL source is analyzed for SQL, CICS, REDEFINES, etc. to determine LOW/MEDIUM/HIGH complexity. The complexity tier drives both
MaxOutputTokenssizing and the model-specific reasoning parameter.
⚠️ Want to use different models? Just change
AZURE_OPENAI_MODEL_IDandAZURE_OPENAI_SERVICE_TYPE. The framework auto-detects capabilities — no code changes needed.
[!IMPORTANT] Azure OpenAI Quota Recommendation: 1M+ TPM
For optimal performance, we recommend setting your Azure OpenAI model quota to 1,000,000 tokens per minute (TPM) or higher.
| Quota | Experience | |-------|------------| | 300K TPM | Works, but slower with throttling pauses | | 1M TPM | Recommended - smooth parallel processing |
Higher quota = faster migration. The tool processes multiple files and chunks in parallel, so more TPM means less waiting.
To increase quota: Azure Portal → Your OpenAI Resource → Model deployments → Edit → Tokens per Minute
Parallel Jobs Formula
To avoid throttling (429 errors), use this formula to calculate safe parallel job limits:
TPM × SafetyFactor
MaxParallelJobs = ─────────────────────────────────
TokensPerRequest × RequestsPerMinute
Where:
- TPM = Your Azure quota (tokens per minute)
- SafetyFactor = 0.7 (recommended, see below)
- TokensPerRequest = Input + Output tokens (~30,000 for code conversion)
- RequestsPerMinute = 60 / SecondsPerRequest
Understanding SafetyFactor (0.7 = 70%):
The SafetyFactor reserves headroom below your quota limit to handle:
| Why You Need Headroom | What Happens Without It | |----------------------|------------------------| | Token estimation variance | AI responses vary in length - a 25K estimate might actually be 35K | | Burst protection | Multiple requests completing simultaneously can spike token usage | | Retry overhead | Failed requests that retry consume additional tokens | | Shared quota | Other applications using the same Azure deployment |
| SafetyFactor | Use Case | |--------------|----------| | 0.5 (50%) | Shared deployment, conservative, many retries expected | | 0.7 (70%) | Recommended - good balance of speed and safety | | 0.85 (85%) | Dedicated deployment, stable workloads | | 0.95+ | ⚠️ Risky - expect frequent 429 throttling errors |
Example Calculation:
| Your Quota | Tokens/Request | Request Time | Safe Parallel Jobs |
|------------|----------------|--------------|-------------------|
| 300K TPM | 30K | 30 sec | (300,000 × 0.7) / (30,000 × 2) = 3-4 jobs |
| 1M TPM | 30K | 30 sec | (1,000,000 × 0.7) / (30,000 × 2) = 11-12 jobs |
| 2M TPM | 30K | 30 sec | (2,000,000 × 0.7) / (30,000 × 2) = 23 jobs |
Configure in appsettings.json:
{
"ChunkingSettings": {
"MaxParallelChunks": 6, // Parallel code conversion jobs
"MaxParallelAnalysis": 6, // Parallel analysis jobs
"RateLimitSafetyFactor": 0.7, // 70% of quota
"TokenBudgetPerMinute": 300000 // Match your Azure TPM quota
}
}
💡 Rule of thumb: With 1M TPM, use
MaxParallelChunks: 6for safe operation. Scale proportionally with your quota.
Framework: Microsoft Agent Framework
This project uses Microsoft Agent Framework (Microsoft.Agents.AI.*), not Semantic Kernel.
<!-- From CobolToQuarkusMigration.csproj -->
<PackageReference Include="Microsoft.Agents.AI.AzureAI" Version="1.0.0-preview.*" />
<PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.*" />
<PackageReference Include="Microsoft.Extensions.AI" Version="10.0.1" />
Why Agent Framework over Semantic Kernel?
- Simpler
IChatClientabstraction - Native support for both Responses API and Chat Completions API which is key for being future proof for LLM Api's
- Better streaming and async patterns
- Lighter dependency footprint
Setup (2 minutes)
# 1. Clone and enter
git clone https://github.com/Azure-Samples/Legacy-Modernization-Agents.git
cd Legacy-Modernization-Agents
# 2. Configure Azure OpenAI
cp Config/ai-config.env.example Config/ai-config.local.env
# Edit: _MAIN_ENDPOINT (required), _CODE_MODEL / _CHAT_MODEL (optional)
# Auth: use 'az login' (recommended) OR set _MAIN_API_KEY
# See docs/az-login-auth-guide.md for Entra ID setup details
# 3. Start Neo4j (the password is configured in ai-config.local.env)
export NEO4J_PASSWORD="$(sed -n 's/^NEO4J_PASSWORD=//p' Config/ai-config.local.env | tr -d '"')"
docker-compose up -d neo4j
# 4. Build
dotnet build
# 5. Run migration but we recommend using the next section with doctor.sh run or portal for just loading the portal
./doctor.sh run
🎯 Usage: doctor.sh
Always use ./doctor.sh run to run migrations, not dotnet run directly.
Main Commands
./doctor.sh run # Full migration: analyze → convert → launch portal
./doctor.sh portal # Launch web portal only (http://localhost:5028)
./doctor.sh reverse-eng # Extract business logic, persist to DB, launch portal
./doctor.sh convert-only # Conversion only; prompts to reuse persisted RE context
Business Logic Persistence and --reuse-re
After every reverse-eng or full run, extracted business logic is persisted to the SQLite database. This enables three distinct conversion modes:
| Mode | Command | RE context in prompts? |
|------|---------|------------------------|
| Full migration | ./doctor.sh run | ✅ Yes — RE runs first, results injected automatically |
| Pure conversion | ./doctor.sh convert-only → answer N | ❌ No context |
| Conversion + cached RE | ./doctor.sh convert-only → answer Y | ✅ Yes — loads persisted results from last RE run |
The --reuse-re flag can also be passed directly: dotnet run -- --source ./source --skip-reverse-engineering --reuse-re.
Persisted RE results are visible in the portal — each run card has a 🔬 RE Results
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.7kCommit, push, and open a PR
