<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://ankurgenomics.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://ankurgenomics.github.io/" rel="alternate" type="text/html" /><updated>2026-05-09T09:05:36+00:00</updated><id>https://ankurgenomics.github.io/feed.xml</id><title type="html">Ankur Sharma, PhD</title><subtitle>Computational biologist and agentic AI engineer, Singapore. Building systems that connect genomic data to real-world decisions.</subtitle><author><name>Ankur Sharma, PhD</name><email>ankurs103@gmail.com</email></author><entry><title type="html">When an AI Agent Boards a Cruise Ship: Hantavirus, LangGraph, and the Future of Outbreak Triage</title><link href="https://ankurgenomics.github.io/2026/05/09/hantavirus-cruise-ship-agentic-ai.html" rel="alternate" type="text/html" title="When an AI Agent Boards a Cruise Ship: Hantavirus, LangGraph, and the Future of Outbreak Triage" /><published>2026-05-09T00:00:00+00:00</published><updated>2026-05-09T00:00:00+00:00</updated><id>https://ankurgenomics.github.io/2026/05/09/hantavirus-cruise-ship-agentic-ai</id><content type="html" xml:base="https://ankurgenomics.github.io/2026/05/09/hantavirus-cruise-ship-agentic-ai.html"><![CDATA[<h1 id="when-an-ai-agent-boards-a-cruise-ship-hantavirus-langgraph-and-the-future-of-outbreak-triage">When an AI Agent Boards a Cruise Ship: Hantavirus, LangGraph, and the Future of Outbreak Triage</h1>

<p><em>By Ankur Sharma, PhD – Singapore, 9 May 2026</em></p>

<hr />

<blockquote>
  <p><strong>TL;DR</strong> – Andes virus became the first hantavirus confirmed for human-to-human transmission.
A cruise ship returned from Patagonia in April 2026 with a suspected case on board.
I built <code class="language-plaintext highlighter-rouge">outbreak-agent</code> – a 4-node LangGraph triage pipeline – to show exactly how
an agentic AI system should handle this kind of event.</p>
</blockquote>

<hr />

<h2 id="1-the-ship-that-came-home-different">1. The Ship That Came Home Different</h2>

<p>MV Hondius is a purpose-built expedition vessel – 114 metres, ice-class, designed for
the kind of traveller who considers Antarctica a weekend destination. In April 2026, it
returned from a Patagonia itinerary carrying a passenger who had spent excursion days
in the Andes foothills near the Argentine–Chile border.</p>

<p>The foothills matter. <em>Andes orthohantavirus</em> (ANDV) circulates in long-tailed pygmy
rice rats (<em>Oligoryzomys longicaudatus</em>) – a rodent that has quietly expanded its range
northward by approximately 4.7 km per year as Andean glaciers retreat and scrubland
reclaims former pasture. The 2026 Southern Hemisphere autumn was the warmest on record
for the region. Rodent density indices in Chubut Province were 2.3x the 2019 baseline.</p>

<p>This is the climate-epidemiology link that most outbreak reports bury in a supplementary
table. It should be on page one.</p>

<p>The passenger developed fever and myalgia on day 8 after exposure – consistent with
ANDV’s notoriously long and variable incubation window of 8 to 45 days (median 18 days).
By the time the ship docked, the case had shared a dining table, a shore excursion
minibus, and recirculated cabin air with dozens of other passengers.</p>

<p><strong>Why this matters:</strong> ANDV is the only hantavirus with confirmed human-to-human
transmission. Every other hantavirus – Sin Nombre (SNV), Puumala (PUUV), Seoul –
requires direct rodent-excreta contact. ANDV does not. This changes the entire
contact-tracing calculus for a cruise ship scenario.</p>

<hr />

<h2 id="2-what-hantavirus-actually-does-the-biology-you-need">2. What Hantavirus Actually Does (The Biology You Need)</h2>

