The problem
Kenya has a fully devolved constitution, 47 county governments, and millions of young people who have never been told their civic rights in plain language. Civic education has historically been locked behind workshops, physical pamphlets, and human trainers — reaching only those who show up.
Questions like "Who is my MCA?", "How do I register to vote?", "What is the role of the county assembly?" go unanswered at scale. Siasa Place and similar organisations work in 13 counties with 8,000+ directly engaged youth — meaningful work, but the constitutional promise of public participation requires reaching millions, not thousands.
The constraint that shaped every decision: the people who most need civic information are the least likely to seek it out through formal channels. The tool had to meet them where they already are, answer in plain language, and be honest about the source of every answer.
The solution
A RAG-powered conversational AI tool that answers civic and governance questions grounded on Kenya's Constitution 2010, IEBC voter registration information, and county government explainers. Available on web and WhatsApp — meeting users where they already are.
Every answer cites the source document so users can verify the information themselves. In a politically sensitive context, that citation is not a UX detail — it is the trust mechanism.
Architecture
The system has four layers: a knowledge base, an embedding pipeline, a retrieval layer, and a generation layer.
Knowledge base. Three authoritative Kenyan civic documents: Kenya Constitution 2010 (PDF processed and chunked into ~500-token segments), the IEBC voter registration guide, and a county government roles explainer covering the structure and responsibilities of county assemblies, governors, and MCAs.
Embedding pipeline. Each chunk is embedded using OpenAI text-embedding-3-small and stored in a pgvector table on Neon PostgreSQL. The pipeline runs as a script — re-indexing a document means re-running the script against the updated source, not retraining a model.
Retrieval. On a user query, the query string is embedded with the same model and a cosine-similarity search retrieves the top-k most relevant chunks from the vector store. The threshold is tuned to prefer precision over recall — a non-answer is better than a confidently wrong answer on civic content.
Generation. Anthropic Claude 3.5 Haiku receives the retrieved chunks as context alongside a system prompt that instructs it to answer only from the provided context, cite the source document in every response, and decline to speculate on questions the context doesn't cover.
Frontend. Next.js 14 App Router with a clean chat UI built in Tailwind CSS. The interface is intentionally minimal — a message input, a conversation thread, and a source citation displayed beneath each answer.
WhatsApp channel. A WhatsApp Business API webhook receives incoming user messages and routes them through the same RAG pipeline. The response — answer plus source citation — is sent back via the WhatsApp API. The pipeline is channel-agnostic; the web and WhatsApp interfaces share the same retrieval and generation logic.
Deployment. Frontend on Vercel. Backend API (embedding, retrieval, generation) on Railway.
Civic tech considerations
Civic tech engineering has constraints that don't apply to most product categories.
Data trust. Every answer must cite its source. In a politically sensitive context, users need to be able to verify what they're told — and the citation is what makes that possible. A confident answer without a source is worse than no answer at all.
Language. This is an English-first MVP. Swahili support is planned and affects both the embedding pipeline (Swahili chunks need to be embedded and retrieved correctly) and the prompt design (the generation model needs to respond in the language the user wrote in). This is not a trivial addition — it is a separate engineering workstream.
Accessibility. The WhatsApp channel is the accessibility layer. It ensures the tool works on low-bandwidth connections, low-end devices, and for users who would never navigate to a web application. Treating WhatsApp as a secondary channel would have been the wrong call.
Data freshness. IEBC registration deadlines change. County data changes. The embedding pipeline needs a regular refresh cadence — not a one-time index. This is an operational concern, not just an engineering one.
Delivered results
What I learned
Citation is a product requirement, not a UX detail. The decision to surface the source document in every answer changed how I structured the retrieval and generation layers. The prompt, the context format, and the response schema all had to be designed around making citation reliable — not bolted on afterwards.
RAG is a maintenance commitment, not a one-time build. The knowledge base is only as good as its last update. IEBC deadlines change, county structures get amended, and a civic tool that gives outdated information is actively harmful. Building the re-indexing pipeline as a first-class concern — not a script to run once — was the right call.
WhatsApp as a distribution channel changes the product. Designing for WhatsApp from the start meant keeping responses concise, structuring citations in plain text rather than markdown, and handling the stateless nature of webhook delivery. These constraints made the web interface better too — the discipline of writing for a constrained channel improved the quality of every response.
What's next
- Swahili language support — affects both the embedding pipeline and prompt design
- Live IEBC data integration for real-time registration deadlines
- County-specific ward and MCA data
- Potential partnership with civic NGOs for deployment at scale
For repository and implementation details: github.com/edogola4