Agent Genome is an interactive browser exhibit built around a simple question: how do you explain evolving agents without asking people to read logs or trust an aggregate chart?
The answer is a small, visual population. Forty glowing organisms move across a sparse resource-and-hazard field. Every organism has an explicit 1–10 genome. Visitors can inspect an organism’s traits, current intent, recent reflection, fitness, memory, and lineage; when the generation ends, they see selection, inherited strategies, and mutation produce the next cohort.
The product decision: reveal the mechanism
This is intentionally neither a chat application nor a game. The user should be able to answer three questions almost immediately:
- What are the organisms doing?
- Why does one behave differently from another?
- How does a generation change the next one?
The dark field, energy sources, hazards, trails, specimen panel, and full-screen generation transition are all designed to expose that causal chain rather than decorate it.
A monorepo with deliberate boundaries
Agent Genome uses a Turborepo workspace. This is not architectural theatre: genetics, simulation, memory, and rendering should evolve independently.
apps/web Next.js UI, Canvas renderer, local interaction state
packages/genome Trait types, clamping, crossover, mutation
packages/simulation Parent selection and offspring construction
packages/core Structured memory capped at 20 records
packages/agents Goal vocabulary
packages/langgraph Real LangGraph reflection workflow and provider adapters
packages/ui Genome colour tokens
packages/shared Shared constants
The web app owns transient visual positions and trails. Selection and crossover belong in pure TypeScript modules. This means a future React Three Fiber scene, headless simulation runner, or replay UI can reuse the same genetics API.
A readable genome
Every trait is a whole number between 1 and 10. That range is a product choice: a visitor can understand it instantly, a bar chart stays useful, and a mutation is easy to describe.
export type GenomeTrait =
| 'planning' | 'memory' | 'risk' | 'curiosity'
| 'cooperation' | 'explorationRadius'
| 'toolUsage' | 'reflectionFrequency';
export type Genome = Record<GenomeTrait, number>;
export const clampTrait = (value: number) =>
Math.max(1, Math.min(10, Math.round(value)));
Bound the values at the domain edge, not in the renderer. That lets every downstream consumer assume genome data is valid.
Crossover and mutation without a black box
For each trait, a child inherits a value from one parent, then has a small chance of a one-step mutation:
export function crossover(a: Genome, b: Genome, mutationRate = 0.08): Genome {
const child = {} as Genome;
for (const key of Object.keys(a) as GenomeTrait[]) {
const inherited = Math.random() > 0.5 ? a[key] : b[key];
const mutation = Math.random() < mutationRate
? (Math.random() > 0.5 ? 1 : -1)
: 0;
child[key] = clampTrait(inherited + mutation);
}
return child;
}
Parent selection takes the highest-fitness segment of the population. It is intentionally simpler than a research-grade evolutionary system because inspectability is the point.
const elite = [...population]
.sort((left, right) => right.fitness - left.fitness)
.slice(0, Math.ceil(population.length * 0.35));
const parentA = elite[index % elite.length];
const parentB = elite[(index * 7 + 3) % elite.length];
Later versions can add tournament selection, novelty search, or seeded randomness and replay. They should retain a visible explanation for every evolutionary event.
The simulation is autonomous; LLM reflection is optional
The project names a cognition loop even though the initial exhibit uses deterministic browser-safe behaviour:
packages/langgraph implements a LangGraph flow behind the optional reflection action. LangChain adapters connect it to Ollama, LM Studio/OpenAI-compatible endpoints, OpenAI, and Anthropic. A model-backed reflection node looks at structured recent outcomes and proposes a bounded change—for example, lowering risk after costly exploration. It cannot rewrite simulation code, bypass trait limits, or issue arbitrary actions.
The simulation itself does not need a provider or API key. Its fitness is calculated from live world events: resources collected, hazard avoidance, proximity-based cooperation, and exploration. This preserves an important distinction: memory records an organism’s recent experience; evolution changes the strategy distribution across a population. LLM reflection is an optional, evidence-constrained layer on top of that loop—not the source of the simulation’s behaviour.
The reflection action sends the selected organism’s goal, current fitness, structured memory, and genome to the selected provider. It returns strict JSON containing one sentence and permitted bounded trait changes. There is no tool access, code execution, RAG, vector database, or persistent provider conversation.
Why the initial renderer is Canvas 2D
Three.js and React Three Fiber are listed as an upgrade path, but Canvas 2D is the right first rendering layer. It keeps the 40-organism field inexpensive while still providing glow, trails, particles, resources, hazards, and selection feedback.
The animation loop updates motion imperatively while React handles interface state:
a.vx += Math.cos(angle) * 0.004 * (a.genome.curiosity / 5);
a.vy += Math.sin(angle) * 0.004 * (a.genome.curiosity / 5);
a.vx *= 0.97;
a.vy *= 0.97;
a.x = Math.max(3, Math.min(97, a.x + a.vx * speed * dt * 50));
This is expressive visual motion, not a physics engine. Keeping it light gives the project a clear 60 FPS target without shaders or high-frequency React state updates.
Run and extend it
npm install
npm run dev --workspace=@agent-genome/web
npm run build --workspace=@agent-genome/web
The highest-value next additions are richer resource respawning and cooperation events, mutation replay, generation comparison, JSON genome snapshots, reduced-motion and keyboard support, deterministic seeds, and a WebGL renderer that consumes the same simulation contract.
The guiding principle is simple: make every change in the population explainable to the person watching it.
Code & more: https://www.dailybuild.xyz/project/212-agent-genome



Top comments (0)