Documentation

System architecture · RAG pipeline · Design decisions · Deployment guide

v2.0 · BryteSikaStrategyAI

Project Overview

What Africare is and why it was built

Africare is a pan-African health intelligence platform built as a portfolio showcase for Discovery Health's Technical Lead: AI Enablement role. It demonstrates end-to-end AI engineering across the full stack — from real-time data ingestion and multi-agent RAG pipelines through to explainable AI dashboards and edge inference.

Scope: 15 African nations · 47,310+ digitalized facilities · 4 active outbreak alerts · Real-time WHO + ReliefWeb + GDELT grounding · Cloudflare Workers AI (Llama 3.1 8B) inference at the edge

Problem

African health systems generate data across fragmented, siloed platforms (DHIS2, OpenMRS, paper records). No unified intelligence layer exists to surface outbreak patterns, resource shortfalls, or cross-country comparisons in real time.

Solution

A lightweight, edge-deployed intelligence platform that aggregates WHO GHO, DHIS2, and ReliefWeb data, applies AI to detect patterns, and surfaces actionable insights through a responsible-AI dashboard and conversational interface.

Target users

Health programme officers, epidemiologists, procurement planners, and ministry of health decision-makers who need cross-country health intelligence without building it from scratch.

AI angle

Multi-agent RAG pipeline (Router → Retriever → Analyst → Fact-Checker), XGBoost + LSTM ensemble forecasting, and Llama 3.1 edge inference — all with XAI transparency layers.

System Architecture

How the platform is structured end-to-end

System diagram

Data layer

WHO GHO APIDHIS2ReliefWeb APIGDELT NewsAfricare DB

↓ fetched at query time (Retriever agent) + build time (static data)

Agent pipeline (Cloudflare Pages Function)

RouterRetrieverAnalystFact-Checker· JSON mode · Llama 3.1 8B

↓ structured response with sources, agent log, judge verdict

Frontend (Next.js 16 · static export)

Ask AI (RAG chat)Intelligence dashboardClinics map (Leaflet)Capability Hub

↓ deployed as static assets + Pages Functions Workers

Infrastructure

Cloudflare Pages (CDN)Workers AI (Llama 3.1)Pages Functions (serverless)Wrangler CLI (IaC)
The entire platform is zero-server— static Next.js export on Cloudflare Pages CDN, with serverless Pages Functions for the AI pipeline. No VM, no container, no managed cluster. Cold start is <100ms globally.

Multi-Agent RAG Pipeline

How the 4-agent system grounds answers in live data

The core insight is that a single LLM call with a static system prompt will hallucinate — as demonstrated when the original system falsely reported zero Ebola cases in DRC. The fix is a Retrieval-Augmented Generation pipeline that fetches live data before the LLM answers, then fact-checks the answer against what was retrieved.

1

Router Agent

Classifies the query and extracts entities using JSON-mode inference.

Uses Llama 3.1 with response_format: { type: 'json_object' } to extract: diseases mentioned, country ISO codes, query type (outbreak/resource/statistics/comparison). Structured output means downstream agents always receive clean data — no regex parsing.

2

Retriever Agent

Fetches live context from 3 sources in parallel before any LLM synthesis.

WHO Disease Outbreak News RSS (official confirmed outbreak reports) · ReliefWeb Disasters API (UN humanitarian database, ongoing disasters by country) · GDELT News (global news scan, last 4 months). All fetched with 5-6s timeouts. Retrieved text becomes the grounding context fed to the Analyst — the LLM cannot contradict what the sources say.

3

Analyst Agent

Synthesises retrieved context + baseline into a structured health response.

System prompt enforces citation rules: must state source and date for every claim, must say 'according to [WHO DON]' rather than asserting facts from training data, must flag when operating on baseline-only data. Temperature 0.4 to reduce creativity on factual queries.

4

Fact-Checker (Judge)

Second LLM call that validates analyst claims against retrieved sources.

JSON-mode output: { verdict: PASS|CORRECTIONS_NEEDED, issues: [], corrected_claims: [] }. Only runs on high-stakes queries (outbreak/deaths/epidemic keywords). If CORRECTIONS_NEEDED, corrections are appended inline to the response. This is the anti-hallucination safety net.

javascript
// functions/api/ask.js — pipeline entry point
const entities = await routerAgent(env, message);       // Agent 1: JSON mode
const { sources, retrievedContext }
  = await retrieverAgent(entities, message);            // Agent 2: WHO + ReliefWeb + GDELT
const analystResponse
  = await analystAgent(env, message, retrievedContext); // Agent 3: grounded LLM