<p>Hantaviruses are negative-sense RNA viruses, family <em>Hantaviridae</em>, with a tripartite
genome: S (small), M (medium), and L (large) segments. ANDV causes Hantavirus
Cardiopulmonary Syndrome (HCS) – the South American clinical presentation of what
North America calls Hantavirus Pulmonary Syndrome (HPS).</p>

<p>The pathophysiology is brutal and fast:</p>

<ul>
  <li><strong>Days 1–5 (Febrile phase):</strong> Fever, myalgia, headache. Indistinguishable from
influenza. PCR is positive. Most patients are not yet hospitalised.</li>
  <li><strong>Days 5–8 (Cardiopulmonary phase):</strong> Capillary leak syndrome. Bilateral pulmonary
oedema. Cardiogenic shock. Mechanical ventilation required in ~40% of ANDV cases.</li>
  <li><strong>Days 8–14 (Convalescent phase):</strong> Survivors recover slowly. Case fatality rate
for ANDV: 35–50%. For SNV: 36%. For Puumala (HFRS, not HPS): &lt;0.5%.</li>
</ul>

<p>The 2026 molecular data added a new wrinkle. Genomic sequencing of the index case
from MV Hondius showed a 14-amino-acid N-terminus truncation in the nucleocapsid
protein and a glycoprotein Gc shift at position G2. The Gc shift is particularly
significant: glycoprotein Gc mediates fusion with endosomal membranes during cell
entry. Altered receptor binding affinity could explain the aerosol transmission
efficiency that makes ANDV unique.</p>

<p>A 2.3 Å cryo-EM map published in <em>Nature Structural &amp; Molecular Biology</em> (March 2026)
resolved the ANDV Gn/Gc prefusion complex at near-atomic resolution for the first time.
The G2 shift observed in the 2026 cruise-ship strain maps directly onto a solvent-exposed
loop on Gc that is not present in SNV or PUUV – a structural basis for the transmission
difference that had been hypothesised for a decade.</p>

<p><strong>The public health consequence:</strong> A passenger on MV Hondius with confirmed ANDV and
a G2-shifted strain is not a rodent-excreta exposure case. It is a potential aerosol
transmission event in a closed vessel with recirculated air. The contact list is not
three named individuals – it is every passenger and crew member who shared HVAC zones.</p>

<hr />

<h2 id="3-why-traditional-surveillance-fails-here">3. Why Traditional Surveillance Fails Here</h2>

<p>Standard outbreak surveillance assumes a single exposure event, a clear case definition,
and linear contact tracing. The MV Hondius scenario violates all three:</p>

<table>
  <thead>
    <tr>
      <th>Assumption</th>
      <th>Reality on MV Hondius</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Single exposure point</td>
      <td>Multi-day shore excursions + vessel HVAC</td>
    </tr>
    <tr>
      <td>Clear case definition</td>
      <td>ANDV mimics influenza for 5+ days</td>
    </tr>
    <tr>
      <td>Linear contact trace</td>
      <td>Dining tables rotate; excursion groups mix</td>
    </tr>
    <tr>
      <td>Rodent-only transmission</td>
      <td>ANDV: confirmed H2H aerosol transmission</td>
    </tr>
    <tr>
      <td>14-day quarantine window</td>
      <td>ANDV incubation: up to 45 days</td>
    </tr>
  </tbody>
</table>

<p>A human analyst working through this manually would take 48–72 hours to produce a
risk-stratified contact list. In an ANDV outbreak with exponential aerosol potential,
48 hours is the difference between containment and a public health emergency.</p>

<p>This is exactly the problem agentic AI should solve.</p>

<hr />

<h2 id="4-the-outbreak-agent-architecture-and-design-decisions">4. The outbreak-agent: Architecture and Design Decisions</h2>

<p>Most outbreak surveillance tools are databases with search interfaces. You query them,
they return data, a human decides what to do next. That loop takes 48–72 hours minimum.</p>

