Agent Evolution
The evolution module (buddy.agent.evolution) is an experimental optimization
layer that treats an agent's configuration as a genome and applies
genetic-algorithm operators — mutation, crossover, and fitness selection — to
search for better-performing variants.
Experimental
Evolution is an optimization scaffold, not a turnkey self-improvement system. It mutates configuration (instructions, temperature, personality traits) and scores variants from interaction data you supply. It does not retrain the underlying model. Treat results as candidate configurations to validate.
Availability is gated; check before using:
from buddy import check_feature
assert check_feature("evolution")
from buddy import AgentGenome, EvolutionStrategy, FitnessEvaluator
from buddy.agent.evolution import EvolutionaryMixin
The genome
AgentGenome is a Pydantic model encoding the tunable surface of an agent:
| Field group | Fields |
|---|---|
| Core | instructions, temperature, max_tokens, max_loops, reasoning_depth |
| Personality (0.0–1.0) | creativity, analytical_thinking, empathy, assertiveness, curiosity, patience |
| Tools | preferred_tools, tool_usage_strategy (conservative/balanced/aggressive) |
| Style | response_style, error_handling_strategy, interaction_style |
| Lineage | genome_id, generation, parent_genomes, fitness_score, mutation_history |
from buddy import AgentGenome
genome = AgentGenome(instructions="Be concise.", temperature=0.7)
# Produce a mutated child genome
child = genome.mutate(mutation_rate=0.2, mutation_strength=0.3)
print(child.generation, child.parent_genomes)
# Recombine two genomes
other = AgentGenome(instructions="Be thorough.", temperature=1.0)
offspring = genome.crossover(other, crossover_rate=0.5)
mutate() perturbs numeric and personality genes (and occasionally rewrites
instructions), while crossover() blends parents and combines their preferred
tools.
Fitness evaluation
FitnessEvaluator scores a genome from a list of interaction dictionaries. Each
interaction is a plain dict with optional keys such as response_time,
task_completed, error_occurred, task_type, and a feedback sub-dict with
accuracy and satisfaction.
from buddy import FitnessEvaluator
interactions = [
{"response_time": 1.2, "task_completed": True,
"feedback": {"accuracy": 0.9, "satisfaction": 0.8}},
{"response_time": 3.0, "task_completed": False, "error_occurred": True,
"feedback": {"accuracy": 0.4, "satisfaction": 0.3}},
]
metrics = FitnessEvaluator().evaluate(interactions)
print(metrics.overall_fitness) # weighted score in [0.0, 1.0]
FitnessMetrics.overall_fitness combines accuracy, response time, satisfaction,
completion rate, error rate, efficiency, adaptability, and consistency into a
single normalized score.
Evolution strategies
EvolutionStrategy enumerates the search families the layer is designed around:
| Member | Value |
|---|---|
EvolutionStrategy.GENETIC |
"genetic" |
EvolutionStrategy.DIFFERENTIAL |
"differential" |
EvolutionStrategy.PARTICLE_SWARM |
"particle_swarm" |
EvolutionStrategy.BAYESIAN |
"bayesian" |
Adding evolution to an agent
EvolutionaryMixin adds evolve(), crossover_with(), evaluate_fitness(),
should_evolve(), and auto_evolve() to an agent class. Compose it with
Agent so the mixin can consume its extra keyword arguments
(evolution_enabled, auto_evolution, evolution_threshold):
from buddy import Agent
from buddy.agent.evolution import EvolutionaryMixin
class EvolvingAgent(EvolutionaryMixin, Agent):
pass
agent = EvolvingAgent(evolution_enabled=True, auto_evolution=True)
fitness = agent.evaluate_fitness(interactions)
if agent.should_evolve():
evolved = agent.evolve() # returns a new agent built from a mutated genome
Note
evolve() raises ValueError unless evolution_enabled=True. Fitness
history needs at least five evaluations before should_evolve() will report
a decline. Always benchmark an evolved agent before promoting it.