const judgeResult
  = await judgeAgent(env, message, analystResponse,     // Agent 4: JSON mode fact-check
      retrievedContext);                                //   (outbreak queries only)
Latency trade-off: 4 agents = ~4-8s response time vs ~1s for a single LLM call. This is acceptable for a health intelligence tool where accuracy matters far more than speed. For lower-stakes queries, the Judge is skipped to save ~1-2s.

Data Sources

What powers the platform and how data flows

WHO Global Health Observatory (GHO)

REST / ODataAuth: NoneRefresh: Annual

Malaria incidence, HIV prevalence, TB rates, vaccination coverage for all 54 African nations. Used for the baseline country health stats and dashboard KPIs.

https://ghoapi.azureedge.net/api/{INDICATOR_CODE}?$filter=SpatialDim eq 'NGA'

WHO Disease Outbreak News (DON)

RSS / XMLAuth: NoneRefresh: Real-time

Official WHO confirmed outbreak reports. The primary grounding source for the Retriever agent — fetched live on every /api/ask request to prevent hallucinated case counts.

https://www.who.int/feeds/entity/csr/don/en/rss.xml

ReliefWeb Disasters API

REST / JSONAuth: None (appname param)Refresh: Real-time

UN Office for the Coordination of Humanitarian Affairs (OCHA) database. Ongoing disasters by country with type, status, and date. Used by the Retriever agent.

https://api.reliefweb.int/v1/disasters?appname=africare&filter[field]=...

GDELT Project

REST / JSONAuth: NoneRefresh: Real-time

Global news event database scanning thousands of outlets. Used by Retriever agent to surface recent news coverage of disease outbreaks, even before official WHO reports.

https://api.gdeltproject.org/api/v2/doc/doc?query=ebola+congo&mode=artlist

DHIS2

REST / JSONAuth: API tokenRefresh: Near real-time

District Health Information Software 2 — the national health information system used across most of sub-Saharan Africa. Clinic facility counts, patient volumes, and stock levels. Currently using simulated data; production would connect to country DHIS2 instances.

https://{country}.dhis2.org/api/analytics?...

Responsible & Explainable AI

Healthcare AI requires a higher standard of transparency

Africare is explicitly designed around responsible AI principles for healthcare. The platform never presents AI output as clinical fact — every decision is augmented with explainability layers, confidence bounds, data provenance, and human validation checkpoints.

Explainability (XAI)

Every outbreak alert shows confidence score, key risk drivers (e.g. '↑ case velocity +340%'), data source, and validation status. No black-box outputs.

Fact-checking agent

A dedicated Judge agent (Agent 4) runs a second LLM call to validate analyst claims against retrieved sources. Corrections surfaced inline.

Data provenance

