Skip to content

Ce nu este construit ​

O documentație care descrie o funcționalitate ce nu merge e mai rea decât nicio pagină, pentru că cineva o să construiască pe ea. Pagina asta e lista lucrurilor care arată terminate și nu sunt.

Totul de aici a fost verificat în cod. Unde o altă pagină de pe site descrie una dintre ele, poartă același avertisment și trimite înapoi aici.

Cum se citesc etichetele

works dovedit în cod și exersat. partial o parte merge; rândul spune care parte nu. not built doar specificat, sau scris și niciodată apelat. Nu-ți face planuri pe el.

Pe scurt ​

Dacă alegi acum dacă CallAgent ți se potrivește, astea cinci decid.

Twilio e singurul carrier care ajunge în pipeline-ul AI.Mai există cinci adaptoare. Doar Twilio are o cale de media funcțională de la un apel telefonic la gateway.
Niciun apel pe trunk SIP nu a ajuns vreodată la un asistent.Registration-ul, autentificarea pe IP și admiterea prin ACL sunt dovedite pe un peer de laborator. Predarea media de după nu e construită.
Speech-to-speech e ignorat la runtime.Câmpul se salvează, se versionează și se publică, iar sesiunea live de apel nu îl citește niciodată.
Analiza de după apel nu rulează niciodată.Rezumatul, sentimentul, subiectele, evaluarea de succes și extragerea de structured outputs depind toate de un job pe care nimeni nu îl dispecerizează.
Niciun adaptor de furnizor nu a fost rulat vreodată pe un vendor live în CI.Formatele de pe fir sunt implementate din documentația vendorului și revizuite. Nu e același lucru cu dovedit.

Telefonie ​

Trunking-ul SIP se oprește la predarea media ​

partial

Ce e dovedit, pe un peer SIP real (un container Kamailio în telephony/sip-peer/, condus de prove.sh):

  • un REGISTER provocat care reușește;
  • o parolă greșită care eșuează cu 401 și scoate motivul pe rândul trunk-ului;
  • un INVITE admis de la o adresă din ACL-ul trunk-ului;
  • un INVITE refuzat cu 403 de la una care nu e;
  • reînregistrarea la circa 45 s față de o expirare de 60 s.

Ce nu s-a întâmplat niciodată: un apel de intrare pe trunk care ajunge la un asistent. Apelul e admis, marcat cu DID-ul și trunk-ul lui, transferat către extensia de predare a media și moare acolo:

CallAgent inbound did=+15551234567 from=+15550001111 trunk=<gateway-ulid>
CallAgent handoff mode=esl_socket target=host.docker.internal:8084
CallAgent handoff-failed mode=esl_socket reason=inbound_did          [CRIT]

Cauza sunt trei componente construite pe trei cusături de integrare diferite:

  • dialplan-ul FreeSWITCH așteaptă un socket ESL de ieșire pe portul 8084;
  • voice gateway-ul ascultă pe un singur port, HTTP și WebSocket pe 3010, și nu conține niciun server ESL și niciun stack SIP. Poți vedea singur: lsof -nP -iTCP -sTCP:LISTEN cât timp gateway-ul rulează arată 3010 și nimic altceva;
  • singura cusătură de media pe care gateway-ul o implementează, un WebSocket la /media/freeswitch, are nevoie de mod_audio_fork sau mod_audio_stream pe partea de FreeSWITCH, iar imaginea de FreeSWITCH livrată nu conține niciunul.

Nu e o problemă de SIP și repararea SIP-ului nu o rezolvă.

Nedovedit oricum, independent de predare, pentru că un peer local nu poate fi un carrier: digest SHA-256 (RFC 8760 — sonda e doar MD5), TLS și SRTP pe un SBC real, traversarea NAT și ciudățeniile de keepalive ale carrier-ului, DID-uri reale, prezentarea caller ID-ului, facturarea și comportamentul 302/Diversion.

Dacă un runbook îți spune să verifici portul 8084

nc -z voice-gateway 8084 va afișa mereu CLOSED. Nu ascultă nimic acolo. Orice instrucțiune care tratează un 8084 deschis ca stare sănătoasă e depășită.

