Running a kirana store’s inventory, billing and khata from Telegram.
Live on Telegram · Open source
- Zodvalidated tool calls for every action
- Atomicnon-negative stock updates in Postgres
- PDF + PPTGST invoices and reports, delivered in chat
Why I built it
the problem, minus the buzzwordsA kirana owner won’t learn a new dashboard. But letting an LLM write directly to inventory and billing is risky: one bad tool call can oversell stock or corrupt a customer’s balance.
How it works
chat in, validated tools, safe writes- Telegram webhook1
Fastify receives updates; idempotency keys drop duplicate deliveries.
#ingress
- Agent2
Vercel AI SDK agent with durable shop memory that survives conversation resets.
#llm
- Zod tools3
Inventory, draft billing, GST line calculations, khata, analytics.
#tools
- PostgreSQL4
Drizzle with atomic, non-negative stock updates and conditional locks.
#guardrail
- Artifacts5
Renders GST invoice PDFs and PowerPoint reports and sends them back into the chat.
#output
Built with TypeScript, Node.js, Fastify, Vercel AI SDK, Zod, PostgreSQL, Drizzle.
Decisions I made
and why. mostly why.1.Guardrails live in the database
The model is told not to oversell, but the real guarantee is an atomic update that refuses to take stock below zero, plus conditional locks against race conditions. The model can be wrong; the data can’t.
2.Webhooks are idempotent
Telegram can redeliver an update. Without idempotency the same bill could be created twice, so every update is processed once.
3.Bills are drafts first
Multi-turn bill editing lets the owner say “remove the second item” or “make it 3 kg” before finalising, which matches how billing actually happens at a counter.