On Wednesday, Alexandre De Groodt, Cedric Sounard and I spent the day at the Wintercircus in Ghent for Solve with Google, working on a challenge set by the Belgian Society of Paediatric Haematology and Oncology. By the 16:30 demo we had a headline we were a little embarrassed by and very proud of: we built a fancy PDF viewer.
Doctors Ctrl+F
When a child is referred to one of the seven Belgian centres that treat childhood cancer, the oncologist has to get three things right before the first talk with the family: the diagnostic work-up, the treatment plan, and how to explain it. All three live in a trial protocol, a PDF between 50 and 415 pages long. Then, at the start of every treatment block, the same question comes back: can this patient start? The answer is a list of thresholds on page 48 of one PDF, or page 167 of another.
So doctors do what everyone does with a 400-page PDF. They press Ctrl+F, type "platelets", and scroll through the hits.
Protocols get amended every few months and are uploaded by staff who are not engineers. Each centre runs its own set, with its own local rules on top. The diseases are rare, so whatever we built had to cost almost nothing to run. And patient data was off the table.
Why not a chatbot
The chatbot version is easy to picture. Put the PDFs in a vector store, put a model in front, let the doctor ask "can I start course 3 with platelets at 70?" For a one-day hackathon, it demos well.
Cedric spent the morning with the doctors and our clinical coach, and came back with this: doctors always check the PDF anyway. No oncologist is going to give a child a dose because a chatbot said so. They will read the answer, then go find the page to confirm it. So a chatbot still ends in a Ctrl+F, with a paid model call in front of it, and that call wants the patient's details in the prompt to be useful.
So we aimed for a doctor needing to ask as rarely as possible: put the line they need in front of them, with its page one click away, and most questions never get typed.
Two prototypes, merged
Alexandre and I built two versions in parallel through the morning while Cedric kept bringing back what the doctors wanted. Alexandre's had the better admin flow, uploading a new protocol version and reviewing what changed, and a dose view that the coach liked immediately. Mine had the extraction pipeline and the consult sheet. Early in the afternoon we reconciled them into one: his upload and review flow and his dose tables went onto my pipeline and sheet.
Building twice sounds wasteful. It meant we got to compare two real answers to the same problem instead of arguing about hypothetical ones, and Cedric could put both in front of doctors and come back with which parts they reached for.
Good data in
Most of our time went into understanding the data. Clinical protocols are inconsistent documents. Headings are numbered "5.2 - Induction" in one, "5.2 Induction" in another, and not numbered at all in a third. A list of investigations continues across a page break. A table of starting criteria turns into loose lines of text. Each of these breaks something downstream, and a chatbot built on top hands the error to the doctor with nothing to show it is wrong.
So the pipeline reads every page with its fonts, sizes and positions, finds the structure in code, and then uses Gemini to label it: which sections are the diagnostic work-up, which are treatment steps, where the treatment forks and what decides each fork. The rule we kept to all day was that the model points, and code copies. The model says "line 214 is a start requirement for Course 3". It never writes clinical text. The text a doctor sees is copied verbatim from the PDF with its page and position, and a verifier checks every quote and every number against the page.
What comes out is a spec: one structured, versioned file per protocol version. Every feature is a view over that file. The consult sheet reads the spec and shows the diagnosis work-up in four steps (primary tumour, genetics, extent of disease, baseline) as tickable checklists. It shows the risk groups and the treatment as a map, so picking a risk group folds away every arm that patient will never see. Each treatment block gets its requirements to start, thresholds included. Monitoring becomes a table over time.

Then we added summaries. Every line gets a short scan-line next to it, with the original on hover and the PDF page on click. The model was already writing a short version of every line, so we had the same call write it in English, French and Dutch. Belgian doctors get the protocol in French or Dutch as part of extraction, not only in the English it was written in. Code rejects any summary whose numbers, units or comparison signs differ from the original, and a second model call rejects any summary that changes the meaning, such as an "even if" that became an "if".
The chatbot is still there. Ctrl+J opens an assistant that knows which protocol and which section you are reading, answers in one sentence first, and cites pages it has checked. It is just no longer the front door. Ctrl+K search handles synonyms, abbreviations, Dutch, French and typos, which covers the lookups people would otherwise type into a chatbot.
Evals that improve the pipeline
You can't eyeball 32 protocols and 4,000 pages, so we didn't try. We built evals early and let them drive the work.
There are deterministic checks over every protocol that run in seconds: lists split across blocks, tables flattened into prose, headings that swallowed a sentence, sections whose own heading ended up inside their body. There is a vision judge that puts the rendered PDF page next to what we show and flags differences. There are about a thousand hand-labelled lines for the segmenter, a third of them held out so we never tuned on them. And there were the organisers' golden questions, scored fact by fact.
The loop: run the evals, read the worst failures, fix the pipeline (never the output), re-run. Much of that ran on agents in parallel, each taking one class of failure, fixing the pipeline and showing the count go down. By the demo the golden questions were at 97%, with the remaining misses either disputed answer keys or a table that only exists as an image.
At one point an agent suggested we could get the last few points by making the scorer more lenient. I asked it whether it was Volkswagen. The score on the slide has to measure what the doctor will see, so the scorer stayed exactly as it was.
Pay once, then read for free
A chatbot pays on every question. Our pipeline pays once per protocol version, so we used the strongest model available, with deep thinking, and didn't worry about it. We modelled the cost of every pass, measured from real token counts: building the ML-DS protocol costs about €5, the 415-page ALLTogether protocol about €10, and the full set of 32 between €35 and €140 depending on how many passes you rerun. That happens when a protocol changes, which is every few months.
Running it is close to free. Opening a protocol, searching, following a risk group or ticking a checklist calls no model at all: €0 per lookup. A question to the assistant costs about five cents. The server costs about €24 a month.
It also keeps patient data out. A lookup never sends anything to a model. The assistant gets the question and the protocol text it needs, not the case. The case tracker keeps a patient's progress in the browser and hands the doctor a code to paste into their own record. Nothing about the patient is stored on our side.
What happens next
The day after a hackathon is usually where these projects die. Here, every time the evals find a new kind of failure, it becomes a check, and the fix goes into the pipeline rather than into one protocol. When a centre uploads an amended protocol next month, it goes through the same pipeline and the same checks before anyone publishes it. So the pipeline keeps getting better at reading protocols, including ones it has never seen.
If your team searches protocols, contracts, manuals or regulations with Ctrl+F, we build this kind of system. It is also the workload we built Ingram Cloud to run: long pipelines, evals on every change, and a log of what every model call did and cost. Get in touch if you want to talk about yours.

