A friend in Varanasi types her grocery list like this:
do kilo aata aur 1 litre doodh That is Hindi written in English letters (Hinglish). No search box on a seller's catalog understands it, and no AI agent today can take that sentence, find a nearby kirana store, and place the order safely.
So I built Haat (हाट, the village market): an open-source gateway that lets personal AI agents shop from sellers on ONDC, India's open commerce network, in the language people actually type, and never places an order without the person's explicit approval.
The problem: two protocols that don't talk
- Personal AI agents are starting to speak Poppy (the Personal Agent Protocol, announced by Sierra and Meta in October 2026).
- Lakhs of Indian sellers already speak Beckn, the protocol under ONDC, with machine-readable catalogs and structured orders.
Small sellers will not implement a new protocol one by one. Without a bridge, they are invisible to the agents their customers use. Haat is that bridge: a Poppy "Company" on one side, an ONDC buyer app on the other.
When I searched on 1 November 2026, I found Poppy SDKs and separate ONDC MCP servers, but nothing connecting the two. That is a search result, not proof. If you know of related work, I would like to hear about it.
The end-to-end flow
"do kilo aata aur 1 litre doodh" -> 2 x Whole Wheat Atta 1 kg, 1 x Toned Milk 1 L, Kashi Kirana Store -> "Total ₹197, pay on delivery. Approve?" -> yes -> order KKS-1001 (placed once) Part 1: Parsing Hinglish without a model
I did not want an LLM deciding what ends up in a shopping basket. So the parser is rule-based and driven by data (a lexicon), and every step is testable.
The pipeline:
- Normalise the text. Digits of every Indian script (२ ২ ௨ ౨) become ASCII digits, and zero-width characters are removed.
- Split into items on separators (
aur,and,और, commas, the danda।). - Read quantities: a digit or number word, then a unit.
- Drop stopwords ("mujhe", "chahiye").
- Match Latin-letter words through a phonetic key (
eebecomesi,oobecomesu,dhbecomesd). Words in Indian scripts are compared as written. The longest match wins. - No match? Search the raw words as typed, so nothing is silently lost.
Two bugs the tests now pin:
- Dropping a final vowel made makhana (fox nuts) equal makhan (butter). I removed that rule and added a regression test.
- "do" means both "two" and "give". In "atta de do" it is the verb. A number word only counts if something follows it.
Coverage today is 130 grocery products in Hindi, Bhojpuri, Marathi, Bengali, Tamil, Telugu, Gujarati, Kannada, Malayalam, Punjabi and Odia, each in its own script and in Latin letters.
An honest caveat: only Hindi was written by hand. The other languages were drafted by a machine and have not been reviewed by native speakers. I say so in the docs and in the README. The tests prove the parser behaves consistently on the data, not that the words are right. This is the easiest place to contribute, and you don't need to write any TypeScript.
Part 2: The approval gate
The rule I would not compromise on: a language model never decides approvals. The person approves one exact revision of an order, through the protocol, and the model never sees tokens, keys, OTPs or full phone numbers.
Two details matter most:
At most once, even across restarts. An approved operation runs at most once. If the process dies mid-order and comes back, it must not order twice.
Unknown is not failed. If an action may have happened (a timeout, a connection reset, a 5xx with no NACK, a callback that never came), Haat throws OutcomeUnknownError and answers 503 Retry-After. It never says "failed". Telling a user "failed" when the order actually went through gets them to retry, and then they get two bags of atta. Only not_sent or rejected release the approval.
Seller URLs come from the registry, and prices come from the seller's own quote. Nothing the agent claims is trusted.
Verified, with numbers from real runs
- 126 automated tests (unit and end-to-end over real HTTP), all passing, with lint and typecheck clean.
- The official Personal Agent Protocol validator, run over real HTTPS: 99 checks passed, 0 failed, 0 warnings. The 22 skipped checks cover features Haat doesn't offer (MCP, browser join, Device and Mediated Sign-In).
- No runtime dependencies. It uses Node 22.18+ running TypeScript directly, and
node:sqlitefor storage.
What it does not do (yet)
I would rather tell you than have you find out:
- It works with a local mock network of ONDC-style sellers. It has not touched a real seller or real money.
- A live ONDC connection needs a legal entity, whitelisting and ONDC's approval.
- Sign-in codes need a real SMS provider.
- It is not affiliated with ONDC, Sierra, Meta or the Personal Agent Protocol project.
Try it in one minute
git clone https://github.com/techsaurabh-394/haat-gateway.git cd haat-gateway npm install npm run demo The demo asks you to approve the order in your terminal.
Help me with this
Haat is open source (MIT) and PRs are welcome. Most contributions need no TypeScript:
- Review the machine-drafted Tamil, Bengali, Marathi or other language data
- Teach the lexicon how your city spells pyaz
- Add a domain pack or a mock seller from your neighbourhood
- Improve the docs
Start with CONTRIBUTING.md and the good first issue label.
If you build agents, I would like to know how you handle the "unknown outcome" case. And if you speak one of those languages, tell me which words I got wrong.
Built by Saurabh Pathak, AI engineer and full-stack developer from Varanasi. GitHub | LinkedIn




