The classics of bioinformatics, in more than one tongue.
Scientific software gets locked in the language it was written in. A bridge like
rpy2 lets an agent call an R tool; it does not let anyone
extend or build on it natively — and the classics go unmaintained as their
language and dependencies move on.
Bio-Babel rebuilds them natively in the target ecosystem, and ships each package with a
machine-readable contract so an agent that has never seen it still calls it
correctly. Nothing in that is specific to R, or to graphics.
R → Python is where we are proving it: seventeen classics so far,
each its own repository and its own caretaker.
“And the whole earth was of one language, and of one speech.”
Genesis 11:1
17libraries stewarded
1,606contracted symbols
21public repositories
0runtime bridges
Why Babel
Translation became impossible. That is the part we are fixing.
The punishment in the story was never difference — a field's diversity of thought is
its wealth. It was that ideas could no longer travel. Bioinformatics lives a small version of
that: a beautiful tool blooms on one side of the language line, and the half of the field on
the other side can reach across for it at best — never build on it.
Locked in the source language
Callable from another language, but not natively extended or built upon. A bridge gets you
the call and nothing more: you cannot write a new geom against a tool you reach through
rpy2, and you cannot compose it with anything native. The tool is reachable
and still stranded.
The behaviour is not in the signature
It is in the object system, the data containers, the numerical conventions, the ecosystem
dependencies. Match every signature and a reimplementation will still run while
silently diverging — or run correctly while sitting outside the idioms of the
ecosystem it now belongs to.
Fidelity and usability are separate problems
The rebuild has to behave like the original. And an agent that has never seen it has to
use it correctly. Neither implies the other — a faithful port whose API the model has to
guess at fails just as hard. So every package ships a _biobabel/ contract
alongside the implementation.
The Stack
One lineage, rebuilt from the ground up.
The visualization stack is the first worked example: R's grid → {gtable, scales} → ggplot2
chain and everything downstream of it, carried into pure Python on a Cairo backend.
No matplotlib. Publication-quality output by construction — and one
self-consistent API for an agent to reason about, instead of four.
Tier 1 · Foundation
The graphics engine itself
R's grid — viewports, grobs, units, the whole device model — reimplemented
on Cairo, plus the scales transform/break/palette machinery and the
gtable layout algebra. Everything above stands on these three.
grid_py261 symbols
scales226 symbols
gtable_py21 symbols
Tier 2 · Grammar
The grammar of graphics, whole
geoms, stats, scales, facets, coords, themes and guides — composed with +,
exactly as in R. The largest single contract in the project, and the one an agent is most
likely to hallucinate against.
ggplot2_py626 symbols · 18 concepts · 30 idioms
Tier 2–3 · Extensions
The ecosystem that grew on top
The extension packages that make R plots publication-ready: repelled labels, alluvial
flows, independent scales, facet surgery, plot composition and the two heatmap standards
of genomics.
patchworkcompose with | and /
complexheatmapannotated heatmap lists
ggrepel_pynon-overlapping labels
ggalluvialflow diagrams
ggh4xfacet & axis hooks
ggnewscalemultiple colour scales
pheatmapclustered heatmaps
Tier 2–3 · Analysis
The methods people actually cite
Single-cell trajectories, intercellular communication, CNV calling. These build their
entire visualization layer on the tiers below — so a Monocle 2 trajectory plot
renders like the R tutorial without adapter code.
monocle2pyDDRTree · BEAM · pseudotime
monocle3AnnData-native trajectories
nichenetrligand → target modelling
tradeseqNB-GAM lineage DE
copykatCNV aneuploidy detection
ddrtreereversed graph embedding
The spire
What reaches the agent
Every tier below publishes a _biobabel/ contract through a Python entry
point. biobabel discovers them and serves 12 read-only tools over MCP to
Claude Code, Cursor, Codex and Continue. It runs no business logic and never executes
code.
biobabelcontract registry + MCP server
How a library becomes agent-legible
01
Port
A controller drives coding agents through a 13-step workflow — preparation,
implementation, validation. Implementation operates on the package, not the
function: the whole export surface is resolved into a dependency graph and cut into
slices, each built and tested only after the ones it depends on.
02
Annotate
An agent writes each package's _biobabel/ contract from that package's
own source, never from a neighbour's. Seven deterministic checks gate it — among them that
every public export is covered, and that each anti-pattern's detector fires on its own bad
example and stays silent on the good one.
03
Serve
biobabel enumerates one Python entry-point group — no central registry —
and serves what it finds as 12 read-only MCP tools. An agent sees exactly the packages the
user has installed; a package without a contract is invisible.
The catalog
Seventeen classics, on PyPI today.
Each is its own repository, its own distribution, its own maintainer. Versions track the
upstream R package — rgrid-python 4.5.3.post6 tracks R grid 4.5.3;
a Python-side fix without an R bump becomes a PEP 440 .postN.
Foundationtier 1
rgrid-python
ports R grid · imports as grid_py
R's grid graphics engine — viewports, grobs, units, the device model — reimplemented on a Cairo backend. The floor everything else stands on.
Foundationtier 1
scales-python
ports R scales · imports as scales
Breaks, labels, transforms and palettes. The scale machinery the grammar depends on, down to the tick-placement heuristics.
Foundationtier 1
gtable-python
ports R gtable · imports as gtable_py
Layout tables of grobs — the skeleton a plot is assembled into: panels, axes, strips and guides.
Grammartier 2
ggplot2-python
ports R ggplot2 · imports as ggplot2_py
The grammar of graphics, whole. geoms, stats, scales, facets, coords, themes and guides — composed with +, exactly as in R.
Extensiontier 3
patchwork-python
ports R patchwork · imports as patchwork
Compose plots into arbitrary layouts with |, / and insets. Alignment that actually respects the gtable.
Extensiontier 3
complexheatmap-python
ports R ComplexHeatmap · imports as complexheatmap
Annotated heatmaps, splits and heatmap lists — the de-facto standard for genomics figures.
Extensiontier 2
pheatmap-python
ports R pheatmap · imports as pheatmap
Pretty heatmaps with row/column clustering and annotation bars, built on the original grid model.
Extensiontier 3
ggrepel-python
ports R ggrepel · imports as ggrepel_py
Text and label geoms that repel each other and the plot edges. The reason gene labels are readable.
Extensiontier 2
ggalluvial-python
ports R ggalluvial · imports as ggalluvial
Alluvial diagrams and flow plots for categorical longitudinal data — clone tracking, fate mapping, cohort flows.
Extensiontier 2
ggh4x-python
ports R ggh4x · imports as ggh4x
Hooks into facets, axes and strips that the grammar does not expose on its own.
Extensiontier 2
ggnewscale-python
ports R ggnewscale · imports as ggnewscale
Multiple independent colour and fill scales in a single plot, without fighting the guide system.
Analysistier 2
monocle2-python
ports R monocle 2.9.0 · imports as monocle2py
Single-cell trajectory inference — DDRTree, BEAM, pseudotime — with its entire visualization layer on the Bio-Babel stack. No matplotlib, no seaborn.
Analysistier 2
monocle3-python
ports R monocle3 · imports as monocle3
AnnData-native trajectories, clustering and differential expression.
Analysistier 3
nichenet-python
ports R nichenetr · imports as nichenetr
Ligand → target modelling of intercellular communication, with the prior networks intact.
Analysistier 2
tradeSeq-python
ports R tradeSeq · imports as tradeseq
NB-GAM trajectory-based differential expression along lineages.
Analysistier 3
copykat-python
ports R copykat · imports as copykat
CNV-based aneuploidy detection from scRNA-seq — separating tumour from stroma.
Analysistier 3
ddrtree-python
ports R DDRTree · imports as ddrtree
Reversed graph embedding for principal-graph learning. The engine underneath Monocle 2.
Every library in the catalog is under active testing — APIs stabilizing,
edges still being filed. Use it for verifiable work, and tell us when it is wrong.
The framework
A build side, a read side, and the contract between them.
Fidelity and usability are met by two agent-driven systems, coupled by the contract that each
package carries: a build side that reconstructs the software, and a
read side that serves its operating knowledge to the agent. Two of the three
are not public yet.
Build side01
bio-babel-toolkit
Drives coding agents through the 13-step workflow that reconstructs a package natively.
A controller keeps state in a report tree on disk rather than in the model's context, so
progress survives an agent losing it — and implementation is ordered by a dependency-graph
partition, package-wide, instead of proceeding function by function.
Coming soonThe contract02
bio-babel-annotator
Writes each package's _biobabel/ contract from that package's own source, in
an isolated session that can never read a neighbour's. Seven deterministic checks gate the
result, so coverage of the public surface cannot silently shrink and no detector ships
without firing on its own bad example.
Coming soonRead side03
bio-babel-MCP
Assembles those contracts from every installed package through one Python entry-point
group and serves them as 12 read-only tools over MCP. There is no central registry, and
the server neither plans nor executes: an agent sees exactly what the user installed, and
a package without a contract is invisible.
├──__init__.py# get_manifest() → PackageManifest├──package.yaml# identity · tier · class · foundation├──skill.md# the narrative, for the LLM├──symbols/*.yaml # 261 signatures + requires/writes/mutates├──concepts/*.yaml # 6 invariants, "for R users / for Python users"├──idioms/*.yaml # 15 verbatim runnable templates├──anti_patterns/* # 4 detectable mistakes + the correct form├──templates/*.py # real code that actually runs└──detectors.py# the AST checks, owned by the package
agent session
# the agent guesses — R muscle memorygrid.viewport(width=unit(0.5, "npc")) ✗ silently wrong# the agent asks firstbiobabel.describe_symbol(pkg="grid_py",
symbol="Unit")
→ Unit(value, units) — class, not a function.→ anti-pattern: unit_kw — lowercase unit() is R.grid_py.Viewport(width=Unit(0.5, "npc")) ✓
12 read-only tools
All prefixed biobabel., all returning the same envelope, all served over
line-delimited JSON-RPC on stdio. The server holds no business logic and
never executes your code.
Discovery 8
list_packages
describe_package
list_workflows
describe_workflow
list_symbols
describe_symbol
list_templates
describe_template
Concept 3
describe_concept
list_idioms
describe_idiom
Validation 1
check_code— static AST scan
Hard invariants
Contract is mandatory. No _biobabel/, no registration. There is no
reflection fallback and no degraded mode.
Entry points only. The registry never scans site-packages. The
producer declares itself.
Never executes code. No exec, no subprocess, no eval. Running a
snippet is the calling agent's job.
No silent degradation. Broken entry points, duplicate ids and unregistered
detectors surface as explicit errors.
Domain knowledge stays with its owner. Core ships zero detectors; the package
that owns the domain owns its AST checks.
An ablation, not a demo. Same model, same 38 tasks, same workspace tools, same judge. The
single independent variable is whether the agent can reach the contract server. Both arms
get an identical tool set — that identity is the fairness guarantee.
The agent writes solution.py blind; the harness runs it exactly once and the
judge grades the real artifact. Nothing can be ground out by retrying — this measures what
the model actually knows.
Both arms iterate freely, so accuracy saturates and the signal moves to cost: how many rounds,
how many blind executions, how many output tokens it takes to get there.
The honest line: contract lookups are not free. In execution mode the
Bio-Babel arm spends +272% input tokens to buy −9.7 rounds and −50%
output tokens. We report the cost because a benchmark that only reports the win is an
advertisement.
Principles
The rules we try not to break.
01
Semantic parity, idiomatic surface
Behaviour trusts the reference; the API feels native to the target language. Not a
line-for-line transliteration — a sibling.
02
No runtime bridges
No rpy2, no second interpreter, no R install. If you can
pip install it, it works.
03
Validated against the origin
Every public function is checked against its reference — numerically where possible,
visually where not. Divergence is a bug, not a feature.
04
Docs and stewardship, first-class
A port is alive when someone is learning it and someone is maintaining it. Every package
has a caretaker, not just an author.
Every port goes through the same loop
AI drafts. A private pipeline produces an initial port from the canonical source.
Humans review. A maintainer shapes the API, rejects mimicry, insists on idioms.
The reference judges. Outputs are validated against the origin. Divergence is a bug.
The community maintains. When upstream moves, its sibling here moves too.
🔒 The AI pipeline behind these ports is still in internal
development and is not yet public. It will be. In the meantime, the
libraries it produces are what we are asking you to judge us on.
Community
Five ways in, in rough order of commitment.
01
Nominate a library
Open an issue with a classic package you wish existed on the other side — and the
workflow that is painful without it.