vm@portfolio
Language
Case study · Conversational AI

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.

n8nClaudeSalesforce + ApexMongoDBTelegram
Yerbi
online
Message…
The problem

Orders arrive by chat — scattered, and at every hour.

A client types “hola”, then “mandame 2 tradicionales”, then “y 1 barbacuá” — three messages, one intent. The sales team has working hours; the client doesn't. By the time someone replies, they've already bought from whoever answered first.
  • 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.
How it works

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.

Step 1 · Intake

Telegram Trigger

Every incoming message hits the bot's webhook and starts a run. Nothing is answered yet.

Telegram TriggerExtract Fields
Step 2 · Buffer

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.

Load BufferAppendSave Buffer
Step 3 · Debounce

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.

WaitReload BufferRead & Clear (gate)
Step 4 · Identify

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.

Identify ClientClient Found?Registration
Step 5 · Reason

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.

Prepare PromptAI AgentMemory
Step 6 · Act

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.

search_catalogget_orderscreate_order · Apex
Step 7 · Reply

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.

Send ResponseLog ConversationFallback
The process

The hard part wasn't wiring the AI. It was making it trustworthy.

A few of the decisions and dead-ends along the way:

Concurrency

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.

→ Event-driven broker + a silence-window gate that merges the burst and lets a single run reply.
Reliability

Stopping hallucination

A bot that invents a price or a stock number is worse than no bot. Early on it would happily improvise.

→ Strict grounding + low temperature: catalog, prices and orders may only come from tools, never from the model.
Integrity

Orders that can't half-exist

An order created halfway in the CRM is corrupt data. It has to be all or nothing.

→ A custom Apex REST endpoint creates the Opportunity and its line items in one server-side transaction.
Infra reality

The backend disappeared

The free Salesforce dev org deactivated itself after inactivity, taking the whole data layer with it right before a demo.

→ Rebuilt the data layer as a mockable module so the agent runs standalone, with the real CRM integration kept in code.
Resilience

Never leave a client on read

If the model provider hiccups, the customer still deserves an answer.

→ Two retries plus an error branch with "on error → continue" — a reply is guaranteed.
Product

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.

→ Business logic lives server-side in Salesforce; the prompt only handles the conversation.
Under the hood

The stack, and what each part does.

ServiceRoleCost
Telegram Bot APIReceive & send messages via webhookFree
Anthropic · ClaudeAgent reasoning & tool-callingPaid
Salesforce REST + ApexCatalog, orders, atomic creationDev org
MongoDB AtlasDebounce broker + conversation historyFree M0
n8nOrchestrates the whole flowSelf-host
Yerbi

Portfolio case study. The brand "Yerbatera del Litoral" and all data are fictional; the integration (Telegram · n8n · Claude · Salesforce · MongoDB) is real. Built by Valentino Millimaci.