TL;DR
Today’s AI agents are hand-designed: a human picks the prompts, tools, and workflow, and the agent can’t get smarter than its designer’s next release. In 2007, Jürgen Schmidhuber proposed the “Gödel Machine” — an AI that rewrites its own code, but only when it can mathematically prove the rewrite helps. That proof requirement made it unbuildable in practice. The Darwin Gödel Machine (DGM) swaps the impossible proof for something cheaper and more honest: try the rewrite, measure it on a coding benchmark, and keep it if the number goes up. It borrows its search strategy from Darwinian evolution — instead of always mutating the current best agent, it keeps a growing archive of every viable agent it has ever produced and can branch off any of them, including weaker ones that might be sitting on an idea worth building on later. Starting from one simple agent with a bash tool and a file editor, the DGM lifts its own score from 20.0% to 50.0% on SWE-bench and from 14.2% to 30.7% on Polyglot (full benchmark) — fully automatically, with no human touching the agent’s code in between generations. The gains transfer to models, benchmarks, and languages the DGM never optimized against, which is the paper’s strongest evidence that it discovered real engineering improvements rather than benchmark tricks.
Problem & Motivation
Every LLM-based coding agent you’ve built or used — ReAct loops, tool-calling scaffolds, retrieval-augmented workflows — has a ceiling: it can only be as good as the human who assembled its prompts, tools, and control flow. When someone wants a better agent, a person sits down, reads failure logs, and manually adds a feature (a better diff tool, a retry loop, a context-summarizer). That’s slow, doesn’t scale, and caps the system’s capability at the ingenuity of its designers.
Schmidhuber’s Gödel Machine (2007) imagined the fix: an AI that can rewrite any part of itself, but is only allowed to apply a rewrite once it has a formal proof that the change is net beneficial. That’s a beautiful idea and a dead end in practice — for any realistic software system, you cannot prove in advance that adding a tool, changing a prompt, or restructuring a workflow will help. Whether a new testing tool helps or confuses the agent depends on the model’s training, the task distribution, dozens of interacting factors that resist formal proof.
More recent “meta-learning” approaches (e.g., ADAS) sidestep the proof problem by testing changes empirically instead — but they still use a fixed, hand-built meta-agent whose only job is to propose and evaluate new downstream agents. The meta-agent itself never gets better. Its design ability is frozen at whatever the human who wrote it gave it, so gains taper off once the easy ideas are exhausted (the paper actually reproduces this as a baseline and shows exactly that plateau).
The gap DGM targets: a system where getting better at the target task (writing code) is the same skill as getting better at improving itself — so progress compounds instead of flatlining.
What’s New (Core Contribution)
- A self-referential loop, not a fixed meta-agent. The same coding agent that solves benchmark tasks is also the one that edits its own codebase. Before: a separate, frozen “designer” model proposes changes to a “worker” agent (ADAS-style), so the designer’s skill never improves. Now: there is no separate designer — improving at coding directly improves the agent’s ability to make its next self-modification, because self-modification is a coding task on its own repository.
- Empirical validation replaces formal proof. Before: Gödel Machine required a mathematical proof that a rewrite helps (impossible in practice, so never built). Now: run the candidate on a coding benchmark and keep it only if the score improves. This is the concession that makes the Gödel Machine idea buildable at all — at the cost of losing the theoretical guarantee.
- An open-ended archive instead of hill-climbing. Before: prior self-improving-agent work (Robeyns et al. 2025; Yin et al. 2024; Zelikman et al. 2024b) always mutates the single most-recent or best-known version — classic hill-climbing, which gets stuck once the best-so-far agent is in a local dead end. Now: DGM keeps every agent that still works, in a growing tree, and can sample a parent from anywhere in that tree — including agents that scored worse than their siblings but might carry a feature (a “stepping stone”) that only pays off several generations later.
- Demonstrated generalization, not just benchmark climbing. The paper doesn’t just report a rising score — it swaps in different foundation models after the fact, evaluates on a completely different benchmark, and holds out entire programming languages, and shows the discovered improvements transfer in all three cases. That’s evidence the DGM is finding general engineering practices, not exploiting quirks of one benchmark.
How It Works (Technically)
The moving parts. A “coding agent” here is nothing exotic: a git repository of Python code, powered by a frozen pretrained foundation model (Claude 3.5 Sonnet for SWE-bench, o3-mini for Polyglot evaluation), with exactly two tools — a bash tool to run shell commands, and an editor tool to view/create/edit files. Given a repo, a problem description, and a test description, the agent’s forward() function loops, calling tools until it produces a patch. That’s the entire starting point — deliberately minimal, so that anything sophisticated the final agent does had to be discovered, not hand-installed.
The loop, one iteration at a time.
- Select parents. Pick k agents from the archive (k=2 for SWE-bench, k=4 for Polyglot, run in parallel) using a weighted random draw described below.
- Diagnose. Feed the parent’s own source code plus its recent failure logs (which GitHub issue it tried, what patch it produced, what the hidden tests said) to a separate strong reasoning model (o1 in this implementation). That model is explicitly instructed to propose one improvement that is general — not a fix for that specific GitHub issue — and to phrase it as a GitHub-issue-style problem statement.
- Self-modify. Hand that generated “issue” back to the parent agent, pointed at its own repository instead of a target repo. The parent runs its normal bash/editor tool loop and produces a patch — but the patch changes the agent’s own code (a new tool, a smarter prompt, a different control flow).
- Validity check. If the patched agent no longer compiles or can no longer edit a codebase at all, discard it — a dead branch can’t produce any further descendants, so there’s no point keeping it.
- Evaluate. Run the surviving candidate on a staged subset of a coding benchmark: first 10 tasks (just to confirm basic code-editing ability), then 50–60 tasks, and only if it scores above ~40% and ranks in the archive’s top two does it get the expensive full 200-task SWE-bench evaluation. This staging is what makes 80 generations financially possible — full evaluation on every candidate would be prohibitively expensive.
- Archive. Add the (code, score) pair to the archive. Go back to step 1.
Why “select parents” is the clever bit. DGM doesn’t just mutate the best agent (that’s hill-climbing, and it’s literally one of the paper’s own baselines — it loses). Instead, for every archived agent still short of a perfect score, it computes a selection weight from two ingredients:
- A sigmoid-scaled performance term:
s = 1 / (1 + exp(-λ(score - α₀))), with λ=10 and α₀=0.5. Plain English: this isn’t just “use raw score as weight” — the sigmoid sharply separates “clearly above 50%” agents from “clearly below 50%” agents, so being confidently good matters more than a few extra points near the middle. Think of it as a soft threshold rather than a straight line. - A novelty bonus:
h = 1 / (1 + num_working_children). Plain English: an agent that has already produced one or more surviving children gets discounted, because it’s been “tried” already. An agent with zero children so far gets the full bonus. This is what keeps the DGM from just hammering on the current champion forever — it actively favors under-explored branches.
Multiply the two (w = s·h), normalize across all eligible agents into a probability distribution, and sample k parents from it (with replacement). Crucially, every agent — even a weak, heavily-bred one — keeps a nonzero probability forever. Nothing is ever permanently locked out of being a parent again; that’s the literal mechanism behind “open-ended.”
Selection weights for five hypothetical archive agents, computed from the paper's own formula (λ=10, α₀=0.5). Note agent #4: a low score but zero children still earns a real shot at being picked — that's what stops the search from only ever refining the current champion.
A worked trace. Imagine agent #8 in the archive scored 38% and has zero children so far — it gets a healthy weight (high novelty bonus, moderate confidence). It’s sampled as a parent. Its own evaluation logs show it kept truncating large files it needed to edit. The diagnosis model reads that and proposes: “add line-range-based file viewing/editing instead of always reading the whole file.” That’s handed to agent #8 as a self-directed task; it edits its own tools/editor.py to add ranged viewing. The patch survives the validity check, gets staged through 10 → 60 → 200 tasks, and enters the archive as agent #23 with, say, a 44% score and one more “generation” of children still possible. This is, almost verbatim, one of the real improvements the paper reports the DGM discovering on its own (Figure 3).
A note on the assumption underneath everything. The whole scheme only works because self-modification is itself a coding task performed on the agent’s own repository. That’s why a benchmark score is allowed to stand in for “ability to self-improve” — the paper is betting that an agent which is measurably better at solving GitHub issues in general is also measurably better at solving the “issue” of improving its own code. That’s an assumption, not a proof (which is exactly the point — the DGM gave up on proof).
Safety scaffolding (worth knowing, not a core mechanism). Every execution and self-modification happens inside a sandboxed, time-limited environment with no ability to touch the host or the internet; the archive gives a complete, auditable lineage of every code change. This matters because you’re literally letting an LLM rewrite and re-run its own code unsupervised across 80 generations.
Architecture & data flow
flowchart TD
ARCH[("Archive: every viable agent<br/>(code, score, #children)")] -->|weighted sample, eq. 1-7| SEL[Select k parents]
SEL --> DIAG["Diagnose: strong reasoning model reads<br/>parent's own code + failure logs,<br/>proposes ONE general fix"]
DIAG --> MOD["Parent agent edits its OWN codebase<br/>to implement the fix (same bash+editor tools)"]
MOD --> CHECK{Still compiles and<br/>can edit code?}
CHECK -->|no| DISCARD[Discard candidate]
CHECK -->|yes| EVAL["Evaluate on staged benchmark subset<br/>10 -> 50/60 -> 200 tasks"]
EVAL --> ARCH
sequenceDiagram participant Arc as Archive participant P as Parent agent (its own code) participant D as Diagnosis model (o1) participant C as Same coding agent (Claude) participant B as Benchmark harness Arc->>P: sampled as parent (score-weighted x novelty-weighted) P->>D: own source code + own recent failure logs D-->>P: ONE general improvement, phrased as a GitHub issue P->>C: "solve this issue" -- except the repo IS its own repo C-->>P: patch = new agent version P->>B: staged evaluation (10 -> 60 -> 200 tasks) B-->>Arc: score; keep if it still edits code, else discard
A schematic DGM archive tree (styled after the paper's Figure 3, not the exact run data). Sphere size and color track benchmark score; edges show which agent self-modified into which. Notice the dip at generation 2 — a lower-scoring branch — that the archive keeps alive anyway, and which later feeds the run's best-performing lineage. That's the concrete payoff of not doing pure hill-climbing. Drag to orbit.
The algorithm, simplified
# core DGM loop: Algorithm 1 + parent-selection (eqs. 1-7), simplified
import math, random
LAMBDA, ALPHA0 = 10, 0.5 # sigmoid sharpness, midpoint "good" score
def select_parents(archive, k):
eligible = [a for a in archive if a.score < 1.0] # room left to improve
weights = []
for a in eligible:
s = 1 / (1 + math.exp(-LAMBDA * (a.score - ALPHA0))) # confidently-good bonus
h = 1 / (1 + a.num_working_children) # underexplored bonus
weights.append(s * h)
total = sum(weights)
probs = [wt / total for wt in weights]
return random.choices(eligible, weights=probs, k=k) # sample WITH replacement
def dgm(base_agent, benchmark, iterations, k=2):
archive = [Agent(code=base_agent, score=evaluate(base_agent, benchmark))]
for t in range(iterations):
for parent in select_parents(archive, k):
fix = diagnose(parent.code, parent.last_run_logs) # o1: ONE general improvement
child_code = parent.self_modify(fix) # agent edits its OWN repo
if not can_still_edit_code(child_code):
continue # dead branch, discard
child_score = evaluate(child_code, benchmark) # staged 10->60->200 tasks
archive.append(Agent(code=child_code, score=child_score, parent=parent))
parent.num_working_children += 1
return archive
Built on Prior Work
| Prior idea | What it gave | What this paper changes |
|---|---|---|
| Gödel Machine (Schmidhuber, 2007) | The concept of a provably-beneficial self-rewriting AI | Drops the formal-proof requirement, substitutes empirical benchmark validation — trading a theoretical guarantee for something buildable today |
| ADAS / meta-learning agent design (Hu et al., 2025) | Automated agent design via a fixed meta-agent that proposes and tests downstream agents | Removes the separate, frozen meta-agent entirely — the agent being designed and the agent doing the designing are the same system, so the “designer” improves too |
| Quality-diversity & open-endedness (Lehman & Stanley 2011; Go-Explore, Ecoffet et al. 2019; Clune’s AI-GAs, 2019) | The principle of keeping a diverse archive of “interesting” solutions as stepping stones instead of only tracking the current best | Applies the archive/stepping-stone idea to LLM coding agents specifically, using an FM-driven diagnose-then-edit step as the “mutation” operator instead of a genetic operator |
| Darwinian evolution (as an analogy, not a citation) | Select → mutate → keep-if-fit, with no need to prove a mutation beneficial in advance | Direct mapping: archive = population, self-modify = mutation, benchmark score = fitness, failed compile/edit = natural selection removing the unfit |
| Tool-use LLM agents (Anthropic tool use, ReAct-style loops) | The bash-tool + file-editor-tool pattern for solving coding tasks | This same pattern becomes both the artifact being evolved and the mechanism doing the evolving — the tool loop edits itself, not just target repos |
Results & Evidence
Headline numbers. Over 80 iterations, the DGM lifted its own coding agent from 20.0% → 50.0% on SWE-bench (Verified), and from 14.2% → 30.7% on the full Polyglot benchmark (14.0% → 38.0% on the 50-task subset used to drive the search). The final SWE-bench agent is roughly on par with the best checked open-source SoTA solution — human-engineered by expert teams — though it still trails closed-source frontier solutions.
Ablations that isolate the two mechanisms. Against “DGM w/o self-improve” (the ADAS-style fixed-meta-agent baseline), the DGM pulls ahead because the baseline’s early gains taper off quickly once the frozen meta-agent runs out of easy ideas. Against “DGM w/o open-ended exploration” (archive removed, always mutate the latest agent), the DGM pulls ahead because a single bad self-modification in the no-archive baseline can block all future progress — there’s nothing to fall back to. Both baselines are real code paths the authors ran, not hypotheticals (Appendix A.1).
Transfer evidence (the strongest part of the paper). Swap the foundation model after the DGM run finished: on SWE-bench, o3-mini goes from 23.0%→33.0% and Claude 3.7 Sonnet from 19.0%→59.5% when driven by the DGM-discovered agent instead of the base agent — despite the DGM having only ever been run with Claude 3.5 Sonnet. Swap the benchmark: an agent evolved purely on SWE-bench scores 28.9% on a never-seen Polyglot (vs. the base agent’s 14.2%), and vice versa (24.5% vs. 20.0%). Hold out languages: an agent evolved only on Python Polyglot tasks still transfers respectably to C++/Rust/Go/Java/JS tasks it never trained against, beating both the base agent and the hand-built Aider baseline. This cross-cutting generalization is the evidence that the improvements are real engineering practices (finer-grained editing, retry logic, self-consistency via multiple candidate patches) rather than memorized quirks of one benchmark’s task distribution.
What the evidence does not establish.
- The “diagnose” step still leans on a separate, fixed, strong reasoning model (o1) to read logs and propose fixes — the loop isn’t fully self-contained yet; the authors call this an implementation choice, not a fundamental limit, but it hasn’t been tested without it.
- Cost: one SWE-bench run costs roughly $22,000 and about two weeks of wall-clock time (vs. ~$10,000 for either baseline). This is nowhere near cheap or fast enough to run casually.
- The open-ended exploration machinery itself (the archive, the sigmoid/novelty selection formula, λ and α₀) is fixed and hand-designed by the authors — it is explicitly not something the DGM can modify about itself, so a meaningful chunk of “how do I explore” is still human-authored.
- The diagnosis prompt is fed the private ground-truth test results (though the coding agent solving new tasks never sees them). The authors report manually inspecting logs for hard-coding/overfitting and found none, and point to the transfer results as corroborating evidence — but this is a self-reported audit, not an independent one.
- Never surpasses closed-source frontier SWE-bench agents built by full-time expert teams, so this is evidence of “automates a competent human engineer,” not “beats the best humans.”
How You’d Use It
Don’t plan on running “a self-modifying production agent” next quarter — the compute cost ($22K+/run), the sandboxing infrastructure, and the need for a benchmark you actually trust as a fitness signal make this research-grade, not shippable. But three pieces of the mechanism are usable today, at a much smaller scale, on any agent build you’re already maintaining:
- Your workflows — the parent-selection formula is a general-purpose search pattern, independent of coding agents. Anywhere you’re iterating on prompts/tools/workflows (a support bot, an extraction pipeline, a RAG system) and keeping a handful of past variants around, you can literally reuse
sigmoid(score) × 1/(1+children)as a “what do I try next” heuristic instead of always tweaking whatever currently scores highest. It’s ~15 lines of Python and it directly encodes “favor good-but-underexplored ideas over exhausted ones.” - Your harness — the diagnose-then-fix recipe is a concrete pattern for self-tuning internal tooling. Feed a strong reasoning model your own pipeline’s code plus its recent failure logs, ask for one general (not case-specific) fix, phrase it as a ticket, hand it to a coding agent pointed at your own repo. This is a cheap version of the DGM loop you could run nightly against your own ingestion scripts or any automation you maintain, without needing an 80-generation archive.
- Your business — the governance story matters as much as the capability story. Section 5’s insistence on sandboxing, time limits, and a fully auditable lineage of every AI-authored change is exactly the kind of “we let AI touch production code, here’s how we made it safe and traceable” case you’ll need to make internally before anyone signs off on a self-modifying automation, even a small one.
Build Your Own (Minimal Recipe)
Components:
- A base coding agent: one LLM + two tools (shell execution, file view/edit) + a single prompt taking
{repo, problem_statement, tests}. If you’ve built an ARC-style agent with a shell tool, you already have this. - A small, cheap benchmark you trust — don’t reach for SWE-bench for a toy version (too expensive); use 10-20 self-contained coding-kata-style tasks with unit tests you control.
- An archive: literally a list or table of
(agent_code_snapshot, score, parent_id, num_working_children). - The parent-selection function (the ~15-line snippet above) — cheap to build, does most of the interesting work.
- A “diagnose” step: a strong reasoning model reads the current agent’s code plus its failure logs on 1-2 benchmark tasks, and must propose one improvement general enough to not be issue-specific — copy this instruction verbatim, it’s load-bearing.
- A “self-modify” step: hand that proposal to the same coding agent, pointed at a sandboxed copy of its own repo (a fresh git worktree or container per candidate — never the live one), capture the diff.
- A validity gate: does the patched agent still parse and still edit code at all? If not, discard without wasting eval budget on it.
- Loop: select → diagnose → self-modify → validity-gate → evaluate → append, for N iterations.
The genuinely hard parts:
- Sandboxing self-modifying code safely — every candidate needs a real, isolated execution environment; letting an LLM-authored patch run against your host is the mistake to not make.
- A benchmark that’s a decent proxy and cheap enough for dozens of generations — copy the paper’s staged-gating trick (cheap 10-task smoke test → moderate 50-task check → expensive full eval only for the top performers) or you’ll burn budget evaluating obviously-dead candidates.
- Keeping fixes general, not task-specific — nothing stops a coding agent from quietly special-casing the exact benchmark task it just failed instead of building a genuinely reusable capability; the “not specific to any particular issue” instruction and periodic manual spot-checks are your only defense.
Reach for: Claude Sonnet or an o-series/GPT reasoning model for both the diagnosing role and the coding-agent role; Docker + git worktrees for per-candidate isolation; pytest (or your benchmark’s own harness) for scoring.
How to Improve It
- Make the diagnosis step self-referential too. Right now a separate, frozen model (o1) reads logs and proposes fixes — that’s itself a hand-picked, unevolved component sitting inside an otherwise self-improving loop. Let the archive evolve which model/prompt does the diagnosing.
- Let the open-ended exploration mechanism itself evolve. The archive management and the sigmoid/novelty parent-selection formula (λ=10, α₀=0.5) are fixed by the authors and explicitly not self-modifiable — flagged by the paper itself as future work. A DGM that could also improve how it explores would close one more layer of the self-reference.
- Fold a safety/robustness objective into the fitness function, not just ”% of benchmark tasks solved” — e.g., penalize unsafe tool use or reward interpretable diffs, so evolution optimizes for more than raw score. The paper gestures at this (a Constitutional-AI-style extension) but doesn’t implement it.
- Cut compute cost with cheaper pre-filters. The staged 10→60→200 evaluation already saves a lot, but a static-analysis or smoke-test pre-filter before spending any API budget on the 10-task stage — or routing less-promising branches to a cheaper model — would stretch the same budget across more generations.
- Co-evolve the task distribution alongside the agent, instead of a fixed benchmark — the authors name this directly as the move toward “true” open-endedness (per Faldor et al., 2025): if the benchmark itself keeps generating novel, harder tasks, the system can’t plateau by simply solving the fixed task set it was handed.
Glossary
- Gödel Machine — a theoretical self-rewriting AI (Schmidhuber, 2007) that may only change itself once it has a formal proof the change is beneficial; never built because such proofs are essentially impossible for real systems.
- Self-referential — the system doing the improving and the system being improved are the same system.
- Archive (open-endedness / quality-diversity) — a growing collection of past solutions kept around as potential “stepping stones,” instead of only tracking and overwriting the single current best.
- Open-ended exploration — search that keeps producing novel, still-viable variants indefinitely, deliberately allowed to branch from lower-scoring solutions because they may lead somewhere better later.
- Quality-diversity (QD) — an optimization family that seeks many good-and-different solutions rather than a single best one; contrast with hill-climbing.
- Hill-climbing — always mutating from the current best (or most recent) solution only; the DGM’s “w/o open-ended exploration” baseline does this and loses.
- Parent selection — the step that decides which archived agent(s) get mutated next; here, a weighted random draw favoring high performers with few surviving children.
- Sigmoid — an S-shaped function squashing any input into (0,1); here it converts a raw benchmark score into a sharper “confidently good vs. not” weight, with steepness set by λ.
- Stepping stone — a solution that isn’t the best on its own but carries a feature or idea that a later, better solution gets built on top of.
- Fitness / performance score — here, the fraction of benchmark coding tasks solved; the empirical stand-in for the Gödel Machine’s impossible formal proof.
- Meta-agent — a separate, typically fixed model whose job is to design or modify other agents (used in ADAS-style meta-learning); the DGM removes the need for a distinct meta-agent by making the same agent do both jobs.
- SWE-bench (Verified) — a benchmark built from real GitHub issues; an agent must patch a repo so the issue’s hidden tests pass. “Verified” = a human-filtered subset where every task is confirmed solvable.
- Polyglot — a multi-language coding benchmark (used to evaluate the Aider tool) where each task mostly involves writing a solution from scratch in one file, across languages like C++, Rust, Go, Java, and Python.
- pass@1 — success measured on a single first attempt, with no access to ground-truth test results before answering (vs. pass@k, which allows k tries with feedback).
- Sandboxing — running untrusted or self-modifying code inside an isolated container/VM so it can’t affect or access anything outside it.