CASCADE — an agent that runs drug-discovery experiments off a Trello board

Inspiration

I'm a junior software engineer at a drug-discovery startup. I don't design the computational experiments themselves; I build and maintain the software around them. The idea for CASCADE came from a problem I noticed while working closely with computational chemists.

A typical workflow might involve picking a protein target, preparing a few dozen candidate molecules, launching a screening run, looking through the scores, copying the interesting compounds into a spreadsheet, and then manually starting the next tool on those survivors. A lot of this work happens on virtual machines, and there are plenty of small steps where someone has to wait, check a result, copy something, and start the next experiment.

I started thinking about how much of that could be automated. Not the scientific decisions themselves, but the repetitive work around them: moving results between stages, launching jobs, keeping track of what has happened, and asking the scientist for input when a decision actually needs their attention. The goal is to let scientists spend more of their time interpreting results and making scientific decisions, rather than manually coordinating each experiment.

What cascade does?

A scientist drags one card into To Do — “screen the attached compounds against HIV-1 protease, PDB 1HSG, using indinavir as the control” — and walks away.

CASCADE reads the card, chooses the right computational stage, fetches the protein structure, and runs the workload on Google Cloud. Before reporting results, it validates the run against the known control. If the control fails, CASCADE automatically increases the search effort and re-runs until the result is reliable.

It then gives every compound a verdict and rationale, and proposes the next stage as a new Recommended card with a cost estimate. The scientist simply drags that card into To Do to approve it. One drag per stage is all the scientist needs to do.

CASCADE currently supports three stages, ordered from cheapest to most expensive:

  • Docking — does the compound fit the pocket?
  • Developability & safety screening — does it have known liabilities?
  • GPU stability simulation — does the predicted pose hold up?

The funnel narrows at every stage, so expensive computation is only used when justified. But CASCADE is not a fixed pipeline: it chooses stages based on the question, can run safety screening without a protein structure, and refuses impossible requests with a clear explanation instead of running meaningless jobs.

How CASCADE was built

CASCADE runs as a single service on Cloud Run, with Trello as the user interface. Scientists already use task boards, so there’s no new interface to learn. That makes the system much easier to adopt.

The service is built with FastAPI. Most of what CASCADE does involves waiting on something else — Trello, Gemini, the database, or Cloud Storage — so async handlers let a small container handle many campaigns at once.

When a Trello webhook arrives, the service verifies its signature, acknowledges it in under a second, and sends the event to Pub/Sub. There are two topics: one for incoming card events and one for completed jobs. Both are delivered back to the service through authenticated push requests. This means a twenty-minute scientific job never blocks a Trello webhook, and a completed job can trigger the campaign to continue.

The agent layer uses Google ADK, specifically its graph workflow API rather than a simple chain of agents. The reason is that a campaign needs to pause while a job runs and then resume later, potentially in a completely different container. Cloud Run can scale to zero, so the container that starts a job is unlikely to be the one that receives the completion event.

ADK handles this by checkpointing each step of the graph to the database. A paused campaign can then be resumed using two derived identifiers: one based on the Trello card ID and another based on the run and attempt number. Nothing needs to stay in memory, and there is no dependency on a particular container instance.

The scientific judgement comes from four Gemini agents running on Vertex AI. Each is a single-turn call with a Pydantic model defining both the input and output. I never parse model-generated prose to make a decision. The model has to return a valid, typed response; otherwise, the step fails.

One of the key design principle followed is: Gemini judges, code decides. The model reads the card, selects the next stage, chooses parameters, and produces per-compound verdicts. But irreversible actions — creating a card, submitting a job, or recording a decision — are handled by fixed application steps. The model cannot skip, repeat, or execute them out of order.

PostgreSQL is the primary database hosted on Cloud SQL, it holds five small tables: runs, card events, jobs, decisions, and artifacts. The service accesses them through async SQLAlchemy, with Alembic migrations applied on container startup.

Anything file-shaped goes into Cloud Storage instead: protein structures, compound libraries, job specifications, and results. Everything is organised under a path for each run. This keeps large binary files out of the database and lets the workload containers work directly with the files they need.

Each scientific stage runs as its own Cloud Run Job. Each job reads its specification from Cloud Storage, writes its results back, and publishes a completion event to Pub/Sub. The workload architecture is kept modular, so newer tools can be introduced to agent easily.

Because these are run-to-completion jobs, I only pay for the time the simulations actually run. Finally, the entire cloud infrastructure is managed with Terraform, so the system can be recreated from scratch without relying on any manual setup.

Built With

Share this project:

Updates

Submission history