OVERVIEW
Biotech Accelerator is a multi-agent AI system for early-stage biotech research. A LangGraph pipeline parses a research query and routes it through UniProt, PubMed, the PDB with ProDy normal-mode analysis, and ChEMBL, then synthesizes the collected evidence into a structured list of experiments worth running next. It runs in Docker for reproducibility and reports progress through a Rich terminal UI.
ARRIVED AS
Early-stage biotech research means stitching together protein databases, literature, structural models, and chemistry by hand before anyone can decide which experiment to run. The work is slow, easy to get wrong, and hard to reproduce.
Deciding what biotech experiment to run next depends on evidence scattered across separate systems: sequence and function in UniProt, prior findings in PubMed, structures in the PDB, dynamics from normal-mode analysis, and bioactivity in ChEMBL. A researcher normally queries each by hand and holds the synthesis in their head. This project automates that gathering and synthesis with a multi-agent pipeline so the human starts from a structured shortlist instead of a blank page.
WHAT I BUILT
- 01A LangGraph-orchestrated pipeline that parses a research query and routes it through UniProt, PubMed, the PDB, normal-mode analysis (ANM/GNM), and ChEMBL in sequence.
- 02Each external source sits behind its own agent with a typed interface, so a failed lookup degrades gracefully instead of breaking the run.
- 03Normal-mode analysis via ProDy adds a structural/dynamics signal on top of sequence and literature evidence, which most query tools skip.
- 04Packaged in Docker for a reproducible run, with a Rich terminal UI for readable progress and output.
WHAT CHANGED
- Turns a multi-tool manual research loop into one query that returns a structured list of suggested experiments.
- Cross-references computational evidence with literature so suggestions are grounded, not just generated.
- Reproducible end to end: the same query and container produce the same pipeline, useful for handing results to a collaborator.
ARCHITECTURE

Decisions, with the cost of each.
A decision without its trade-off is marketing. Each row says what was chosen, why, and what it gave up.
Multi-agent pipeline over a single prompt
Each data source has its own access pattern, schema, and failure modes. Giving each source a dedicated agent keeps parsing logic isolated and lets one source fail without aborting the run. A single monolithic prompt would conflate retrieval, parsing, and synthesis and would hallucinate when a lookup came back empty.
One long-context LLM call (brittle, no real retrieval), a fixed script with no agent boundaries (hard to extend per source).
Add normal-mode analysis as a distinct structural signal
Sequence and literature evidence are common; structural dynamics from ANM/GNM normal-mode analysis are not. Including ProDy-based NMA gives the synthesis stage a signal that distinguishes candidates that look similar on sequence alone.
Sequence and literature only (cheaper, less discriminating).
The part that mattered.
The numbers behind the work, and the code that produced them.
- in the pipeline
- 5 agents
- literature · structure · drug · synthesis · experiment-suggester
- external APIs
- 4 sources
- UniProt · PubMed · RCSB PDB · ChEMBL
- NMA modes
- 100
- ProDy ANM, 15A spring-network cutoff
- ports + adapters
- Hexagonal
- graceful degradation per source
_PDB_ID_PATTERN = re.compile(r"\b([0-9][A-Z0-9]{3})\b", re.IGNORECASE)
_GENE_PATTERN = re.compile(r"\b([A-Z]{2,6})\b")
# known proteins resolve straight to UniProt accessions
PROTEIN_NAME_MAP = {
"lysozyme": "P00698", "hemoglobin": "P69905",
"insulin": "P01308", "egfr": "P00533", "tp53": "P04637",
}
# a free-text question -> PDB IDs, gene symbols, and a
# has_drug_query flag that decides whether the ChEMBL stage runs
No model call to start: the parser uses regex for PDB IDs and gene symbols and a name-to-UniProt map for common proteins, then sets a drug-query flag. Cheap, deterministic routing before any expensive lookup.
class NMAAnalyzer:
"""Normal Mode Analysis via ProDy ANM (Anisotropic Network Model)."""
def __init__(self, n_modes: int = 100, cutoff: float = 15.0):
self.n_modes = n_modes
self.cutoff = cutoff # spring-network cutoff, angstroms
def analyze(self, pdb_path: Path) -> NMAResult:
import prody
# model the structure as a spring network, compute the
# lowest n_modes -> eigen-spectrum -> per-residue flexibility
The signal most query tools skip. ANM treats the protein as a network of springs and solves for its low-frequency normal modes, surfacing flexible regions and hinges that sequence and literature evidence alone cannot distinguish. (Reused from Jay's Nobel Data Intelligence project.)
async def structure_node(state: BiotechState) -> dict:
agent = StructureAnalystAgent()
try:
return {**await agent(state), "current_phase": "structure_done"}
except Exception as e: # a flaky API becomes
return { # a degraded section,
"structure_error": str(e), # not a dead run
"structure_summary": f"Structure analysis failed: {e}",
"current_phase": "structure_done",
}
finally:
await agent.close()
# build: parse -> resolve_proteins -> literature -> structure
# -> drugs (conditional) -> synthesis -> END
Each node wraps its agent in try/except/finally. A failing external source turns into a labelled gap in the report instead of aborting the whole pipeline, and the drug stage is skipped entirely when the query is not drug-related.
✓ LEARNED
Source-specific agents with typed interfaces make a research pipeline resilient: a flaky external API becomes a degraded result, not a crash.
A structural-dynamics signal is worth the extra stage. Normal-mode analysis surfaces differences that sequence and literature evidence miss.
Shipping in Docker from the start made the pipeline reproducible, which matters more than speed when the output is a research recommendation someone else has to trust.