Adaptoarele de carrier ​

partial

Sunt declarate nouă id-uri de furnizor. Șase au o clasă de adaptor; trei (zadarma, didlogic, chime) aruncă un 501 în care se numesc. Dintre cele șase, matricile de capabilități diferă enorm și fiecare adaptor și-o declară pe a lui — citește matricea, nu numele. Cea care contează cel mai mult:

  • Telnyx declară media_streams: implemented, și nimic din cod nu construiește o instrucțiune de media stream pentru Telnyx. placeOutboundCall() trimite un URL de webhook Call-Control și se oprește. Un apel Telnyx nu ajunge azi în pipeline-ul AI. E o capabilitate declarată care contrazice runtime-ul.
  • Plivo declară media_streams, inbound_voice, transfer, recording și amd ca neimplementate. Poate cumpăra numere și poate iniția un apel; nu poate rula un asistent.
  • DIDWW implementează trei lucruri: listarea numerelor din cont, validarea unei credențiale și vocea de intrare purtată peste un trunk SIP CallAgent. Restul aruncă.

Vezi Telefonie pentru matricea completă.

DTMF de ieșire pe un leg Twilio media ​

not built

Trimiterea de cifre în afara unui apel are nevoie de API-ul REST Twilio, iar gateway-ul nu ține intenționat nicio credențială de telefonie. În loc de asta, gateway-ul trimite intenția către control plane. Detecția DTMF de intrare funcționează.

Pipeline-ul ​

Speech to speech ​

not built

speechToSpeechModel e un câmp real. Se validează, se salvează, se versionează, se publică și apare în snapshot-ul pe care îl primește gateway-ul.

CallSession — clasa care rulează apelurile vii — nu îl citește niciodată. În arbore există un S2sPipeline complet, cu teste unitare; nimeni nu construiește vreodată unul. Un asistent configurat cu speechToSpeechModel rulează pipeline-ul obișnuit STT → LLM → TTS și nu spune nimic despre asta.

Din cele patru id-uri de furnizor realtime declarate, doar openai_realtime are un adaptor. Celelalte trei lipsesc, în loc să fie stub-uri — ceea ce e forma onestă.

Adaptoarele de furnizor sunt revizuite, nu dovedite ​

partial

SDK-ul de furnizori are un flag verified pe fiecare adaptor. Înțelesul lui e precis și mai îngust decât sună:

verified: true înseamnă că formatul de pe fir e implementat din documentația de protocol curentă și autoritară a vendorului și a fost revizuit față de ea. Niciun adaptor din pachetul ăsta nu a fost rulat pe un endpoint real în CI.

Niciun test din SDK nu depinde de o credențială vie. Toate testele sunt pe fixture-uri.

ClasăId-uri declarateAdaptoare înregistrateMarcate verified
Model1817 + shim-ul custom_llm13
Transcriber1413 + shim-ul custom3
Voce1916 + shim-uri2 (ElevenLabs, OpenAI)
Speech to speech411, și inaccesibil — vezi mai sus

Două id-uri de voce — sesame și xai — au o notă explicită în cod că nu sunt implementate pe API-ul vendorului; funcționează doar pe un endpoint pe care îl pui tu și care vorbește protocolul TTS al CallAgent. callagent ca furnizor de voce e un strat de indirectare al cărui catalog e livrat gol, intenționat.

Citirea practică: ElevenLabs e furnizorul de voce în care echipa are cea mai multă încredere, alți doisprezece au clienți HTTP reali îndreptați spre URL-uri reale de vendor, cu format de fir neverificat, iar restul au nevoie de endpoint-ul tău. Niciunul nu are o bifă verde câștigată pe un apel real.

Azure: trei adaptoare scrise, niciunul dovedit ​

not built

azure_speech (voce), azure_speech (transcriber) și azure_openai (model) sunt adaptoare complete, cu teste pe fixture-uri, și toate trei sunt puse în seed pe not_implemented — adică niciun tenant nu le poate alege. Nu e o scăpare, e regula din §188. Niciunul nu a produs audio, transcript sau un răspuns pe un endpoint Azure real, iar implemented e o afirmație că ceva a fost văzut funcționând, nu o descriere a cât de terminat arată codul.

