This isn't really "Clojure with types beats Clojure."
It's "an agent with a typed repair protocol beats an agent without one."
Beagle works like this:
Beagle source
→ Racket reader/parser
→ custom type checker
→ emitted plain .clj
→ normal Clojure runtime
No Typed Racket. The type system is hand-rolled in racket/base .
- Custom reader that preserves
[]vs()because Clojure vectors matter - Full pipeline inside
#%module-begin: parse → check → emit → display generated Clojure - ~666 pre-typed Clojure stdlib functions
- LSP server
- Typed REPL
- Daemon using
filesystem-change-evtfor reactive checking The main experiment was whether this helps coding agents repair Clojure programs. I ran 15 agentic coding head-to-head experiments that feature beagle, clojure, and python. Notably in one experiment at ~8,500 LOC with 35 injected bugs:
Beagle: 3/3 full correctness
Clojure: 0/3 full correctness
Beagle can turn runtime failures into ranked, machine-readable repair patches. That means the agent spends basically zero tokens on mechanical bugs and can focus on actual semantic repair. Still early, but the results are interesting (correctness, wall-time, etc). Next step is designing more robust experiments with larger programs, cleaner baselines, and harder repair cases.
This is the second version of a pattern I first tested with Nisp for Nix: use Racket as a source-aware authoring/checking layer, then emit ordinary code for the target ecosystem. While Beagle targets Clojure, the underlying machinery such as type-driven repair, oracle synthesis, and reactive diagnostics are not Clojure-specific.
I think Racket itself could benefit from the same kind of agent-facing repair/compiler infrastructure.