[{"data":1,"prerenderedAt":571},["ShallowReactive",2],{"posts-3":3,"post-\u002Fwriting\u002Fpatients-journey":12,"post-surround-\u002Fwriting\u002Fpatients-journey":570},[4],{"path":5,"title":6,"description":7,"date":8,"type":9,"readingTime":10,"draft":11},"\u002Fwriting\u002Fpatients-journey","Patient’s Journey: keeping nothing lost between the GP and the tumour board","Our MediBit team took 3rd place and the Microsoft Award at Rakathon 2026, the national AI hackathon against cancer, with Cesta Pacienta, a proof of concept that keeps information from getting lost as cancer patients move through the healthcare system.","2026-11-11","Project",6,false,{"id":13,"title":6,"body":14,"cover":559,"coverAlt":559,"date":8,"description":7,"draft":11,"extension":560,"meta":561,"navigation":262,"path":5,"readingTime":10,"seo":562,"stem":563,"tags":564,"type":9,"__hash__":569},"writing\u002Fwriting\u002Fpatients-journey.md",{"type":15,"value":16,"toc":544},"minimark",[17,53,56,61,64,103,110,114,129,137,144,150,154,157,208,219,223,228,231,234,377,380,384,387,391,466,470,477,481,488,492,495,507,511,522,526,537,540],[18,19,20,21,25,26,29,30,33,34,37,38,47,48,52],"p",{},"In October, our team ",[22,23,24],"strong",{},"MediBit"," took ",[22,27,28],{},"3rd place overall"," at ",[22,31,32],{},"Rakathon 2026",", the national AI hackathon against cancer, and won the ",[22,35,36],{},"Microsoft Award"," with our project ",[39,40,44],"a",{"href":41,"rel":42},"https:\u002F\u002Fsubmit.rakathon.cz\u002Fprojects\u002Fcesta-pacienta-spolecne-k-cili",[43],"nofollow",[22,45,46],{},"Patient’s Journey"," (",[49,50,51],"em",{},"Cesta Pacienta"," in Czech).",[18,54,55],{},"This note is about what we built, and more importantly, the design decisions behind it. They're the same principles I keep coming back to in everything I build for medicine.",[57,58,60],"h2",{"id":59},"the-event","The event",[18,62,63],{},"Rakathon is big, and it's serious about real problems:",[65,66,67,74,80,90,100],"ul",{},[68,69,70,73],"li",{},[22,71,72],{},"Nearly 500 participants"," across Prague, Brno and Ostrava",[68,75,76,79],{},[22,77,78],{},"23 real challenges"," set by Czech hospitals, research institutes, VZP ČR (the General Health Insurance Company) and health-tech companies",[68,81,82,85,86,89],{},[22,83,84],{},"65 projects submitted",", with ",[22,87,88],{},"28 city winners"," advancing to the national final in Prague",[68,91,92,93,96,97],{},"Held under the patronage of the ",[22,94,95],{},"World Health Organization"," and the ",[22,98,99],{},"Office of the Government of the Czech Republic",[68,101,102],{},"A final jury that included the government commissioner for AI and leaders from VZP ČR, the Ministry of Health and Prague's largest university hospitals",[18,104,105,106,109],{},"We took on a challenge set by ",[22,107,108],{},"VZP ČR",", built around a simple but important question: how do we make sure information doesn't get lost as cancer patients move through the healthcare system?",[57,111,113],{"id":112},"the-problem-a-patient-is-a-stack-of-documents","The problem: a patient is a stack of documents",[18,115,116,117,120,121,124,125,128],{},"When a GP suspects cancer, the patient starts a journey through the system. In the Czech setting we designed for, that means a referral to a ",[22,118,119],{},"Comprehensive Oncology Centre",", where an ",[22,122,123],{},"oncology coordinator"," prepares the case for the ",[22,126,127],{},"multidisciplinary tumour board",". The board decides on a plan, and the patient, along with the information, goes back to the GP.",[18,130,131],{},[132,133],"img",{"alt":134,"src":135,"title":136},"The patient's path: GP, oncology coordinator, tumour board, and back to the GP","\u002Fimages\u002Fwriting\u002Fpatients-journey\u002Fpathway.svg","The loop we built for: every handover is a chance to lose information",[18,138,139,140,143],{},"Every arrow in that loop is a handover, and every handover is paperwork: heterogeneous medical reports in different formats, written by different people at different times. Before a case reaches the tumour board, the care coordinator has to collect those reports, spot what's missing and keep track of deadlines. Much of that still happens ",[22,141,142],{},"through emails and phone calls",", and information gets lost, duplicated or contradicted along the way.",[18,145,146,147],{},"Our goal was simple to state: ",[22,148,149],{},"carry the patient through the whole loop without information loss.",[57,151,153],{"id":152},"what-we-built","What we built",[18,155,156],{},"Patient’s Journey is a proof of concept that brings this process into one place. Coordinators can track each patient's documentation, see what's missing and manage the whole journey, while the referring doctor stays informed about progress. Under the hood, it's built around each step of that loop:",[65,158,159,165,175,193,199],{},[68,160,161,164],{},[22,162,163],{},"Extraction."," An LLM reads the incoming medical reports and pulls out the data the next person in the chain needs for the handover.",[68,166,167,170,171,174],{},[22,168,169],{},"Verbatim quotes."," Every extracted value carries a quote from the source document. That quote is ",[22,172,173],{},"verified against the original"," and highlighted there, so anyone can see exactly where a number came from.",[68,176,177,180,181,184,185,188,189,192],{},[22,178,179],{},"Deterministic checks."," Next to the model, plain rules flag ",[22,182,183],{},"missing documents",", ",[22,186,187],{},"contradictions"," between reports, and ",[22,190,191],{},"critical lab values",".",[68,194,195,198],{},[22,196,197],{},"Human confirmation."," Nothing counts until a person confirms it. The system prepares the evidence; the clinician makes the call.",[68,200,201,204,205,192],{},[22,202,203],{},"Closing the loop."," When the plan goes back to the GP, their ",[22,206,207],{},"receipt is logged in an append-only audit trail",[18,209,210,211,214,215,192],{},"We built and demoed all of it ",[22,212,213],{},"on synthetic data",". No real patient records were involved. You can find the project on the ",[39,216,218],{"href":41,"rel":217},[43],"Rakathon project page",[57,220,222],{"id":221},"design-decisions-that-mattered","Design decisions that mattered",[224,225,227],"h3",{"id":226},"_1-quote-the-source-verbatim","1. Quote the source, verbatim",[18,229,230],{},"An extracted value is only as good as the sentence it came from. LLMs are good at reading messy reports, but they can also paraphrase, merge or invent. So instead of trusting the output, every value has to point to an exact quote, and we check that the quote really exists in the source.",[18,232,233],{},"The core of that check is deliberately boring. In a simplified form, the idea looks like this:",[235,236,241],"pre",{"className":237,"code":238,"language":239,"meta":240,"style":240},"language-python shiki shiki-themes github-light github-dark","import re\n\ndef normalise(text: str) -> str:\n    # ignore differences in whitespace and letter case\n    return re.sub(r\"\\s+\", \" \", text).strip().lower()\n\ndef quote_is_verified(quote: str, source: str) -> bool:\n    \"\"\"A value is only trusted if its supporting quote appears in the source.\"\"\"\n    return normalise(quote) in normalise(source)\n","python","",[242,243,244,257,264,289,296,328,332,357,363],"code",{"__ignoreMap":240},[245,246,249,253],"span",{"class":247,"line":248},"line",1,[245,250,252],{"class":251},"szBVR","import",[245,254,256],{"class":255},"sVt8B"," re\n",[245,258,260],{"class":247,"line":259},2,[245,261,263],{"emptyLinePlaceholder":262},true,"\n",[245,265,267,270,274,277,281,284,286],{"class":247,"line":266},3,[245,268,269],{"class":251},"def",[245,271,273],{"class":272},"sScJk"," normalise",[245,275,276],{"class":255},"(text: ",[245,278,280],{"class":279},"sj4cs","str",[245,282,283],{"class":255},") -> ",[245,285,280],{"class":279},[245,287,288],{"class":255},":\n",[245,290,292],{"class":247,"line":291},4,[245,293,295],{"class":294},"sJ8bj","    # ignore differences in whitespace and letter case\n",[245,297,299,302,305,308,312,315,318,320,322,325],{"class":247,"line":298},5,[245,300,301],{"class":251},"    return",[245,303,304],{"class":255}," re.sub(",[245,306,307],{"class":251},"r",[245,309,311],{"class":310},"sZZnC","\"",[245,313,314],{"class":279},"\\s",[245,316,317],{"class":251},"+",[245,319,311],{"class":310},[245,321,184],{"class":255},[245,323,324],{"class":310},"\" \"",[245,326,327],{"class":255},", text).strip().lower()\n",[245,329,330],{"class":247,"line":10},[245,331,263],{"emptyLinePlaceholder":262},[245,333,335,337,340,343,345,348,350,352,355],{"class":247,"line":334},7,[245,336,269],{"class":251},[245,338,339],{"class":272}," quote_is_verified",[245,341,342],{"class":255},"(quote: ",[245,344,280],{"class":279},[245,346,347],{"class":255},", source: ",[245,349,280],{"class":279},[245,351,283],{"class":255},[245,353,354],{"class":279},"bool",[245,356,288],{"class":255},[245,358,360],{"class":247,"line":359},8,[245,361,362],{"class":310},"    \"\"\"A value is only trusted if its supporting quote appears in the source.\"\"\"\n",[245,364,366,368,371,374],{"class":247,"line":365},9,[245,367,301],{"class":251},[245,369,370],{"class":255}," normalise(quote) ",[245,372,373],{"class":251},"in",[245,375,376],{"class":255}," normalise(source)\n",[18,378,379],{},"If the quote can't be found, the value isn't silently accepted. It gets flagged for a person to look at.",[224,381,383],{"id":382},"_2-rules-next-to-the-model-never-replaced-by-it","2. Rules next to the model, never replaced by it",[18,385,386],{},"Some things shouldn't be left to a language model at all. Is a required document missing? Do two reports disagree? Is a lab value in a critical range? These have clear answers, so deterministic rules handle them, and the model does what it's actually good at: reading unstructured text.",[224,388,390],{"id":389},"_3-a-human-confirms-every-value","3. A human confirms every value",[392,393,394,410],"table",{},[395,396,397],"thead",{},[398,399,400,404,407],"tr",{},[401,402,403],"th",{},"Step",[401,405,406],{},"Done by the system",[401,408,409],{},"Done by a person",[411,412,413,424,435,445,456],"tbody",{},[398,414,415,419,422],{},[416,417,418],"td",{},"Reading the reports",[416,420,421],{},"extracts values with source quotes",[416,423],{},[398,425,426,429,432],{},[416,427,428],{},"Checking consistency",[416,430,431],{},"flags gaps, contradictions, critical labs",[416,433,434],{},"reviews the flags",[398,436,437,440,442],{},[416,438,439],{},"Accepting a value",[416,441],{},[416,443,444],{},"confirms it",[398,446,447,450,453],{},[416,448,449],{},"Tumour board decision",[416,451,452],{},"prepares the evidence",[416,454,455],{},"decides",[398,457,458,461,464],{},[416,459,460],{},"Handover to the GP",[416,462,463],{},"logs receipt in the audit trail",[416,465],{},[224,467,469],{"id":468},"_4-time-matters-in-medicine","4. Time matters in medicine",[18,471,472,473,476],{},"Tumour board write-ups in Patient’s Journey are ",[22,474,475],{},"time-correct to the meeting date",": they reflect what was known when the board met, not what arrived in the system later. When you look back at a decision, you need to see the information the doctors actually had.",[224,478,480],{"id":479},"_5-privacy-by-default","5. Privacy by default",[18,482,483,484,487],{},"Even in a hackathon proof of concept running on synthetic data, the national ID is ",[22,485,486],{},"pseudonymised",". It's much easier to build it in from the start than to bolt it on later.",[57,489,491],{"id":490},"what-im-taking-away","What I'm taking away",[18,493,494],{},"Patient’s Journey is a proof of concept, not a product yet. Taking it into a real hospital needs validation with clinicians, integration with existing systems, and everything that comes with running software in clinical care.",[18,496,497,498,501,502,506],{},"But the hackathon confirmed something I believe strongly: ",[22,499,500],{},"AI in medicine is most useful when it shows its work."," Traceable sources, deterministic safety nets and a human in the loop aren't constraints that slow the AI down. They're what make it usable at all. It's the same approach I'm taking with clinical-trial matching at ",[39,503,24],{"href":504,"rel":505},"https:\u002F\u002Fmedibit.tech",[43]," and with agentic AI for DNA variant interpretation in my MSc thesis.",[57,508,510],{"id":509},"whats-next","What's next",[18,512,513,514],{},"We're continuing to develop Patient’s Journey with MediBit: testing it in real clinical workflows and, eventually, piloting it with a partner institution. ",[22,515,516,517,192],{},"If you work in cancer care coordination and would like to help us take it further, I'd love to ",[39,518,521],{"href":519,"rel":520},"https:\u002F\u002Fcalendly.com\u002Fmartinsivak\u002F30min",[43],"hear from you",[57,523,525],{"id":524},"thank-you","Thank you",[18,527,528,529,532,533,536],{},"Our mentors' experience with real patient pathways shaped the solution: ",[22,530,531],{},"doc. MUDr. Zuzana Bielčiková, Ing. Klára Vankova, Mgr. Tereza Chrástová, RNDr. Marian Rybář, MUDr. Michaela Klimeš Lipánová and Alina Pirshtuk",". Special thanks to our Microsoft mentor, ",[22,534,535],{},"Olena Vasylenko",", for her guidance and support.",[18,538,539],{},"Thanks also to Tomas Studenik and the entire Caelestinus team, VZP ČR, the Second Faculty of Medicine of Charles University (2. lékařská fakulta Univerzity Karlovy), and Motol University Hospital and Homolka Hospital (Fakultní nemocnice Motol a Homolka).",[541,542,543],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":240,"searchDepth":259,"depth":266,"links":545},[546,547,548,549,556,557,558],{"id":59,"depth":259,"text":60},{"id":112,"depth":259,"text":113},{"id":152,"depth":259,"text":153},{"id":221,"depth":259,"text":222,"children":550},[551,552,553,554,555],{"id":226,"depth":266,"text":227},{"id":382,"depth":266,"text":383},{"id":389,"depth":266,"text":390},{"id":468,"depth":266,"text":469},{"id":479,"depth":266,"text":480},{"id":490,"depth":259,"text":491},{"id":509,"depth":259,"text":510},{"id":524,"depth":259,"text":525},null,"md",{},{"title":6,"description":7},"writing\u002Fpatients-journey",[565,566,567,568],"rakathon","oncology","llms","clinical-workflow","8doZs55_PMr_YKDWSpzXeF46eDR6p8D3tD5aFt-96BM",[559,559],1794418143230]