Fiecare așteaptă o singură rulare pe viu:

FurnizorAre nevoie deTestul care ar tranșa problema
voce azure_speechCheia unei resurse Speech și regiunea eiSintetizezi o replică în µ-law 8k și auzi sunet, adică TtsFirstAudio pe un apel real
transcriber azure_speechAceeași cheie și aceeași regiuneDeschizi socketul de recunoaștere, vorbești și vezi un speech.hypothesis, apoi un speech.phrase
model azure_openaiNume de resursă, nume de deployment, versiune de API și o cheieUn răspuns în flux de la /openai/deployments/{deployment}/chat/completions

Două detalii din transcriber sunt implementate din documentația de protocol și nu au fost niciodată observate: convenția de lungime a antetului RIFF în flux și dacă parametrul endSilenceTimeoutMs e acceptat pe socketul de recunoaștere. Amândouă sunt marcate în docblock-ul adaptorului.

Cheia și regiunea Azure Speech sunt o singură credențială pentru ambele produse — o conectezi o dată și acoperă și transcrierea, și vocile — pentru că cele două rânduri din registru cer aceleași câmpuri, iar ProviderAccountScope deduce partajarea din asta, nu dintr-o listă.

API-ul REST nu poate seta majoritatea setărilor de furnizor ale unui asistent ​

not built

POST și PATCH /assistants folosesc $request->validated() din Laravel, care întoarce doar cheile care au avut o regulă de validare. În interiorul lui transcriber, model, voice și server, clasa de request declară reguli pentru cinci sub-chei și atât:

transcriber.provider · model.provider · model.model · voice.provider · server.url

Tot restul din cele patru blocuri e aruncat înainte să fie salvat — voice.voice_id, voice.speed, voice.stability, model.temperature, model.max_tokens, model.tool_choice, model.num_fast_turns, model.context_window_messages, transcriber.model, transcriber.language, transcriber.smart_format și celelalte. Request-ul reușește cu 201, iar valoarea ciuntită se întoarce în răspuns.

Reprodus pe un control plane viu:

trimis  "voice": { "provider": "elevenlabs", "voice_id": "rachel", "speed": 1.1 }
salvat  "voice": { "provider": "elevenlabs" }

voice.voice_id e unul dintre cele cinci câmpuri fără de care configurația de apel a gateway-ului nu poate fi construită, deci consecința nu e cosmetică: un asistent al cărui bloc de voce a fost scris ultima dată prin API-ul REST produce o configurație de apel nulă și nu poate porni un apel. validate le verifică pe celelalte patru și pe ăsta nu, deci se validează și se publică fără reproș. CLI-ul trimite către același endpoint și moștenește problema.

Dashboard-ul scrie direct în model, nu prin clasa asta de request, deci asistenții configurați acolo sunt compleți. Blocurile de plan nu au sub-reguli și trec întregi.

Doi asistenți demo din seed nu pot porni un apel ​

not built

O problemă de ortografie înrudită, vizibilă în datele de seed livrate. Convertorul de fir citește voice['voice_id']; doi asistenți din seed — Outbound — appointment reminders și Blue Olive — reservations — poartă doar voiceId în camelCase și niciun voice_id:

json
{ "model": "eleven_flash_v2_5", "speed": 1, "voiceId": "burt", "provider": "elevenlabs" }

Configurația lor de apel se rezolvă la null, din același motiv ca mai sus.

callagent:doctor e omorât de erorile pe care există ca să le raporteze ​

partial

php artisan callagent:doctor încarcă clasele aplicației ca să o găsească pe cea stricată, deci o eroare fatală de încărcare doboară comanda cu tot cu ea și primești eroarea PHP brută în loc de un raport. La momentul scrierii, un widget Filament face exact asta — CallTrendsWidget::render() e declarat private unde clasa părinte îl declară public — iar doctor și php artisan tinker mor amândoi pe el.

Eroarea fatală tot numește fișierul și linia, deci nu e inutilă. callagent:check nu încarcă dashboard-ul și continuă să funcționeze.

