A salesperson that takes orders by chat — no salary, no schedule.
Yerbi is a B2B ordering agent for a yerba mate roaster. It reads natural language, quotes from the live catalog, builds the order, asks for confirmation, and writes it straight into the CRM — all inside Telegram.
Orders arrive by chat — scattered, and at every hour.
- →After-hours messages pile up overnight, on weekends and holidays.
- →The window that matters is minutes — while the client is still deciding.
- →Passing every order into the CRM by hand is slow and loses traceability.
- →A menu-driven bot ("press 1") feels robotic and gets abandoned.
Seven nodes, one clean answer.
The flow is event-driven. Each Telegram fragment is buffered; a short silence window merges them before the agent ever runs — so three quick messages produce a single, considered reply.
Telegram Trigger
Every incoming message hits the bot's webhook and starts a run. Nothing is answered yet.
Append to the message buffer
The fragment is stored in a per-chat buffer (Redis / MongoDB) with a timestamp. This is what lets the agent treat several messages as one.
Wait, then the silence gate
The run waits a few seconds. If a newer fragment arrived meanwhile, this run aborts — only the last one survives. That guarantees exactly one reply per burst.
Who is this client?
A Salesforce lookup matches the Telegram chat to an Account. Unknown clients are routed into a multi-step registration flow first.
The Claude agent
The merged message plus client context is handed to the agent. It reasons about intent and decides which tool to call — with conversation memory across turns.
Tools hit Salesforce
Three tools do the real work: read the catalog, read past orders, and create an order. Creation goes through an Apex endpoint so it's one atomic transaction.
One answer back
The agent's response is sent to Telegram and the exchange is logged. If the model ever fails, a fallback branch still replies — the client is never left on read.
The hard part wasn't wiring the AI. It was making it trustworthy.
A few of the decisions and dead-ends along the way:
Fragmented messages
Answering each fragment broke the conversation. My first buffer did a read-modify-write and, under near-simultaneous messages, occasionally let two runs through — a real race condition.
Stopping hallucination
A bot that invents a price or a stock number is worse than no bot. Early on it would happily improvise.
Orders that can't half-exist
An order created halfway in the CRM is corrupt data. It has to be all or nothing.
The backend disappeared
The free Salesforce dev org deactivated itself after inactivity, taking the whole data layer with it right before a demo.
Never leave a client on read
If the model provider hiccups, the customer still deserves an answer.
Keeping business rules out of the prompt
Internal states, explicit confirmation before creating, never exposing internal IDs — too important to leave to a language model.
The stack, and what each part does.
| Service | Role | Cost |
|---|---|---|
| Telegram Bot API | Receive & send messages via webhook | Free |
| Anthropic · Claude | Agent reasoning & tool-calling | Paid |
| Salesforce REST + Apex | Catalog, orders, atomic creation | Dev org |
| MongoDB Atlas | Debounce broker + conversation history | Free M0 |
| n8n | Orchestrates the whole flow | Self-host |