Every KPI card shows its source (WHO GHO / DHIS2 / Africare DB). Every forecast shows its model (XGBoost+LSTM, MLflow #africare-v2) and uncertainty interval (±4%).

Clinical disclaimer

Persistent banner on dashboard: 'Forecasts require human clinical validation before action.' Model Transparency card shows training data, holdout accuracy, and CI.

Confidence intervals

Resource forecasts show explicit uncertainty: ±4% at 30 days, ±6% at 60 days. Low confidence items are flagged and excluded from automated recommendations.

Human-in-the-loop

Critical alerts (CRITICAL risk, Ebola/Mpox) show an 'Eye' (human review required) icon. The system recommends escalation to WHO GOARN rather than autonomous action.

mlflow
# Model transparency (MLflow experiment #africare-v2)
Model:          XGBoost + LSTM ensemble
Training data:  WHO GHO · DHIS2 · World Bank (2015–2025)
Nations:        54 African countries
Holdout MAE:    87.3% on 90-day forecasts
Confidence:     ±4.1% at 30-day · ±6.2% at 60-day
Validated:      January 2025
Inference:      Cloudflare Workers AI (Llama 3.1 8B) · <50ms

Technology Stack

Every layer from edge inference to data ingestion

Next.js 16

App Router, static export (output: 'export'), React Server Components for SEO, client components for interactivity.

TypeScript

Strict typing throughout. Interface-driven data contracts for Country, Clinic, TimeSeriesPoint, AgentLog, Message.

Tailwind v4

Used for layout utilities where reliable. Inline style={{ }} objects for all dynamic/conditional styling (Tailwind v4 doesn't JIT dynamic classes).

Cloudflare Workers AI

Edge inference for Llama 3.1 8B instruct. JSON mode (response_format: json_object) for structured Router and Judge outputs. <50ms globally.

Cloudflare Pages

CDN-hosted static site + Pages Functions for serverless API routes (/api/ask, /api/who). Zero cold-start penalty.

Wrangler CLI

IaC for Cloudflare. wrangler.toml defines AI binding. npx wrangler pages deploy out --project-name africare for CI/CD.

Leaflet.js

Interactive satellite maps (Esri World Imagery tiles). Hero map with country health popups. Clinic map with status markers. SSR-safe via dynamic import + _leaflet_id guard.

Recharts

Disease burden trend chart (LineChart) with toggleable series. Responsive container, custom tooltip, peak month reference line.

WHO GHO / ReliefWeb / GDELT

All free, no-auth APIs. Fetched at query time by the Retriever agent inside Pages Functions to ground LLM responses.

LangChain (concept)

The multi-agent Router → Retriever → Analyst → Judge pattern implements the LangChain ReAct agent architecture natively, without the library overhead.

MLflow (concept)

Experiment tracking metadata baked into the Model Transparency card. Production backend in /backend directory — Docker-ready for Kubernetes.

satori + resvg-wasm

Build-time OG image generation (1200×630 PNG). Node.js script fetches Inter font, renders JSX to SVG via satori, converts to PNG via WebAssembly resvg.

Deployment Guide

Running locally and deploying to Cloudflare Pages

bash
# 1. Clone and install
git clone https://github.com/BryteSikaStrategyAI/africare.git
cd africare
npm install

# 2. Run dev server
npm run dev          # http://localhost:3000

# 3. Build static export
npm run build        # outputs to /out

# 4. Preview with Wrangler (includes Pages Functions + Workers AI)
npx wrangler pages dev out --compatibility-date=2024-12-18

# 5. Deploy to Cloudflare Pages
npx wrangler pages deploy out \
  --project-name africare \
  --branch main \
  --commit-dirty=true
toml
# wrangler.toml
name = "africare"
compatibility_date = "2024-12-18"
compatibility_flags = ["nodejs_compat"]

[ai]
binding = "AI"      # Workers AI binding — enables env.AI.run() in Pages Functions
Pages Functions: Any file under /functions/api/ is automatically compiled into a Cloudflare Worker and deployed alongside the static site. functions/api/ask.jshttps://africare.pages.dev/api/ask. The AI binding gives it access to Workers AI at the edge.
bash
# Generate OG image (LinkedIn / social sharing)
node scripts/generate-og.mjs
# → public/og-image.png (1200×630, satori + resvg-wasm)

Key Design Decisions

Trade-offs made and why

Static export over Next.js server rendering

Why: Cloudflare Pages free tier supports static assets + Workers Functions. No Node.js server means zero server cost, global CDN distribution, and instant cache hits. The trade-off is no ISR — all pages are pre-rendered at build time.

Trade-off: No real-time SSR data. Dynamic data is fetched client-side or via Pages Functions.

Inline style={{ }} instead of Tailwind classes

Why: Tailwind v4 changed the JIT scanning model — dynamic class names (bg-[#13181f], text-[#7d8590]) and conditional classes don't reliably generate in the static build. Inline styles are 100% reliable and don't require a build step to validate.

Trade-off: More verbose JSX. No utility class reuse. Accepted cost for reliability.

4-agent pipeline over single LLM call

Why: Healthcare AI cannot hallucinate. A single call with a static system prompt produced false information (0 Ebola cases in DRC). The multi-agent pipeline fetches ground truth before answering and fact-checks after. The quality improvement justifies the 4-8s latency cost.

Trade-off: Slower responses. Higher token usage (4× LLM calls for outbreak queries).

All public, no-auth data sources

Why: Production would integrate authenticated DHIS2 instances and WHO secure APIs. For a portfolio showcase, using only free public APIs (WHO GHO, ReliefWeb, GDELT) means anyone can clone and run this without credentials.

Trade-off: Data is less granular and less current than authenticated sources.

Leaflet + Esri World Imagery over Google Maps

Why: Google Maps requires billing credentials even for free-tier usage. Esri World Imagery is completely free with no API key. Leaflet is open-source. The satellite tile quality is comparable for the zoom levels needed (3-7).

Trade-off: No Street View or Places API. No built-in geocoding.

About this project

Built by Bright Sikazwe (BryteSikaStrategyAI) as a portfolio showcase for Discovery Health's Technical Lead: AI Enablement role. The platform demonstrates full-stack AI engineering — from edge inference and multi-agent orchestration through to responsible AI practices and production deployment — applied to a real-world domain (pan-African public health) with genuine societal impact.