Hook-urile asistentului se declanșează pentru un eveniment din paisprezece ​

partial

hooks[] declară o acțiune la unul dintre paisprezece puncte de declanșare. Control plane-ul le convertește și le trimite gateway-ului. Sursa gateway-ului nu conține nicio referință la hooks.

Un singur trigger rulează, în control plane și nu în gateway: handoff, prin HandoffHookRunner. Celelalte treisprezece nu fac nimic.

Conversia îngustează și acțiunile: supraviețuiesc doar say, transfer, tool și end_call. O acțiune handoff, setVariable sau webhook e aruncată în tăcere.

Câmpuri de asistent pe care gateway-ul nu le citește niciodată ​

not built

Fiecare dintre ele e acceptat de API, salvat, versionat și — cu excepția celui notat — convertit pe fir. Nimic din gateway nu citește vreunul.

CâmpEfectul intenționat
model.num_fast_turnsTrimite primele tururi la un model mai ieftin.
model.fast_modelCare model mai ieftin. Nici măcar nu e convertit — există doar în contract.
model.emotion_recognitionSemnale de emoție către model.
voice_formatting (în contract chunkPlan)Cum e normalizat și tăiat textul înainte de sinteză.
pronunciations (în contract pronunciationDictionary)Pronunții impuse pe cuvinte.
compliance_planInclusiv identity_disclosure_required.
artifact_plan.storage_path_templateUnde se scrie o înregistrare.
speech_to_speech_modelTot pipeline-ul realtime.

Furnizorii de smart endpointing ​

partial

startSpeakingPlan.smartEndpointing.provider acceptă callagent, livekit și model. Doar callagent e implementat. Alegerea oricăruia dintre celelalte două scrie un warning și rulează în tăcere scorerul intern.

După apel ​

Analiza de după apel ​

not built

Rezumatul, sentimentul, subiectele și evaluarea de succes au un pipeline complet și o clasă de job. Finalizatorul apelului rulează redactarea, artefactele, transcrierea de după apel și retenția — și nu dispecerizează niciodată job-ul de analiză. Nu există niciun test care să îl acopere.

calls.summary se populează doar dacă gateway-ul îl furnizează în payload-ul de finalizare.

Extragerea de structured outputs ​

not built

Aceeași cauză. Definițiile, versionarea, validarea și stocarea funcționează toate. Pasul de extragere e făcut de pipeline-ul de analiză de mai sus, care nu rulează.

Scorecards pe apeluri vii ​

partial

Motorul de scoring e real și e exersat de simulări. Scorarea unui apel viu depinde de pipeline-ul de analiză.

Exportul de trace-uri de observabilitate ​

not built

Există exportere pentru Langfuse și OTLP. Nimeni nu le invocă. Gateway-ul o scrie pe față: tag-urile și sampling-ul se aplică, span-urile nu sunt trimise. Nu-ți face o integrare pe asta.

Transcrierea de după apel ​

partial

Lista de furnizori vine din registry; Sonix e singurul adaptor. Orice altă alegere nu are niciun client în spate, iar interfața o spune, în loc să eșueze mai târziu.

Înregistrare și conformitate ​

partial

Asta contează juridic, deci citește-o cu atenție.

Recorderul e construit și pornit, iar redarea începe, înainte ca anunțul de consimțământ să fie rostit. Anunțul vine după.

Mai rău, gateway-ul poate raporta către control plane o singură stare de consimțământ: announced. Nu raportează niciodată granted sau denied, pentru că nu există niciun mecanism de confirmare — niciun prompt DTMF, niciun matcher de expresii. Setarea onConsentDenied e purtată în configurația apelului, nu e citită și nu se poate declanșa. Control plane-ul are un applyConsentDecision() care oprește înregistrarea; nimic dintr-un apel real nu îl declanșează.

Deci: un anunț poate fi redat. Un refuz nu poate fi respectat. Tratează „recording consent" ca „s-a făcut un anunț" și satisface orice obligație mai strictă în afara CallAgent.

Regulile pe regiuni din politica de înregistrare sunt documentație pentru operator. Nimic nu se ramifică pe ele ca să decidă dacă o înregistrare e legală.