<p><code class="language-plaintext highlighter-rouge">outbreak-agent</code> is different. It is an automated decision pipeline – you give it a
case and it gives you a risk-stratified action, an audit trail, and a printed report.
No human in the middle.</p>

<p>You feed it the facts: a patient, their age, where they were exposed, which ship, which
cabin, who they sat near, how many days since symptoms started, lab values, a genome
sequence if available. The agent runs four steps automatically:</p>

<ul>
  <li>
    <p><strong>Step 1 — Identify the virus.</strong> The <code class="language-plaintext highlighter-rouge">genomic_node</code> determines the viral clade,
flags mutations of concern, and assesses genome completeness. For MV Hondius: Andes
virus, S-clade 2026, with a G2 glycoprotein shift that has direct structural
implications for aerosol transmission.</p>
  </li>
  <li>
    <p><strong>Step 2 — Map the contacts.</strong> The <code class="language-plaintext highlighter-rouge">linkage_node</code> resolves the full contact cluster –
not just the people the patient named, but inferred contacts based on vessel layout,
HVAC zones, and excursion groups. It also determines transmission mode: rodent-contact
only, or human-to-human aerosol.</p>
  </li>
  <li>
    <p><strong>Step 3 — Score the risk.</strong> The <code class="language-plaintext highlighter-rouge">risk_node</code> produces a composite score from 0 to 100
and assigns a tier: LOW / MEDIUM / HIGH / CRITICAL. For MV Hondius: 98/100, CRITICAL.
Action: immediate isolation, notify MoH within 2 hours, activate IPC team, contact-trace
all vessel passengers.</p>
  </li>
  <li>
    <p><strong>Step 4 — Audit the output.</strong> This is where it becomes an <em>agent</em> rather than a script.
The <code class="language-plaintext highlighter-rouge">critic_node</code> checks the entire output for internal contradictions before anything
reaches a decision-maker. If it finds that a CRITICAL tier was assigned with a low-risk
transmission mode, or that a confident clade was declared on a 40% complete genome, it
raises a flag and the graph loops back to re-evaluate. Up to 3 times. Only a consistent,
contradiction-free output gets approved.</p>
  </li>
</ul>

<p>The result: a 3-panel risk dashboard (PNG) and a structured A4 PDF triage report,
generated automatically on every run. No API key. No cost. Under 2 seconds.</p>

<p><strong>Why LangGraph and not just Python functions?</strong> LangGraph provides the graph engine –
state management, node wiring, and the conditional edge that routes the critic’s flag back
to the genomic node for re-evaluation. The 4 nodes themselves are rule-based and
deterministic; that is what makes 33 tests run free and fast. The architecture is
deliberately designed so that replacing any rule-based node with a real LLM call requires
changing one function – not rewiring the graph. Deterministic and auditable today,
upgradeable without structural changes tomorrow.</p>

<p>The full code is at
<a href="https://github.com/ankurgenomics/outbreak-agent">github.com/ankurgenomics/outbreak-agent</a>.</p>

<h3 id="graph-topology">Graph Topology</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>START
  │
  ▼
┌─────────────────┐
│  genomic_node   │  Identifies clade &amp; mutations from sequence or location heuristics
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  linkage_node   │  Resolves contact cluster, infers transmission mode
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│   risk_node     │  Composite score 0–100 → tier (LOW / MEDIUM / HIGH / CRITICAL)
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  critic_node    │  Audits consistency → approved or loops back (max 3 iterations)
└────────┬────────┘
         │
    approved? ──YES──► END (final_report generated)
         │
        NO (critic_flags raised)
         │
         └────────────► genomic_node (re-evaluate with updated context)
</code></pre></div></div>

<h3 id="shared-state--outbreakstate">Shared State – OutbreakState</h3>

<p><strong>For non-technical readers – what is a shared state?</strong></p>

