Most chatbots fail Kenyan customers in one of two ways. Either they only understand the exact words on a menu, so a customer who types in Sheng gets "Sorry, I didn't understand", or they are clever enough to chat but guess the answers, including prices and opening hours. Both cost you sales.
We have been building a WhatsApp sales and booking bot that does neither. We are testing it now with a Nairobi beauty studio. Here is what it does and how it stays honest.
It answers from your own information
Every business has the same questions on repeat: where you are, when you open, how long a service takes, what the deposit policy is, whether you deliver. Instead of stuffing all of that into the bot's instructions and hoping it remembers, we load your own information into a searchable knowledge base: your policies, opening hours, location, service descriptions and frequently asked questions.
When a customer asks something, the bot searches that knowledge base first, using a search that matches both the meaning of the question and the exact words in it. It answers from what it finds and keeps track of which part of your information each answer came from, so your team can check it. If the answer isn't there, it says so and passes the chat to a person, rather than making something up.
That also means you update the bot by updating your information. Change your Saturday hours once, and the bot gives the new hours from then on.
It switches between English, Swahili and Sheng
Customers switch languages mid-conversation, sometimes mid-sentence. A customer might open in English, ask the price in Swahili and confirm a booking in Sheng. The bot follows the switch smoothly and keeps helping, without losing track of what the customer wants or asking them to start again in "proper" English. Whatever language the question comes in, it finds the right answer in your information.
We measure this rather than assume it. On our own test set of 30 customer questions about the business, the passage with the right answer came up in the bot's top three search results 93 per cent of the time, and 93 per cent again when the questions were asked in Swahili and Sheng. We keep adding to that test set as we see new ways customers ask.
It sells, books and takes M-Pesa, without guessing
Answering questions is only half the job. The bot can also show products, check free appointment slots, take a booking with a deposit and ask for payment. The rules that protect your money live in the code, not in the AI's instructions:
- The AI never sets a price. Prices, stock, free slots and totals are read from your records. The AI can look them up, but it has no way to set or change them.
- Only M-Pesa confirms payment. The bot sends an M-Pesa prompt to the customer's phone through Safaricom's Daraja API, and an order is marked paid only when Safaricom confirms a successful payment for the exact amount.
- A person is one message away. Complaints, refunds and anything that needs judgement go to your team, and the bot stays quiet in that chat until they hand it back.
- It follows WhatsApp's rules. It runs on Meta's official WhatsApp Cloud API, not a workaround that can get your number suspended.
We wrote about these rules in more detail in WhatsApp assistants that sell, book and take M-Pesa, and about the costs and consent rules in our guide to WhatsApp automation in Kenya.
Under the hood: how the retrieval works
This part is for technical readers. The pattern is retrieval-augmented generation (RAG): instead of asking the model to remember the business, we fetch the relevant passages at question time and let the model answer from them.
The stack
- Conversation and decisions: Claude, by Anthropic, in a tool loop. Knowledge search is one tool among the others for products, slots, bookings, payments and handover.
- Store: one Postgres table with a
vector(384)column (pgvector, HNSW index, cosine distance) and a generatedtsvectorcolumn over the same text (GIN index). No separate vector database to run. - Embeddings:
BAAI/bge-small-en-v1.5through fastembed, running on ONNX on the CPU. No API key, no account and no per-query cost. Each row records the model that embedded it, and search refuses a store built with a different model, because vectors from two models can't be compared.
Chunking
The business's playbook is split by section. Long bullet lists are split again into one chunk per bullet so each chunk covers one topic, while numbered procedures stay whole, because a sales procedure cut in half loses its meaning. The catalogue becomes one chunk per product or service, plus chunks for hours, location, payment methods, delivery areas and the booking window. Every chunk carries a breadcrumb title that is embedded with the text, so a short passage keeps its context, and a stable, readable id such as business:hours. Template lines that the business hasn't filled in yet are dropped rather than indexed, so the bot never retrieves an empty policy and guesses the rest.
Prices never enter the store
The catalogue chunker reads only named fields, so price, fee, deposit and stock fields can't reach a passage. A second pass replaces any currency amount left in free text ("KES 6,000", "3500/=", "12k", "2,500 bob") with a pointer to the pricing tools, and the search tool runs that pass again on its output. Tests check that no catalogue amount appears in any chunk, and that a passage claiming a different price leaves the M-Pesa amount at the database price.
Hybrid search with reciprocal rank fusion
Vector search finds passages that mean the same thing; Postgres full-text search finds passages that share the exact words, which matters for place names and product names. Chatty questions rarely contain every word of a passage, so the full-text query joins words with OR rather than AND. Each retriever returns its top 20, and the two rankings are merged with reciprocal rank fusion: each passage scores the sum of 1/(60 + rank) across both lists. RRF uses only ranks, so a cosine distance and a full-text rank never have to be put on the same scale. The tool returns the top four passages.
Citations, and retrieved text treated as data
The tool result tells the model that passages are reference data, not instructions, and that they never set a price, stock level, deposit or slot. That is a guard against prompt injection through the documents. The model cites each fact with a source id. Before a reply goes out, the code keeps only ids that the search actually returned in that turn, logs them, logs any invented id as a warning, and strips the tags so the customer sees a clean message.
Swahili and Sheng
Claude already reads and writes English, Swahili and Sheng, which is what lets the bot follow a customer who switches language mid-conversation. The gap was retrieval: the passages are in English and the embedding model is English-only. We measured three fixes on the same 30 questions asked in Swahili or Sheng:
| Setup | Hybrid recall@3 | Hybrid recall@5 |
|---|---|---|
| English model, question searched as typed | 70% | 90% |
| Multilingual model (multilingual-e5-large), as typed | 90% | 97% |
| Multilingual MiniLM, as typed | 73% | 83% |
| English model, Claude rewrites the query in English | 93% | 100% |
| English questions, for comparison | 93% | 100% |
We went with the last approach. The search tool asks Claude for "the customer's question rewritten as a short English search query", then the reply goes back in the customer's language. That costs nothing extra, because Claude is already reading the message. A glossary of about 80 Swahili and Sheng words and stems widens the keyword search as a safety net (saa to hours, wapi to location, leta to delivery). Swahili attaches prefixes to verbs, so "mnafunga" (you close) has to match the stem "funga", which is why stems of four or more letters match inside a word.
Two lessons from the comparison. First, check a model's language list: the multilingual MiniLM model wasn't trained on Swahili and did worse than the English model. Second, fusion is only as good as its inputs: on raw Swahili, a near-random vector ranking fused with a strong keyword ranking pulled the result down, because RRF rewards agreement. The large multilingual model works, but it is a 2.1 GB download and about eight times slower per search, so we keep it in reserve for paths with no LLM in front.
Evaluation
Every question in the test set is labelled with the passage that should answer it, and we score recall@k (the share of questions where a correct passage is in the top k) and mean reciprocal rank:
| Mode | recall@1 | recall@3 | recall@5 | MRR |
|---|---|---|---|---|
| Vector only | 80% | 90% | 90% | 0.84 |
| Keyword only | 67% | 87% | 87% | 0.76 |
| Hybrid (RRF) | 83% | 93% | 100% | 0.89 |
A hybrid search takes about 6 to 18 milliseconds on a warm local database. The honest caveats: 30 questions written by us over a corpus of 29 passages is a small, friendly test, and we expect the numbers to fall as the business adds its own policies and FAQs. The real test set will come from the business's own chats, with names and numbers removed.
What comes next
- Answer-level evaluation: checking that each cited passage actually supports the claim, and adding questions with no answer in the store, where the right reply is "I'll check with the team".
- A guardrail that fails any reply containing a shilling amount that no pricing tool returned in that turn.
- A cross-encoder reranker over the fused top 10, and a filter on chunk type for product versus service questions.
- Reindexing automatically whenever the catalogue changes, so the store can't go stale.
Where it stands today
To be clear about what we can and can't claim: the bot is built and running on a test number while we finish testing it with the studio. It is not serving customers yet, so we have no sales figures to share, only how it is built and how it performs in our tests. We are also preparing a WhatsApp assistant for parcel deliveries on the same foundations.
What your business would need
- Your price list, products or services, and how stock or appointment slots are tracked today.
- The answers you give most often: hours, location, delivery, deposits, refunds.
- An M-Pesa till or paybill in the business's name.
- A WhatsApp number for the business, and someone on your team to take over chats when needed.
We set up the rest: the WhatsApp Business Platform, the knowledge base, M-Pesa, the handover to your team, and the tests that keep the bot from breaking when we change it.
Want a WhatsApp sales bot for your business?
Book a free 30-minute discovery call. We'll look at how your customers ask, order and pay today, and what a bot would take off your hands. You leave with clear next steps, or an honest "we're not the right fit".

