Assistants that answer on the channels your customers actually write on, out of your own information, and hand the conversation to a person the moment it goes beyond their role.
We deploy text assistants on our own platform, aichat.md, which runs in production. The work means channels connected with our own code, an indexed knowledge base, tools that execute inside your systems, and a handover path to a person recorded in the database.
Construit dejaServiciul se sprijină pe o platformă proprie aflată în producție, nu pe o promisiune. `https://aichat.md` răspunde public (307 către `/ro`, verificat 06.09.2026), iar comportamentele descrise mai jos sunt citite din schema bazei de date și din rutele platformei, cu fișier și linie: pragurile căutării, tipurile de unelte și timpul lor maxim, stările firului de discuție, jurnalul de preluare. A doua implementare proprie citată este funcția de catalog de magazin (`storeCatalog.service.js` plus trei unelte încorporate), scrisă ca funcție de platformă în locul uneltelor per client. Ce nu susține dovada spunem la fel de explicit: mesajele din șablon WhatsApp nu există în cod, deci nu promitem mesaje proactive în afara ferestrei de 24 de ore.
Un asistent util nu e unul care scrie frumos, ci unul care e conectat la informația reală a afacerii și care știe unde se oprește. Lucrarea noastră începe de la canalul pe care scriu clienții tăi și se termină la persoana care preia discuția când asistentul nu mai are ce să spună. Între ele punem cunoștințele, uneltele și limitele.
Platforma pe care construim este aichat.md, făcută de noi și aflată în producție. Asta schimbă natura serviciului: nu integrăm o cutie neagră a altcuiva, ci configurăm un sistem în care putem citi orice prag și putem schimba orice comportament. Când spunem că răspunsul folosește implicit cinci fragmente din documentele tale, cu prag de similitudine 0,70 și 30% pondere pe potrivirea de cuvinte, sunt valori din schema bazei de date, nu o descriere de broșură.
Canalele cu cod propriu, verificate la 06.09.2026, sunt șase: Facebook Messenger, Instagram Direct, Telegram, 999.md, widgetul de pe site și WhatsApp Business prin Cloud API pe Graph v22.0. Fiecare are propriul modul, nu o casetă bifată — iar diferențele dintre ele contează în practică: Messenger poate afișa un carusel de produse, Instagram nu, pentru că Meta nu oferă șabloane generice pe Instagram.
Partea pe care clienții o subestimează este predarea către om. În aichat ea nu e o promisiune, ci o stare în baza de date: firul este `bot` sau `human`, jurnalul de preluare distinge preluarea de către un om, revenirea la bot și reactivarea automată, iar firul are separat o stare de respectare a timpului de răspuns — `ok`, `warning`, `breached`. Se poate arăta, la sfârșit de lună, câte discuții au fost preluate și în cât timp.
What it covers
The work, piece by piece
Conectăm canalul și verificăm ce se întâmplă când tace
Șase canale au cod propriu în platformă: Messenger, Instagram Direct, Telegram, 999.md, widget web și WhatsApp Business Cloud API pe Graph v22.0. Conectarea Meta se face prin Embedded Signup. La fiecare canal verificăm și cazul urât, nu doar primul mesaj reușit: un token de pagină expirat oprește canalul în tăcere, nu cu eroare vizibilă, de aceea platforma are monitorizare de tokenuri și notificare la expirare.
Indexăm cunoștințele și fixăm pragurile după care caută
Documentele și paginile se taie în fragmente cu hash de conținut și embeddinguri `text-embedding-3-small`. Valorile implicite pe care le pornim și apoi le reglăm: cinci fragmente pe întrebare, prag de similitudine 0,70, căutare hibridă, pondere 0,30 pe potrivirea de cuvinte, atribuirea sursei pornită. Fiecare interogare se poate jurnaliza cu fragmentele returnate, scorurile și timpii — deci „de ce a răspuns așa” are răspuns cu date, nu cu presupuneri.
Legăm uneltele de sistemele care execută
O unealtă poate fi un webhook către sistemul tău, cu metodă și antete la alegere, o bucată de cod JavaScript rulată de platformă, sau o unealtă încorporată în platformă. Fiecare are un timp maxim de execuție, implicit 15 secunde. Consecința practică, spusă înainte de contract, nu după: o integrare care răspunde în 40 de secunde trebuie făcută asincron, nu forțată în conversație.
Catalog viu, conectat cu adresa magazinului
Pentru magazine există trei unelte încorporate — `store_catalog_search`, `store_catalog_match`, `store_catalog_product` — peste un serviciu comun de catalog. Pentru WooCommerce, Store API este publică, deci magazinul se conectează cu adresa site-ului, fără chei de acces. Înainte, catalogul se scria ca unealtă separată pentru fiecare client; a devenit funcție de platformă tocmai pentru că varianta cu unelte scrise pe nume de client nu se putea întreține.
Predare către om, cu evidență
Firul are stare explicită `bot` sau `human`. Jurnalul de preluare cunoaște trei acțiuni: preluare de către un om, revenire la bot și reactivare automată. Separat, firul are stare de respectare a timpului de răspuns: `ok`, `warning`, `breached`. Modulul de preluare din platformă are coadă și roluri. Stabilim din prima discuție cine preia și în cât timp, pentru că starea aceasta se măsoară de la primul fir, nu se adaugă mai târziu.
Voce în conversația scrisă
Nota vocală primită pe WhatsApp sau Telegram se transcrie cu `whisper-1` și intră în conversație ca text. Răspunsul poate pleca înapoi ca voce, prin `tts-1` sau prin ElevenLabs, cu setări de stabilitate și similitudine per voce. Pentru cine dictează în loc să scrie — un meșter pe teren, un șofer — asta e diferența dintre canal folosibil și canal decorativ.
Traducere în conversație, într-un singur sens azi
Răspunsul operatorului poate fi rescris în limba clientului, cu tonul agentului și fără să adauge fapte. Sensul invers — mesajul clientului tradus pentru operator — nu există în cod la data verificării, deci operatorul citește originalul. Îl spunem pentru că e diferența dintre o echipă care poate servi un client rus sau englez și una care crede că poate.
Comportamentul la mesaje duble și la rafale
Webhookul Meta chiar retrimite același mesaj: dedublarea se face pe identificatorul mesajului, cu 120 de secunde de memorie. Iar când cineva scrie trei rânduri unul după altul, ele se adună într-un tampon de 15 secunde și primesc un singur răspuns, la tot ce a scris omul, nu trei răspunsuri parțiale.
Modelul nu e legat de un furnizor
Apelurile trec printr-un gateway propriu la `api.megapromoting.com/v1`, care vorbește forma OpenAI pentru toți furnizorii din spate. Modelul se alege per asistent și se poate schimba fără să rescriem integrarea. Pentru embeddinguri folosim `text-embedding-3-small`.
What it looks like
The route, step by step.
01
Alegem canalul și persoana care preia
Un canal, un public, un rezultat urmărit. În aceeași discuție se stabilește cine preia firele marcate `human` și în cât timp. Livrăm: lista scenariilor pe care asistentul le acoperă și lista explicită a celor pe care nu le acoperă.
02
Conectăm sursele și verificăm ce iese din ele
Documentele și paginile intră ca surse de cunoștințe. La cataloage verificăm produsele extrase unul câte unul acolo unde contează prețul. Livrăm: sursele indexate, pragurile de căutare setate pentru cazul tău și un set de întrebări de control cu răspunsurile obținute.
03
Legăm uneltele și testăm cazul lent
Webhook către CRM sau ERP, cod pentru transformări proprii, unealtă încorporată pentru ce există deja. Testăm cazul lent și cazul de eroare, nu doar cel fericit, pentru că limita de 15 secunde e cea care decide. Livrăm: uneltele configurate și comportamentul documentat la depășirea limitei.
04
Deschidem canalul cu monitorizare pornită
Canalul intră în funcțiune cu monitorizarea tokenului activă și cu preluarea umană exersată cel puțin o dată pe un caz real. Livrăm: acces la panou, procedura de preluare și punctele în care sistemul se oprește singur.
05
Citim jurnalele și reglăm
După primele conversații reale se uită la jurnalul de interogări: ce a găsit, cu ce scor, în cât timp. De acolo se reglează pragul, numărul de fragmente sau textul sursei. Livrăm: lista modificărilor făcute și motivul fiecăreia.
Drumul unui mesaj
Datele
What we touch, where it lives, and how long it stays
The questions anyone with a data protection officer asks — asked here before they do.
Unde stau conversațiile
MySQL, pe serverul propriu din Microsoft Azure. Schema are peste 80 de tabele modelate în Prisma, cu tabele separate pentru firele Meta, firele Telegram, firele 999.md, comentarii, etichete, note interne și jurnal de audit.
Tokenurile de canal se păstrează criptate
Tokenul WhatsApp e stocat criptat Fernet, cu revenire la text simplu doar pentru înregistrările vechi. Mesajele au propriul modul de criptare în serviciul de canale. Există monitorizare de tokenuri și notificare la expirare.
Ce vede widgetul și de unde
Widgetul are o listă de origini permise per asistent. Comportamentul implicit trebuie știut: dacă lista e goală, verificarea trece — e o alegere de compatibilitate cu instalările vechi, scrisă ca atare în cod. Înseamnă că restricționarea pe domeniu se configurează explicit la fiecare implementare care o cere; noi o configurăm, nu o presupunem.
Ce date personale intră fără să le ceri
Câmpul liber al unei conversații poate conține orice — un număr de telefon, o adresă, o problemă medicală. Nu se poate opri tehnic, dar se poate trata: se stabilește ce se păstrează, cât, cine are acces și ce se instruiește echipa să nu ceară pe canal. Registrul de prelucrări al implementării se scrie în același timp cu implementarea, nu după.
Termenul de păstrare
Se stabilește per implementare și se scrie în politica publicată a clientului. Regula pe care o aplicăm la noi și o cerem și în proiecte: dacă o modificare de cod schimbă ce se colectează, cui ajunge sau cât se păstrează, politica publicată se modifică în același commit.
A case
A price question that starts in Instagram and ends with a person
Situația
Un magazin cu catalog online primea întrebări de preț în DM-urile de Instagram și pe Messenger. Aceleași cinci întrebări, toată ziua, iar răspunsul corect exista deja pe site.
Ce am construit
Am conectat cele două canale, am indexat sursele și am legat catalogul prin uneltele încorporate de magazin, care pentru WooCommerce citesc Store API publică — deci fără chei de acces în platformă. Am setat tamponul de concatenare, ca trei mesaje scrise la rând să devină o singură întrebare, și am scris explicit ce nu are voie asistentul să facă. Pe Messenger am pornit caruselul de produse, cu cele trei condiții de care depinde; pe Instagram am rămas la text plus poză, pentru că Meta nu oferă acolo șabloane generice.
Ce a ieșit
Întrebările de preț și disponibilitate primesc răspuns cu produsul afișat și link. Ce iese din catalog trece pe starea `human` și ajunge la persoana desemnată, cu tot contextul discuției. Jurnalul de interogări arată ce a găsit asistentul, cu ce scor și în cât timp, deci reglajul se face pe date.
Ce nu spune cazul
Rezultatul depinde de calitatea catalogului. Un preț greșit pe site devine un preț greșit în conversație — asistentul citește sursa, nu o corectează. Și nu am măsurat reducerea volumului de muncă a echipei, deci nu o afirmăm ca rezultat.
Întrebări
What people ask us before they call
Poate scrie el primul pe WhatsApp unui client care n-a mai scris de o săptămână?
Nu. Și motivul e la Meta plus o lipsă reală la noi, spuse amândouă. În afara ferestrei de 24 de ore de la ultimul mesaj al clientului, Meta respinge textul liber cu eroarea 131047, iar platforma marchează mesajul ca eșuat și afișează eroarea în loc să pretindă că a plecat. Trimiterea în afara ferestrei cere mesaje din șablon aprobate de Meta, iar acelea nu există în codul nostru — o căutare după tipul `template` pe tot codul întoarce zero rezultate. Deci: răspuns în fereastra de 24 de ore, da; campanie proactivă pe WhatsApp, nu, până se implementează șabloanele.
Pe ce canale funcționează efectiv, azi?
Șase, cu cod propriu verificat la 06.09.2026: Facebook Messenger, Instagram Direct, Telegram, 999.md, widget web și WhatsApp Business Cloud API. Un audit intern mai vechi a găsit cod și pentru SMS și e-mail; nu le-am reverificat la această dată, deci nu le trecem ca disponibile fără o verificare pe implementarea concretă. Un canal apărut între timp nu se presupune conectat.
Integrarea cu 999.md este oficială?
Nu este o integrare de partener cu API public. Funcționează cu sesiunea contului tău: platforma îți cere valoarea cookie-ului de sesiune din browserul tău și o folosește ca să citească și să răspundă la mesaje. Consecința practică, spusă înainte: dacă 999.md schimbă mecanismul de sesiune, integrarea se oprește și trebuie reconectată. Cine nu acceptă riscul ăsta nu ar trebui să pornească pe canalul ăsta.
De unde știe răspunsul și ce face când nu-l știe?
Caută în sursele tale cu o căutare hibridă — implicit cinci fragmente, prag 0,70, 30% pondere pe cuvinte, restul semantic — și poate atașa sursa la răspuns. Când nu găsește, calea proiectată e predarea către om: firul trece pe starea `human`, iar jurnalul înregistrează cine a preluat și când. Există și revenire automată la bot, tot ca acțiune înregistrată.
Poate arăta produse cu poză și preț?
Pe Messenger, da — carusel de carduri. Pe Instagram, nu: Meta nu oferă șabloane generice pe Instagram, deci acolo rămâne text plus poză. Caruselul cere trei lucruri simultan: să fie pornit în configurația asistentului, unealta să întoarcă cel puțin două produse, iar instrucțiunea asistentului să ceară listă cu preț și link — pentru că detectorul se uită la textul agentului, nu doar la date. Dacă lipsește oricare din trei, caruselul nu se construiește. Le configurăm pe toate trei, dar e util să știi de ce.
Cine răspunde clientului care scrie în rusă echipei care vorbește română?
Răspunsul operatorului se poate rescrie automat în limba clientului, păstrând tonul agentului și fără să adauge fapte — asta funcționează. Sensul invers, mesajul clientului tradus pentru operator, nu există în cod la data verificării. Practic: clientul primește răspuns în limba lui, dar operatorul citește mesajul original. Dacă vă trebuie și sensul celălalt, e o lucrare de făcut, nu o setare de bifat.
Ce se întâmplă dacă un client trimite același mesaj de două ori?
Nu primește două răspunsuri. Duplicatele se filtrează pe identificatorul mesajului, cu 120 de secunde de memorie — webhookul Meta chiar retrimite. Iar mesajele scrise unul după altul se adună într-un tampon de 15 secunde și primesc un singur răspuns, la tot.
Cu ce model AI răspunde și ce se întâmplă dacă vreau altul?
Apelurile trec printr-un gateway propriu la `api.megapromoting.com/v1`, care vorbește forma OpenAI pentru toți furnizorii din spate; modelul se alege per asistent. Schimbarea modelului nu cere rescrierea integrării. Pentru embeddinguri folosim `text-embedding-3-small`; schimbarea modelului de embedding, în schimb, cere reindexarea surselor — nu e același lucru.
Ce nu face acest serviciu?
Nu face voce la telefon — aceea e altă platformă a noastră, Kallina, și e altă lucrare. Nu trimite mesaje proactive pe WhatsApp, din motivul de mai sus. Nu generează PDF-uri și nu atașează fotografiile primite la o comandă — la data verificării, fotografia primită doar se marchează. Și nu garantăm procente de reducere a volumului de muncă: nu avem măsurătoarea, deci nu o afirmăm.
Pe ce se sprijină fiecare afirmație de mai sus (21 surse)
Firul are stare bot|human; jurnalul de preluare are trei acțiuni: human_takeover, bot_takeover, auto_reactivationschema.prisma:1728-1731 și 1647-1651
Firele au stare de respectare a timpului de răspuns: ok / warning / breachedschema.prisma:1733-1737 (enum MetaThreads_sla_status)
Modulul de preluare de la bot către om, cu coadă și roluri:modul de 808 linii
Modelele trec printr-un gateway propriu la api.megapromoting.com/v1, în forma OpenAI pentru toți furnizoriiwidget.routes.js:1752, 1768, 1863 (embeddinguri la 1468)
WhatsApp: Cloud API pe Graph v22.0, conectare prin Embedded Signup, token stocat criptat Fernetwhatsapp.service.js:1-44; whatsapp-oauth.service.js:5-30
În afara ferestrei de 24 h Meta respinge textul liber cu eroarea 131047, iar mesajul e marcat eșuatwhatsapp.service.js:27-30
Mesajele din șablon WhatsApp nu există în cod: o căutare după tipul `template` întoarce zero rezultate; se trimite doar tipul `text`main.py:11116:verificat prin grep pe tot codul, audit 01.09.2026
Integrarea 999.md folosește cookie-ul de sesiune al contului clientului, nu un API de partenertrei9.routes.js:22-33
Dedublare pe identificatorul mesajului cu 120 s memorie, tampon de concatenare 15 sREADME.md:140-141
Widgetul are listă de origini permise per asistent, iar o listă goală lasă verificarea să treacăwidget.routes.js:190-205 („fallback open if no allowlist configured”)
Notele vocale se transcriu cu whisper-1; răspuns vocal prin tts-1 sau ElevenLabswhisper.py:20, 29-35:elevenlabs_voice.py:16-25; transcriere WhatsApp în aichat_fb/main.py:11231-11249
Rescrierea răspunsului operatorului în limba clientului există; sensul invers, client → operator, nu existămain.py:9535 (build_operator_rewrite_messages); audit 01.09.2026
Catalog de magazin ca funcție de platformă: trei unelte încorporate peste un serviciu comun; WooCommerce prin Store API publică, deci fără cheistoreCatalog.service.js:unelte store_catalog_search / store_catalog_match / store_catalog_product, configurate în agent_tools.builtin_config
Instagram nu suportă carusele (Meta nu are șabloane generice pe Instagram); caruselul pe Messenger cere trei condiții simultanemain.py:8154; detectorul verifică textul agentului, nu datele (_looks_like_product_catalog)
Fotografia primită doar se marchează, nu se atașează la o comandă; generarea de PDF nu existămain.py:11228; audit 01.09.2026
Afirmații pe care codul NU le susține: „99,9% SLA”, „60+ integrări”, „280+ agenți activi”, „10 canale”, „sub 2 secunde”, badge-uri de certificare. Nu le folosim în materialele scrise aici. Verificat pe 6 septembrie 2026: toate cinci sunt încă live pe aichat.md și se scot.audit intern de coerență cod ↔ materiale de marketing, 27.07.2026:listă păstrată ca regulă de redactare pentru orice material aichat.md
Citările interne arată numele fișierului și linia. Calea completă rămâne în depozitul nostru; o putem parcurge împreună, la cerere.