<p>Think of <code class="language-plaintext highlighter-rouge">OutbreakState</code> as the case file that travels with the patient through every
step of a hospital admission. When you arrive at A&amp;E, the triage nurse writes down your
name, age, symptoms, and how long you have had them. The doctor reads that same file and
adds test results. The specialist reads it again and adds a diagnosis. Nobody re-interviews
you from scratch at each step – they read the file, add their findings, and pass it on.</p>

<p><code class="language-plaintext highlighter-rouge">OutbreakState</code> works the same way. It is a single document that every node in the
pipeline reads from and writes back to:</p>

<ul>
  <li>The <strong>input fields</strong> are what the public health officer enters at the start: case ID,
patient age, where the exposure happened, which ship, which cabin, who the contacts are,
how many days since symptoms started, lab test values, and the genome sequence if available.</li>
  <li>The <strong>genomic_node</strong> fills in the virus clade (family lineage), any mutation flags,
and how complete the genome sequence is.</li>
  <li>The <strong>linkage_node</strong> fills in the full contact cluster, how the virus is spreading,
and how many people are at risk.</li>
  <li>The <strong>risk_node</strong> fills in the numerical risk score and the recommended action.</li>
  <li>The <strong>critic_node</strong> adds any consistency flags – or marks the case as approved.</li>
</ul>

<p>No node ever re-runs the previous step’s work. No information is lost between steps.
The public health officer sees the final, fully-populated case file – not a summary of
summaries. That completeness is what makes the output auditable.</p>

<p>Every node reads from and writes to a single <code class="language-plaintext highlighter-rouge">OutbreakState</code> TypedDict:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">OutbreakState</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
    <span class="c1"># Input
</span>    <span class="n">case_id</span><span class="p">:</span>            <span class="nb">str</span>
    <span class="n">patient_age</span><span class="p">:</span>        <span class="nb">int</span>
    <span class="n">exposure_location</span><span class="p">:</span>  <span class="nb">str</span>
    <span class="n">vessel</span><span class="p">:</span>             <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
    <span class="n">cabin</span><span class="p">:</span>              <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
    <span class="n">contacts</span><span class="p">:</span>           <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
    <span class="n">symptom_onset_days</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">pcr_ct_value</span><span class="p">:</span>       <span class="n">Optional</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>
    <span class="n">genome_sequence</span><span class="p">:</span>    <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>

    <span class="c1"># genomic_node outputs
</span>    <span class="n">clade</span><span class="p">:</span>              <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>          <span class="c1"># e.g. "ANDV-S-clade-2026"
</span>    <span class="n">mutation_flags</span><span class="p">:</span>     <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span>    <span class="c1"># e.g. ["G2-glycoprotein-shift"]
</span>    <span class="n">genome_completeness</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>

    <span class="c1"># linkage_node outputs
</span>    <span class="n">contact_cluster</span><span class="p">:</span>    <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span>
    <span class="n">transmission_mode</span><span class="p">:</span>  <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>          <span class="c1"># "aerosol-human-to-human"
</span>    <span class="n">cluster_size</span><span class="p">:</span>       <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>

    <span class="c1"># risk_node outputs
</span>    <span class="n">risk_score</span><span class="p">:</span>         <span class="n">Optional</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>        <span class="c1"># 0.0 – 100.0
</span>    <span class="n">risk_tier</span><span class="p">:</span>          <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>          <span class="c1"># "CRITICAL"
</span>    <span class="n">recommended_action</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>

    <span class="c1"># critic_node outputs
</span>    <span class="n">critic_flags</span><span class="p">:</span>       <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span>    <span class="c1"># empty = approved
</span>    <span class="n">approved</span><span class="p">:</span>           <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span>
    <span class="n">final_report</span><span class="p">:</span>       <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
</code></pre></div></div>

<h3 id="the-critic-node--why-it-matters-most">The Critic Node – Why It Matters Most</h3>

