Legacy systems are the bedrock of many businesses. They hold decades of battle-tested, critical business logic. But they are also often monolithic, brittle, and notoriously difficult to integrate with modern applications. The thought of a full rewrite is daunting—a high-risk, multi-year project that can derail innovation.
So, how do you modernize without the "big bang"? How do you leverage your most valuable assets—your core business rules—in new, agile ways?
The answer lies in a strategic, incremental approach: wrapping your core logic and exposing it as a modern API. With function.do, you can encapsulate specific pieces of legacy logic into atomic functions, turning them into reusable, composable services that breathe new life into your old systems.
If you're working with a legacy system, these challenges probably sound familiar:
These problems effectively trap your most valuable business logic, preventing you from adapting to market changes and building innovative products quickly.
Instead of rewriting everything, you can strategically "strangle" the legacy system piece by piece—a pattern known as the Strangler Fig. You identify a single, valuable piece of business logic and build a modern, lightweight service around it. This new service becomes the new, canonical interface, and over time, more and more logic is migrated out of the monolith.
This is where function.do excels. It’s designed to create these exact kinds of wrappers.
With function.do, you don't just write code; you define atomic, single-purpose functions that represent a distinct business capability. For example, instead of a massive BillingSystem monolith, you can create individual functions like calculateSalesTax, validateCreditCard, or generateInvoicePDF.
Each of these atomic functions is deployed as an independent, executable agent on the .do platform, instantly available as a clean and simple Business Logic API. This decouples new applications from the old system's internal complexity.
Let's walk through how you could wrap a core function from a legacy insurance system: a premium calculator.
First, pinpoint the function. In our legacy insurance application, there's a complex, time-tested set of rules for calculating an insurance premium. This is our target. We want to expose this calculatePremium logic as a modern API endpoint without rewriting it... yet.
Next, we write a function.do agent in TypeScript. This agent will serve as the modern facade for our legacy code. It defines the clean inputs and outputs we want for our new API. The agent's implementation will handle the "dirty" work of connecting to the old system.
import { Agent, property } from '@do-sdk/core';
// Define the modern, clean interface for our function
interface PremiumRequest {
  policyType: 'auto' | 'home';
  coverageAmount: number;
  deductible: number;
  driverAge?: number; // Example specific field
}
interface PremiumResult {
  monthlyPremium: number;
  annualPremium: number;
  discountsApplied: string[];
}
// Create an agent to wrap the legacy premium calculation logic
export class LegacyInsuranceWrapper extends Agent {
  
  @property()
  async calculatePremium(
    request: PremiumRequest
  ): Promise<PremiumResult> {
    
    // --- The "Wrapper" Magic Happens Here ---
    // In a real-world scenario, this is where you would connect
    // to your legacy system. This could be via:
    // 1. A database call
    // 2. A SOAP/RPC request
    // 3. Reading from a message queue
    // 4. Executing a shell script that runs a COBOL program
    
    console.log('Calling legacy system with:', request);
    // const legacyResult = await callLegacyEndpoint(request);
    
    // For this example, we'll simulate the response we'd get back
    const simulatedLegacyResponse = {
      premium: 125.50,
      applied_discounts: 'LOYALTY,MULTI_POLICY',
    };
    
    // --- Transform the Legacy Response to the Modern Contract ---
    // The agent's final job is to map the old, clunky response 
    // to our new, clean API contract.
    const result: PremiumResult = {
      monthlyPremium: simulatedLegacyResponse.premium,
      annualPremium: simulatedLegacyResponse.premium * 12,
      discountsApplied: simulatedLegacyResponse.applied_discounts.split(','),
    };
    return result;
  }
}
This code does three powerful things:
Once you've written your agent, the .do platform takes over. With a single command, your wrapper is deployed as a resilient, scalable, and secure API endpoint. It's automatically versioned, discoverable, and billable within the .do ecosystem. You don't need to configure an API Gateway, manage containers, or provision servers.
Now the magic happens. Your once-inaccessible legacy logic for calculatePremium is a first-class citizen in your modern stack. You can now start building composable workflows:
You are now innovating on top of your legacy system, not in spite of it.
This wrapper approach delivers immediate and long-term value:
Don't let your legacy systems be an anchor. Start unlocking their trapped value today. With function.do, you can build a bridge to the future, one atomic function at a time.
Ready to breathe new life into your core business logic? Get started with function.do and turn your legacy code into a composable API.