Dezvăluirea AI și articolul 50 din EU AI Act ​

not built

Nimic din CallAgent nu face un asistent să dezvăluie că e un AI.

  • compliance_plan de pe un asistent (inclusiv identity_disclosure_required) se salvează, e întors de API și e inclus în snapshot-ul publicat. Voice gateway-ul nu îl citește niciodată.
  • Primul mesaj e validat doar pentru lungime și sintaxă de template. Nicio regulă de conținut nu cere o dezvăluire.
  • Singura dezvăluire conform articolului 50 din tot codul e scrisă hardcodat în demo-ul de vânzări al CallAgent, care refuză să inițieze apelul dacă textul dezvăluirii e gol. Mecanismul acela nu e expus asistenților clienților.

Dacă ai nevoie de o dezvăluire, pune propoziția tu în first_message și lasă first_message_interruptions_enabled pe false, ca să nu poată fi vorbită peste. Vezi Dezvăluire AI și consimțământ.

Redactarea PII nu atinge audio-ul ​

partial

Redactarea rulează o singură dată, la finalizare, peste text: conținutul mesajelor, transcrierea, rezumatul și payload-urile de evenimente. Există câmpul artifactPlan.piiRedaction.redactRecording. Audio-ul înregistrării nu e modificat niciodată.

artifactPlan.storagePathTemplate e ignorat pentru înregistrări ​

not built

Recorderul scrie hardcodat org/{organizationId}/calls/{callId}/{channel}.wav. Câmpul de template nu e citit nicăieri în gateway.

Contact center ​

Supervizor: listen, whisper și barge ​

partial

Dovedite: poarta de permisiuni, urma de audit (fiecare încercare scrie un rând, inclusiv refuzurile și eșecurile) și contractul endpoint-ului. end e complet dovedit, pentru că el deține tranziția de stare a apelului.

Nedovedit: că audio-ul se conectează vreodată. Calea eavesdrop din FreeSWITCH nu are niciun test cu switch-ul pornit — suita de teste o spune într-un comentariu. Calea mai nouă, cu leg de participant în gateway, e testată pe un gateway HTTP fals, nu pe unul care rulează. Calea aceea e și oprită implicit (contact_center.media.gateway_leg_enabled).

Transferul warm merge doar pe FreeSWITCH ​

partial

Un transfer consultativ (warm) e o secvență în trei pași — hold → originate → bridge — făcută cu comenzi FreeSWITCH. Nu există un echivalent Twilio implementat. Pe calea de conferință Twilio, o consultare privată între doi operatori nu e oferită, în loc să fie simulată — amândoi sunt în conferință cu apelantul.

Transfer către extensie de la un carrier găzduit ​

partial

Un apel Twilio nu poate ajunge la o extensie SIP internă simplă. Transferul e refuzat cu extension_not_reachable_from_carrier, în afară de cazul în care extensia are o destinație de redirecționare permanentă.

Destinații de transfer dinamice dintr-un tool ​

not built

Când tool-ul de transfer al asistentului cere o destinație dynamic, dispecerul o refuză cu dynamic_expression_unresolved. Destinațiile dinamice se rezolvă doar pe calea inițiată de operator sau de supervizor.

Telefonul web al operatorului ​

not built

Arhitectura e decisă — refolosește transportul WebRTC al Web SDK-ului. Nu e construit. Operatorii înregistrează un dispozitiv SIP.

Tools ​

Cinci tipuri de tool nu ajung niciodată într-un apel ​

not built

bash, computer, text_editor, client_side și custom_provider sunt valori valide ale enum-ului de tip de tool. Le poți crea prin API și le poți atașa unui asistent.

Maparea care transformă un tool salvat în formatul de pe fir al gateway-ului nu are nicio intrare pentru niciunul dintre cele cinci. Un tool de unul dintre tipurile acelea e aruncat în tăcere din lista de tools a fiecărui apel. Modelul nu îl vede niciodată.

Tools-urile client_side funcționează prin calea proprie de înregistrare a Web SDK-ului — acela e un mecanism diferit.

Serverul MCP cu 24 de tools din packages/mcp nu e montat ​