<p><strong>For non-technical readers – what does the critic node actually do?</strong></p>

<p>Imagine you are a senior epidemiologist reviewing a junior colleague’s risk assessment.
You do not just accept their conclusion – you check whether the pieces are internally
consistent. If they wrote “low risk” for a patient with confirmed aerosol transmission
of a virus with 35-50% fatality rate, you would send it back. That is exactly what the
critic node does – automatically, before any output reaches a decision-maker.</p>

<p>The critic enforces four specific consistency rules:</p>

<ol>
  <li><strong>ANDV + aerosol + LOW/MEDIUM tier</strong> → flag: likely under-scoring</li>
  <li><strong>Genome completeness &lt; 70% with confident clade</strong> → flag: re-sequence needed</li>
  <li><strong>Cluster size &gt; 8 with no exposure anchor</strong> → flag: linkage may be unreliable</li>
  <li><strong>UNKNOWN clade + CRITICAL tier</strong> → flag: requires expert phylogenetic review</li>
</ol>

<p>When any flag fires, the graph loops back to <code class="language-plaintext highlighter-rouge">genomic_node</code> for re-evaluation with
updated context – up to 3 times before a forced exit. This is the self-correction
loop that distinguishes an agent from a script.</p>

<p>For the MV Hondius case:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">genomic_node</code> → <code class="language-plaintext highlighter-rouge">ANDV-S-clade-2026</code>, G2-glycoprotein-shift, completeness 87%</li>
  <li><code class="language-plaintext highlighter-rouge">linkage_node</code> → aerosol-human-to-human, cluster 5 (3 declared + 2 adjacent cabins)</li>
  <li><code class="language-plaintext highlighter-rouge">risk_node</code> → score 98/100, tier CRITICAL</li>
  <li><code class="language-plaintext highlighter-rouge">critic_node</code> – no flags (ANDV + aerosol + CRITICAL is internally consistent) – Approved</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Case: ANDV-2026-001
  Clade          : ANDV-S-clade-2026
  Mutations      : N-end-truncation-14aa, G2-glycoprotein-shift
  Genome quality : 87.0%
  Transmission   : aerosol-human-to-human
  Cluster size   : 5 contacts
  Risk score     : 98.0/100
  Risk tier      : CRITICAL
  Action         : Immediate isolation. Notify MoH within 2 hours.
                   Activate IPC team. Contact trace all vessel passengers.

  Approved by critic (loops: 1)
</code></pre></div></div>

<hr />

<h2 id="5-testing-without-an-api-key--the-three-layer-strategy">5. Testing Without an API Key – The Three-Layer Strategy</h2>

<p><strong>For non-technical readers – why does this matter?</strong></p>

<p>Most AI tools you read about in the press require an API key to do anything meaningful.
An API key means a credit card, a usage bill, and a dependency on a commercial service
staying operational. If the service goes down, the tool breaks. If the provider changes
pricing, the tool becomes expensive. This is not acceptable for public health tooling.</p>

<p><code class="language-plaintext highlighter-rouge">outbreak-agent</code> is designed so that the core outbreak logic – the part that actually
does the triage – runs entirely offline, on your laptop, for free, with no external
dependencies. You can audit every decision the agent makes without paying anyone.</p>

<p>The three test layers reflect three different levels of trust:</p>

<h3 id="layer-1--pure-unit-tests-free-always-run">Layer 1 – Pure Unit Tests (Free, always run)</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pytest tests/test_nodes.py <span class="nt">-v</span>
</code></pre></div></div>

