AtendeLink.
WhatsApp customer service with several people on one number, and an AI agent that follows the flow the business designed.


The problem
Manual work
Small businesses serve customers on WhatsApp with several people sharing one number. They need to know who is handling each customer, automate the start of a conversation and sell inside the chat, while staying in control of what the bot says. AtendeLink is not omnichannel, on purpose: it is WhatsApp plus internal chat, connected to LinkDev’s ERP Web.
What I built
AtendeLink is a LinkDev product, and I have worked at LinkDev since 2021. On it, I built the visual flow builder with the AI Agent block, which answers in text and voice, plus a playground that simulates a flow without sending anything to WhatsApp. I built the RAG knowledge base, WhatsApp sales (orders through the flow, abandoned carts and commissions), the CRM for leads, customers and documents, and Stripe subscriptions with Checkout, the customer portal and webhooks. I also added per-company modules, moved the screens to shadcn and Tailwind 4, fixed the isolation between companies and wrote the specs that guided each stage.
Technical decisions
01Knowledge per company, keys kept on the server
Each company has its own knowledge base. Text is split into chunks, embedded with text-embedding-3-small and stored in pgvector, and search only looks at that company’s chunks. The AI key never comes back in a listing or over the socket, and failures use typed errors (ERR_AI_*) so the UI knows what went wrong.
Where it lives in the code: services/KnowledgeServices/chunkText.ts · embeddings.ts · searchKnowledge.ts
02The flow is a graph you can simulate
The flow drawn in the front end with @xyflow/react is saved as a graph and validated on save. The engine walks its blocks: start, message, menu, question, AI agent, catalog, checkout, condition, transfer and end. The same engine has a simulation mode, and the playground uses it to run a conversation through the flow, agent block included, without sending anything to WhatsApp.
Where it lives in the code: services/FlowServices/FlowEngine.ts · flowGraph.ts · SimulateFlowService.ts · aiAgent.ts · salesTools.ts
03Stripe webhooks checked on the raw bytes
The webhook route takes the raw body before any JSON parser touches it, because Stripe signs the exact bytes. An event without a valid signature is rejected. A forged POST activates nothing.
04Spec before code
Features, rules and the screen standardization were written up as specs first, and the standardization moved in stages.
Where it lives in the code: docs/specs/
Numbers
64
models in the product
210
migrations
40
pages
Stack
- Node.js
- TypeScript
- Express
- Sequelize
- PostgreSQL 16
- pgvector
- Redis
- Bull
- Socket.io
- Baileys
- OpenAI SDK
- Stripe
- React 19
- Vite
- Tailwind 4
- shadcn/ui
- Electron
- Docker
Screens



Kaelith