not built

Există două implementări de „CallAgent ca server MCP". Cea în TypeScript din packages/mcp declară 24 de tools și nu e importată de nimic — un schelet, nu un server care rulează.

Cea vie e POST /mcp din control plane, autentificată cu cheie de API, și publică 13 tools. Tools-urile absente lipsesc intenționat: comentariul din registry spune că a face reclamă unui tool al cărui subsistem nu e terminat e mai rău decât a-l omite. Vezi MCP.

Refresh-ul de OAuth pentru MCP în PHP ​

partial

Clientul MCP în TypeScript reîmprospătează un token OAuth expirat. Partea de PHP — folosită pentru discovery, nu pentru apeluri de tools — îl raportează ca expirat.

Platformă ​

API-ul ​

AșteptatRealitate
POST /api/v1/client/callsnot built Pornirea unui apel din browser prin API. Schimbul de token (POST /client-tokens) e viu; ăsta nu.
/api/v1/policiesnot built CLI-ul validează policies/ local și spune că nu le poate trimite.
/api/v1/files, /api/v1/storagenot built Destinațiile de storage se configurează doar din dashboard. Scope-ul storage.write există fără nimic în spate.
/api/v1/chatnot built Există un ChatController în arbore și niciun fișier de rute nu îl referă. Scope-urile chat.read / chat.write sunt inaccesibile.
/api/v1/smsnot built Tipul de tool sms și contractul de trimitere există; nu există endpoint și nu există adaptor.

Idempotența dincolo de POST /calls ​

partial

POST /calls deduplică pe (organization_id, idempotency_key) printr-un index unic pe tabela de apeluri. Asta e reală și e impusă de baza de date.

Mai există și o tabelă idempotency_keys cu o coloană request_hash, un cod de eroare idempotency_conflict și un 409 documentat. Niciun cod nu scrie în tabela aia și niciun cod nu citește din ea, clasa de serviciu la care trimite propriul docblock nu există, și nimic nu ridică idempotency_conflict. Un Idempotency-Key generic pe alte endpoint-uri nu face nimic.

Consecința pe POST /calls: reluarea unei chei cu un body diferit întoarce apelul original în loc să dea eroare. Nu există comparație de hash al request-ului.

Suprascrieri de rate limit per tenant ​

partial

api_rate_limit_per_minute de pe un plan chiar suprascrie valoarea implicită de 300/minut. Există și o tabelă rate_limit_overrides cu coloanele bucket, per_minute, burst și expires_at, pe care niciun cod nu o citește. Vezi Limite de rate.

SAML SSO și grupuri SCIM ​

not built

Serviciul de SSO întoarce „SAML is not implemented in this build" și, intenționat, nu există nicio rută; e blocat pe o bibliotecă de XML-DSig. SCIM provizionează utilizatori; grupurile lipsesc.

Vector stores și embeddings ​

partial

pgvector și custom sunt implementate. Qdrant, Pinecone și Weaviate există ca valori de enum ca interfața să poată spune „încă nu" cinstit. OpenAI e singurul furnizor de embeddings.

Stripe nu a fost niciodată apelat cu o cheie reală ​

not built

Fiecare cale de Stripe e acoperită de teste care conduc SDK-ul real Stripe — semnare reală a request-ului, serializare reală — pe fixture-uri conservate. Niciun endpoint Stripe live sau de test nu a fost vreodată contactat. STRIPE_SECRET e gol în mediul de exemplu livrat, iar gateway-ul aruncă o eroare cu nume în loc să degradeze în tăcere.

Verificarea semnăturii webhook-urilor, tratarea idempotentă a evenimentelor și creditarea autoritară pe ledger sunt tot cod real. Niciunul nu a întâlnit Stripe.

Onboardingul self-serve dă un număr pe care nu l-a cumpărat ​

partial

Plata unei înscrieri de pe o pagină de soluție creează un cont real, pe un plan real, generează un asistent din site-ul firmei, îl publică și dă un număr de telefon care răspunde — pe același ecran. Patru lucruri de acolo nu sunt, intenționat, ce par.