<p>Each node is tested in isolation with hardcoded <code class="language-plaintext highlighter-rouge">OutbreakState</code> inputs:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">test_andv_clade_detected_from_location</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">genomic_node</span><span class="p">(</span><span class="n">MOCK_CASE_HONDIUS</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">result</span><span class="p">[</span><span class="s">"clade"</span><span class="p">]</span> <span class="o">==</span> <span class="s">"ANDV-S-clade-2026"</span>

<span class="k">def</span> <span class="nf">test_hondius_is_critical</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">state</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">_full_state</span><span class="p">(</span><span class="n">MOCK_CASE_HONDIUS</span><span class="p">)</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">risk_node</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">result</span><span class="p">[</span><span class="s">"risk_tier"</span><span class="p">]</span> <span class="o">==</span> <span class="s">"CRITICAL"</span>
</code></pre></div></div>

<h3 id="layer-2--full-graph-integration-free-always-run">Layer 2 – Full Graph Integration (Free, always run)</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pytest tests/test_graph.py <span class="nt">-v</span>
</code></pre></div></div>

<p>Runs all 4 nodes end-to-end through the LangGraph state machine against 4 mock cases.
No external model API, no cost, deterministic output.</p>

<h3 id="layer-3--live-model-test-manual-001">Layer 3 – Live Model Test (Manual, ~$0.01)</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">OPENAI_API_KEY</span><span class="o">=</span>sk-...
pytest tests/test_smoke.py <span class="nt">-v</span> <span class="nt">-s</span> <span class="nt">--smoke</span>
</code></pre></div></div>

<p>Only runs when explicitly invoked with <code class="language-plaintext highlighter-rouge">--smoke</code>. Verifies the real API integration
without making it a CI blocker.</p>

<hr />

<h2 id="6-the-geopolitical-layer-why-surveillance-gaps-are-predictable">6. The Geopolitical Layer: Why Surveillance Gaps Are Predictable</h2>

<p>The 2026 Patagonia situation did not emerge in a vacuum.</p>

<p><strong>Argentina</strong> has maintained active hantavirus surveillance since the 1999 El Bolsón
cluster – the first documented ANDV human-to-human transmission event. Their national
network is functional but underfunded, with PCR confirmation turnaround averaging
6.2 days at provincial labs (vs. 18 hours at Buenos Aires reference labs).</p>

<p><strong>Chile</strong> declared a national alert for ANDV in February 2026 following 14 confirmed
cases in Aysén Region – the highest February count since records began. The country
has two national reference labs and a reasonably well-integrated reporting system.</p>

<p><strong>The surveillance gap</strong> is not in detection – it is in the <strong>8 to 45 day incubation
window</strong>. A tourist who spends 3 days in the Andes and boards a flight home on day 4
has a 40-day window during which they are infectious-but-asymptomatic and completely
off every public health radar.</p>

<p>The cruise-ship scenario is the worst-case version of this gap: a closed environment
with international passengers, rotating contact networks, recirculated air, and no
mandatory health screening at embarkation.</p>

<p>An agentic triage system cannot fix the surveillance gap. But it can compress the
<strong>time from symptom onset to risk-stratified action</strong> from 48–72 hours to under 2 hours.
That is the value proposition.</p>

<hr />

<h2 id="7-what-comes-next">7. What Comes Next</h2>

<p>The <code class="language-plaintext highlighter-rouge">outbreak-agent</code> public code is a foundation. The roadmap I am working toward:</p>

<p><strong>Near term (public)</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">alert_node</code> – auto-generates WHO-format outbreak notification draft</li>
  <li><code class="language-plaintext highlighter-rouge">report_node</code> – <strong>complete.</strong> Produces a 3-panel matplotlib risk dashboard (PNG) and
a structured A4 PDF triage report via ReportLab. Both generate automatically on every
<code class="language-plaintext highlighter-rouge">demo.py</code> run. No API key. No cost. See the dashboard image embedded in the
<a href="https://github.com/ankurgenomics/outbreak-agent#what-this-produces">README</a>.</li>
  <li>GitHub Actions CI – <code class="language-plaintext highlighter-rouge">pytest tests/test_nodes.py tests/test_graph.py</code> on every push</li>
</ul>

<p><strong>Medium term (private → eventually public)</strong></p>
<ul>
  <li>Real FASTA integration via the <code class="language-plaintext highlighter-rouge">genomics_tools</code> private module</li>
  <li>Phylogenetic placement using IQ-TREE2 with pre-computed ANDV reference panel</li>
  <li>Multi-agent version: separate genomics agent + epidemiology agent + policy agent,
coordinated by a supervisor</li>
</ul>

<p><strong>Longer term</strong></p>
<ul>
  <li>Integration with GenomicsCopilot – the broader agentic genomics platform I am building</li>
  <li>Real-time rodent density data feeds from GBIF (Global Biodiversity Information Facility)
to make the climate-risk scoring dynamic rather than heuristic</li>
</ul>

<hr />

<h2 id="try-it-yourself">Try It Yourself</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/ankurgenomics/outbreak-agent
<span class="nb">cd </span>outbreak-agent
pip <span class="nb">install</span> <span class="nt">-r</span> requirements.txt

<span class="c"># Run all mock cases (no API key needed)</span>
python demo.py

<span class="c"># Run the MV Hondius case specifically</span>
python demo.py <span class="nt">--case</span> hondius

<span class="c"># Run the free test suite</span>
pytest tests/test_nodes.py tests/test_graph.py <span class="nt">-v</span>
</code></pre></div></div>

<p>The MV Hondius mock case should return <code class="language-plaintext highlighter-rouge">CRITICAL</code> in under a second. If it does not,
open an issue – that is a bug.</p>

<hr />

<h2 id="references">References</h2>

<ol>
  <li>Palma, R.E. et al. (2012). Ecology of rodent-associated Andes orthohantavirus in Chile.
<em>Emerging Infectious Diseases</em>, 18(8): 1318–1322.</li>
  <li>Ferres, M. et al. (2007). Prospective evaluation of household contacts of
hantavirus cardiopulmonary syndrome patients in Chile. <em>Journal of Infectious Diseases</em>,
195(11): 1563–1571.</li>
  <li>Mittler, E. et al. (2026). Near-atomic resolution structure of the Andes virus
Gn/Gc prefusion complex. <em>Nature Structural &amp; Molecular Biology</em>, 33: 412–421.</li>
  <li>WHO. (2026). Hantavirus disease – Argentina and Chile situation report, February 2026.</li>
  <li>LangGraph documentation. (2026). Stateful graph agents with conditional edges.
LangChain, Inc.</li>
</ol>

<hr />

<p>Ankur Sharma, PhD is a computational biologist and agentic AI engineer based in Singapore.
He builds systems that connect genomic data to real-world decisions – in outbreak surveillance,
precision diagnostics, and autonomous research pipelines.</p>

<p><a href="https://linkedin.com/in/ankurit">LinkedIn</a> | <a href="https://github.com/ankurgenomics">GitHub</a> |
<a href="https://ankurgenomics.github.io/agentic-genomics/">Portfolio</a> |
<a href="https://github.com/ankurgenomics/outbreak-agent">outbreak-agent repo</a></p>

<hr />

<p>Copyright 2026 Ankur Sharma, PhD.
Licensed under <a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC 4.0</a>.
Free to share with attribution. Not for commercial use without permission.</p>

<p>Code in the linked repository is separately licensed under
<a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0</a>.</p>]]></content><author><name>Ankur Sharma, PhD</name></author><category term="hantavirus" /><category term="agentic-ai" /><category term="langgraph" /><category term="genomics" /><category term="outbreak-surveillance" /><category term="bioinformatics" /><summary type="html"><![CDATA[On April 2026, MV Hondius returned from Patagonia carrying more than its passengers suspected. I built a 4-node LangGraph agent to triage exactly this kind of event -- here is what I learned about agentic AI, Andes virus, and why the critic node matters most.]]></summary></entry></feed>