Evolutionary Engine (Genetic Programming)
Relevant source files
The following files were used as context for generating this wiki page:- packages/core/src/improvement/gp/evolutionengine.ts
- packages/core/src/improvement/gp/Genome.ts
- packages/core/src/improvement/gp/operators/crossover/Crossover.ts
- packages/core/src/improvement/gp/operators/mutations/MutationCoordinator.ts
- packages/core/src/improvement/gp/Select.ts
- packages/core/src/improvement/gp/README.md
- packages/core/src/main.ts
- packages/core/README.md
- packages/core/src/utils/persistence/README.md
- apps/web/src/app/components/evolution/WorkflowEvolutionVisualization.tsx
- apps/web/scripts/inspect-evolution-run.ts
- packages/core/src/improvement/gp/tests/EvolutionEngine.test.ts
The Genetic Programming (GP) module is an evolutionary workflow system that uses Large Language Models (LLMs) to evolve autonomous AI agent workflows. It treats workflows as evolvable JSON-based data structures, which are optimized through genetic programming principles to discover effective agent collaboration patterns. This system addresses the manual effort required in designing multi-agent systems by automating the discovery and optimization of their workflows.
The system implements a μ+λ evolutionary strategy, where a population of workflows (genomes) competes for survival based on performance metrics like accuracy, cost, and latency. This approach combines traditional genetic programming with modern LLM capabilities for semantic understanding and modification of workflows. The entire process is managed by the EvolutionEngine, which orchestrates the evolutionary loop of evaluation, selection, reproduction, and survival.
Sources: packages/core/src/improvement/gp/README.md:3-5, README.md:8-11, packages/core/README.md:3-5, 23-26
Architecture Overview
The GP module is a core part of the lucky project's self-improving capabilities. It is designed as a modular system where the EvolutionEngine acts as the central orchestrator, coordinating various components to drive the evolutionary process.
The following diagram illustrates the high-level architecture of the Genetic Programming module.
This diagram shows the main components of the evolution engine and their interactions.
Sources: packages/core/src/improvement/gp/README.md:21-35
Execution Modes
The system can be run in two primary evolution modes, controlled via the --mode command-line argument: Iterative (Cultural) Evolution and Genetic Programming (GP). The main entry point in packages/core/src/main.ts orchestrates which mode to execute.
This flowchart shows the execution path based on the selected evolution mode.
Sources: packages/core/src/main.ts:83-96, 170-173, 332-335
Iterative (Cultural) Evolution
This mode focuses on improving a single workflow through iterative analysis and targeted modifications. It involves a loop of running the workflow, evaluating its performance, and applying AI-judged improvements. This process includes robust execution features like retries and circuit breakers to handle failures.
Sources: packages/core/src/main.ts:175-177, 219-222, packages/core/README.md:23-25
Genetic Programming (GP)
This mode uses a population-based approach. It maintains a pool of diverse workflows (genomes) and evolves them over multiple generations using genetic operators like crossover and mutation. This is the primary focus of this document.
Sources: packages/core/src/main.ts:337-340, packages/core/README.md:26-29
Core Components
Evolution Engine (evolutionengine.ts)
The EvolutionEngine is the central orchestrator of the GP process. It manages the entire lifecycle from population initialization to termination.
Key Responsibilities:
- Initialization: Creates an initial population of diverse workflows, either randomly from a goal description or based on a provided seed workflow.
- Evolution Loop: Manages the iterative cycle of evaluation, selection, and reproduction.
- Termination: Halts evolution based on criteria like reaching the maximum number of generations, budget limits (
maxCostUSD), or fitness stagnation. - Persistence: Interacts with
RunServiceto persist evolution runs, generations, and genomes to a database.
The core evolution loop follows these steps:
- Evaluate the fitness of the current population.
- Select parent genomes for reproduction.
- Create offspring through crossover and mutation.
- Combine the current population with the new offspring.
- Select the fittest individuals to survive to the next generation (μ+λ strategy).
- Check for termination conditions.
Sources: packages/core/src/improvement/gp/README.md:39-42, 51-64, packages/core/src/improvement/gp/evolutionengine.ts, packages/core/src/improvement/gp/tests/EvolutionEngine.test.ts:311-321
Genome (Genome.ts)
A Genome represents an individual workflow within the evolutionary process. It extends the base Workflow class, adding metadata essential for evolution, such as fitness, generation number, and lineage (parent IDs).
This diagram shows that the Genome implementation inherits from Workflow and contains evolutionary metadata.
Key properties of a WorkflowGenome:
evolutionId: A unique identifier for the genome instance.generation: The generation number in which the genome was created.parentIds: An array of parentevolutionIds, tracking its lineage.operation: The genetic operation that created this genome (e.g., 'crossover', 'mutation').fitness: The calculated performance score.
The Genome class provides static methods like createRandom to generate new genomes from a text goal using an LLM and toWorkflowConfig to convert a genome back into a standard WorkflowConfig for execution.
Sources: packages/core/src/improvement/gp/Genome.ts, packages/core/src/improvement/gp/README.md:66-83, packages/core/src/improvement/gp/tests/Genome.test.ts:203-214
Genetic Operators
Genetic operators are used to create new offspring from parent genomes, introducing variation into the population.
Crossover (Crossover.ts)
The crossover operator combines two parent workflows to create a new hybrid offspring. It uses an LLM to semantically merge the "best elements" from both parents, aiming to produce a functionally coherent and potentially superior workflow.
The process involves sending both parent workflow configurations to an LLM with a prompt instructing it to create a hybrid.
Sources: packages/core/src/improvement/gp/operators/crossover/Crossover.ts, packages/core/src/improvement/gp/README.md:87-105
Mutation (MutationCoordinator.ts)
The MutationCoordinator applies intelligent modifications to a single workflow genome. It supports various mutation types and intensities to introduce controlled changes.
| Mutation Type | Description |
|---|---|
PROMPT_REFINEMENT | Modifies task descriptions and system prompts within nodes. |
PARAMETER_ADJUSTMENT | Adjusts parameters for nodes or tools. |
STRUCTURAL_CHANGE | Adds, removes, or reorganizes nodes in the workflow graph. |
TOOL_SUBSTITUTION | Changes the tools assigned to a node. |
Mutations can be applied with different intensities (LIGHT, MEDIUM, HEAVY), allowing for a range from minor tweaks to substantial structural alterations. The system can also perform multi-type parallel mutations and adapt the intensity based on population dynamics.
Sources: packages/core/src/improvement/gp/operators/mutations/MutationCoordinator.ts, packages/core/src/improvement/gp/README.md:107-130, packages/core/src/improvement/gp/tests/Mutations.test.ts
Selection (Select.ts)
The selection strategy determines which genomes from the current generation will become parents for the next. The system uses Tournament Selection with Elitism.
- Tournament Selection: A number of genomes (defined by
tournamentSize) are randomly selected from the population. The one with the best fitness becomes a parent. This process is repeated until the required number of parents is chosen. - Elitism: A small number of the very best genomes from the current population (defined by
eliteSize) are preserved and passed directly to the next generation without modification, ensuring that top-performing solutions are not lost.
The selection process is configured via SelectionConfig, which includes parameters like tournamentSize, eliteSize, crossoverRate, and mutationRate.
Sources: packages/core/src/improvement/gp/Select.ts, packages/core/src/improvement/gp/README.md:132-155
Configuration
The EvolutionEngine is highly configurable. A default configuration can be created and customized.
| Parameter | Type | Description | Default |
|---|---|---|---|
populationSize | number | Number of genomes in the population. | 20 |
generations | number | Maximum number of generations to run. | 10 |
eliteSize | number | Number of top genomes to carry over to the next generation. | 2 |
tournamentSize | number | Number of participants in a selection tournament. | 3 |
crossoverRate | number | Probability of performing crossover. | 0.6 |
mutationRate | number | Probability of performing mutation. | 0.4 |
maxCostUSD | number | Budget limit in USD for the entire run. | 100 |
stagnationGenerations | number | Number of generations without fitness improvement before stopping. | 5 |
Sources: packages/core/src/improvement/gp/README.md:183-196, packages/core/src/improvement/gp/evolutionengine.ts
Persistence and Tracking
The evolutionary process is tightly integrated with a persistence layer, primarily managed by RunService. This allows for detailed tracking of evolution runs, generations, and individual genomes.
Database Schema
The persistence layer relies on a database schema to store all evolutionary data, enabling lineage tracking and post-run analysis.
This ER diagram shows the relationships between evolution runs, generations, and workflow versions/invocations.
Sources: packages/core/src/utils/persistence/README.md:30-75, apps/web/scripts/inspect-evolution-run.ts:13-39
Run Inspection
Evolution runs can be inspected programmatically using scripts like inspect-evolution-run.ts. This script fetches run data, generation bundles, and invocation details from the API to provide a summary of the run's progress, costs, and overall performance.
Sources: apps/web/scripts/inspect-evolution-run.ts
Visualization
The apps/web application includes components for visualizing the evolutionary process. WorkflowEvolutionVisualization.tsx renders charts and statistics about an evolution run, including accuracy timelines and success/failure distributions. This provides a user-friendly way to understand the performance progression of a workflow over generations.
Sources: apps/web/src/app/components/evolution/WorkflowEvolutionVisualization.tsx, apps/web/src/features/evolution/lib/results/README.md:3-6
Summary
The Evolutionary Engine provides a powerful, automated system for optimizing AI agent workflows using genetic programming. By representing workflows as Genomes and applying LLM-powered genetic operators like crossover and mutation, it can explore a vast solution space to find effective collaboration patterns. The engine is highly configurable, supports robust execution, and includes comprehensive persistence and tracking, making it a cornerstone of the project's self-improving architecture.
Sources: README.md:8-11, packages/core/README.md:26-29