Nu se întâmplă absolut nimic înainte de confirmarea plății. Terminarea formularului scrie un singur rând cu ce s-a cerut. Fără organizație, fără asistent, fără număr, fără niciun apel către un model. Poarta asta înlocuiește trei limitări de care avea nevoie o versiune anterioară: nu există nicio cale neautentificată către vreo cheltuială, deci nu mai e nimic de limitat.

Fluxul nu cumpără niciodată un număr. Numerele vin dintr-un stoc cumpărat dinainte de un operator cu callagent:telephony:stock-number-pool --yes — singurul loc din produs care cheltuie bani la operatorul telecom, inaccesibil din orice rută HTTP, orice acțiune Filament și orice job. O înscriere revendică unul, adică un UPDATE, iar numărul se întoarce în stoc dacă nu folosește nimeni contul. Un număr reciclat e curățat înainte — în primul rând hook-ul dinamic, care altfel ar întreba serverul fostului proprietar unde să trimită apelurile următorului.

Contul rulează pe cheile platformei, nu pe ale lui. §31 rămâne regula pentru orice organizație creată altfel. Un cont self-serve e marcat provider_key_mode = platform și folosește credențiale care aparțin organizației platformei — pe care nu le poate lista, numi, testa sau exporta, fiindcă sunt rândurile altei organizații. Cheia lui proprie, adăugată mai târziu, câștigă de la apelul următor.

Provisioningul de după plată se reîncearcă, nu se returnează banii. Un pas blocat — stoc gol, furnizor de voce care nu răspunde — se reia cu întârzieri crescătoare, iar numărul de încercări, următoarea încercare și dacă a fost anunțat cineva stau pe rând. La capăt, rândul primește gave_up_at, în log intră o linie CRITICAL și un operator primește e-mail.

Două rezerve de citit de două ori. Cu COST_FX_USD_EUR nesetat, consumul unui cont în euro se contorizează corect și se evaluează la zero, fiindcă toți furnizorii din registrul de costuri publică în dolari, iar ExchangeRate refuză să inventeze un curs; asta e înregistrată pe rândul de provisioning și spusă pe ecranul de predare. Și epuizarea creditului închide apelul în desfășurare — LiveCreditGuard estimează consumul apelului la tariful afișat, la fiecare raportare de cost de la gateway, și îl termină când portofelul nu îl mai acoperă. Nu există perioadă de grație și soldul nu intră pe minus. Rezoluția e intervalul de raportare al gateway-ului, deci se poate depăși cu câteva secunde.

Protocolul de sesiune din browser ​

partial

Audio-ul și barge-in-ul funcționează cap-coadă. Evenimentele de conversație (transcript, message, state, tool_call, ended) încă aterizează în gateway. Vezi Browserul.

Lucruri care arată a comutator și nu sunt ​

Registrul de feature flags. FeatureFlagSeeder reține o maturitate pentru fiecare modul și e cel mai apropiat lucru de o listă oficială. Tratează-l ca documentație a intenției, nu ca pe un comutator impus — nimic din afara resursei de flag-uri nu citește tabela ca să restricționeze navigația. E și în urma realității pe alocuri: module.mcp_server, module.web_sdk și module.cli sunt toate marcate not_implemented și toate trei sunt construite.

Blocat pe un cont, nu pe cod ​

Complet în cod, așteaptă doar credențiale:

  • Un cont Twilio, un număr cumpărat și un URL public de tunel — apeluri PSTN reale.
  • Chei Deepgram, OpenAI și ElevenLabs — măsurarea reală a latenței furnizorilor. Fiecare adaptor e testat doar pe fixture-uri.
  • Chei de test Stripe — fluxul de cumpărare pay-as-you-go.
  • Un carrier SIP real — tot ce un peer de laborator nu poate fi.
  • Un cont Sonix — transcrierea de după apel.

Dacă găsești pagina asta greșită ​

Pagina e bug-ul, nu codul. E scrisă cu repository-ul în față și o să se învechească. Verifică comportamentul înainte să te bazezi pe oricare dintre ele.

Scrisă după cod. Ce nu este încă implementat este marcat ca atare, niciodată descris ca funcțional.