Skip to main content

System Architecture

The deployment system uses a plugin-based architecture where strategies are self-contained packages that can be added without modifying core code.
ComponentModuleRole
DeploymentFactoryfactory.pyOrchestrates selection, adaptation, and runner creation
SelectorAgentselector/agent.pyLLM-based strategy selection
AdapterAgentadapter/agent.pyCode transformation for target platform
StrategyRegistrystrategies/base.pyAuto-discovery of strategy plugins
Runnerstrategies/*/runner.pyInfrastructure-specific execution
DeployedSoftwaresoftware.pyUnified wrapper for user interaction

Module Breakdown

Directory Structure

src/deployment/
├── __init__.py              # Public exports
├── base.py                  # Data models and abstractions
├── factory.py               # DeploymentFactory orchestration
├── software.py              # DeployedSoftware unified wrapper
├── selector/
│   ├── agent.py             # SelectorAgent (strategy selection)
│   ├── selection_prompt.md  # LLM prompt template
│   └── correction_prompt.md # Error correction prompt
├── adapter/
│   ├── agent.py             # AdapterAgent (code transformation)
│   ├── adaptation_prompt.txt # LLM prompt template
│   └── validator.py         # Adaptation validation
└── strategies/
    ├── base.py              # Runner ABC, StrategyRegistry
    ├── README.md            # Strategy development guide
    ├── local/               # Local strategy plugin
    ├── docker/              # Docker strategy plugin
    ├── modal/               # Modal strategy plugin
    ├── bentoml/             # BentoML strategy plugin
    └── langgraph/           # LangGraph strategy plugin

Core Components

DeploymentFactory (factory.py)

The orchestrator that manages the full deployment pipeline. Responsibilities:
  • Coordinate selection, adaptation, and runner creation
  • Handle strategy validation
  • Create unified Software instances
Flow:
# Phase 1: Selection
if strategy == DeployStrategy.AUTO:
    setting = cls._select_strategy(config, strategies)
else:
    setting = cls._create_setting(strategy)

# Phase 2: Adaptation  
adaptation = cls._adapt_repo(config, setting, strategies)

# Phase 3: Runner creation
runner = cls._create_runner(config, setting, adaptation)

# Phase 4: Wrap in unified interface
return DeployedSoftware(config=config, runner=runner, info=info)

SelectorAgent (selector/agent.py)

LLM-based strategy selection that analyzes code and chooses the optimal deployment target. Responsibilities:
  • Gather selector instructions from all strategies
  • Query coding agent to analyze repository
  • Return DeploymentSetting with chosen strategy
MethodInputOutput
select()SolutionResult, optional allowed_strategiesDeploymentSetting
explain()SolutionResultstr human-readable explanation

AdapterAgent (adapter/agent.py)

Code transformation and deployment using coding agents. Responsibilities:
  • Create adapted workspace (copy of original)
  • Load adapter instructions for target strategy
  • Run coding agent to transform code
  • Extract endpoint URL and run interface from output
MethodInputOutput
adapt()SolutionResult, DeploymentSettingAdaptationResult
Key Output Extraction: The adapter looks for special XML tags in the coding agent’s output:
<run_interface>{"type": "function", "module": "main", "callable": "predict"}</run_interface>
<endpoint_url>https://my-app.modal.run</endpoint_url>

StrategyRegistry (strategies/base.py)

Auto-discovery system for deployment strategies. Responsibilities:
  • Scan strategies/ directory on startup
  • Load configuration and instructions for each strategy
  • Provide access to strategy metadata and runner classes
MethodInputOutput
list_strategies()optional allowed: List[str]List[str]
get_strategy()name: strDeployStrategyConfig
get_runner_class()name: strtype (Runner subclass)

Runner (Abstract Base Class)

Infrastructure-specific execution handler.
class Runner(ABC):
    @abstractmethod
    def run(self, inputs: Union[Dict, str, bytes]) -> Any:
        """Execute with inputs and return result."""
    
    @abstractmethod
    def stop(self) -> None:
        """Stop and cleanup resources."""
    
    @abstractmethod
    def is_healthy(self) -> bool:
        """Check if runner is healthy and ready."""
RunnerStrategyExecution Method
LocalRunnerlocalPython importlib + function call
DockerRunnerdockerHTTP requests to container
ModalRunnermodalmodal.Function.remote()
BentoMLRunnerbentomlHTTP to BentoCloud/local
LangGraphRunnerlanggraphLangGraph Cloud API

DeployedSoftware (software.py)

Unified wrapper that users interact with.
class DeployedSoftware(Software):
    def run(self, inputs) -> Dict[str, Any]:
        """Execute and return normalized response."""
        
    def stop(self) -> None:
        """Stop the software and cleanup."""
        
    def logs(self) -> str:
        """Get execution logs."""
        
    def is_healthy(self) -> bool:
        """Check if software is running."""

Data Models

DeployConfig

@dataclass
class DeployConfig:
    solution: SolutionResult  # The built solution
    env_vars: Dict[str, str]  # Environment variables
    timeout: int = 300        # Execution timeout (seconds)
    coding_agent: str = "claude_code"  # Agent for adaptation

DeploymentSetting

@dataclass
class DeploymentSetting:
    strategy: str              # "local", "docker", "modal", etc.
    provider: Optional[str]    # Cloud provider name
    resources: Dict[str, Any]  # CPU, memory, GPU requirements
    interface: str             # "function", "http", etc.
    reasoning: str             # Why this was selected

AdaptationResult

@dataclass
class AdaptationResult:
    success: bool
    adapted_path: str           # Path to adapted repo (copy)
    run_interface: Dict[str, Any]  # How to call .run()
    files_changed: List[str]
    error: Optional[str]

Strategy Plugin Architecture

Each strategy is a self-contained directory:
strategies/{name}/
├── config.yaml              # Strategy configuration
├── selector_instruction.md  # When to use this strategy
├── adapter_instruction.md   # How to adapt code
├── runner.py                # Runtime execution class
└── __init__.py              # Exports

config.yaml Structure

name: modal
provider: modal
interface: function

runner_class: ModalRunner

default_resources:
  gpu: T4
  memory: 16Gi

run_interface:
  type: modal
  function_name: predict

How Strategies Are Discovered

  1. On import, StrategyRegistry scans strategies/ directory
  2. Each subdirectory with selector_instruction.md AND adapter_instruction.md is registered
  3. Runner classes are lazy-loaded from runner.py when needed
Adding a new strategy is just adding a directory - no code changes required in the core system.

Next Steps