Przejdź do treści
megapromotingPorozmawiajmy

Rozwiązania · Transport i logistyka

Gdy klient pyta, gdzie jest przesyłka, agent nie zgaduje: dzwoni do kuriera, pyta i wraca z odpowiedzią.

Dyspozytornia głosowa, zbudowana jako mechanizm, a nie jako obietnica: tabela z jednoznacznymi stanami, trzy próby w odstępach dwóch minut, strukturalnie zapisany wynik połączenia i filtr, który usuwa numer kierowcy ze wszystkiego, co trafia do modelu, aby nie dało się go podyktować klientowi.

Już zbudowaneMecanismul de dispecerizare e scris și migrat în platforma noastră vocală: tabela `courier_calls` cu șapte stări posibile, trei încercări implicite, pauză de 120.000 ms între ele și rezultatul apelului păstrat structurat, plus cinci funcții de server care o folosesc — inițierea apelului către curier, verificarea rezultatului, mătura pentru apelurile rămase agățate, identificarea celui care sună înapoi și webhookul de după apel. A doua implementare e filtrul de ieșire scris pentru un client din transport, care elimină recursiv câmpurile de contact ale șoferului din rezultatul uneltei, păstrând numerele dispeceratului. Rezerva, spusă înainte să întrebi: partea de telefon trece printr-o gazdă SIP, iar gazda prin care merg liniile noastre de test nu răspunde la data scrierii — nu-ți dăm un număr de demonstrație pe care nu l-am putea ridica în fața ta.

W firmie transportowej lub dostawczej większość odebranych połączeń to to samo pytanie zadane przez różne osoby: gdzie jest towar, o której godzinie dotrze, dlaczego jeszcze nie dotarł. Odpowiedź nie jest w dokumencie i nie jest w systemie — jest w głowie kierowcy, który prowadzi. Dyspozytor łączy te elementy: odbiera połączenie klienta, dzwoni do kierowcy, wraca do klienta. Ta praca zajmuje jedną osobę w pełni i wykonuje się ją sto razy dziennie, używając tych samych trzech zdań.

Zbudowaliśmy dokładnie taki łańcuch, jako mechanizm ze stanami, a nie jako funkcję marketingową. Agent rozmawia z klientem. Gdy potrzebuje odpowiedzi, której nie ma, wywołuje funkcję, która uruchamia drugie połączenie — do kuriera — powiązane z rozmową, z której wyszła. To połączenie ma własny wiersz w tabeli, ze statusem przechodzącym przez `calling`, `in_progress`, `retrying`, `completed`, `failed`, `no_answer`, `timeout`, z numerem próby, z maksymalnie trzema próbami i z dwu-minutową przerwą między nimi. Wynik zapisuje się strukturalnie: podsumowanie tego, co powiedział kurier, szacowany czas, pozycja.

Część, którą łatwo przeoczyć, a którą traktujemy jako wymóg, nie jako ostrożność: numer telefonu kierowcy nie może trafić do klienta. To nie jest instrukcja zapisana w promptcie agenta, bo instrukcję w promptcie można obejść. To filtr, który rekurencyjnie przechodzi przez wynik narzędzia i usuwa pola kontaktowe kierowcy, zanim ten wynik trafi do modelu — zachowując numery dyspozytorni. To, co zostało usunięte, nie może zostać podyktowane, niezależnie od tego, jak agent zostanie zapytany.

A najważniejszym ograniczeniem jest infrastruktura, nie inteligencja: agent głosowy w telefonie zależy od hosta SIP między Twoim operatorem a platformą. Gdy ten host przestaje działać, połączenia nie wychodzą, a sygnatura błędu jest rozpoznawalna — wygasłe żądanie, pusty identyfikator połączenia, zero czasu trwania. Host, przez który przechodzą nasze linie testowe, nie odpowiada na dzień sporządzenia tej strony. W sieci ścieżka głosowa jest dziś weryfikowalna; w telefonie pierwszym etapem każdej pracy jest ustalenie, na jakim hoście wchodzą Twoje numery.

Co obejmuje

Co konkretnie zmienia się w transporcie i logistyce

Agent rozmawiający z klientem może uruchomić drugie połączenie

Gdy odpowiedź nie znajduje się w posiadanych informacjach, agent wywołuje funkcję serwerową, która dzwoni do kuriera. Wywołanie do kuriera zachowuje powiązanie z rozmową, z której pochodzi, poprzez identyfikator rozmowy nadrzędnej — więc zawsze wiadomo, do kogo dzwoniono i dlaczego. Kontekst zamówienia jest przekazywany jako struktura, z Twojego systemu zamówień, nie jest przepisywany.

Połączenie do kuriera ma stany, nie tylko „zadzwoniono”

Siedem stanów zapisanych jako ograniczenie w bazie danych: `calling`, `in_progress`, `retrying`, `completed`, `failed`, `no_answer`, `timeout`. Plus numer bieżącej próby. Różnica między „nie odebrano” a „system padł” jest widoczna w danych, nie zgadywana z logów — i to ma znaczenie, gdy ktoś jutro pyta, dlaczego klient nie dostał odpowiedzi.

Ponowne próby są skonfigurowane, nie improwizowane

Domyślnie: trzy próby, z 120.000 milisekundami — dwie minuty — między nimi, oba zapisane jako wartości domyślne w tabeli i w konfiguracji procesu. Kierowca jadący drogą bez zasięgu nie odbiera przy pierwszej próbie. System, który dzwoni tylko raz i ogłasza porażkę, jest bezużyteczny dokładnie w przypadku, dla którego został zbudowany.

Wynik połączenia wraca jako struktura, nie jako opowieść

To, co powiedział kurier, zapisuje się jako podsumowanie, szacowany czas i pozycja, w strukturze pola powiązanego z wierszem połączenia. Stamtąd może pójść dalej: do agenta, który rozmawia z klientem, do dyspozytorni, do Twojego systemu. Webhook po połączeniu i funkcja sprzątająca dla połączeń pozostawionych w zawieszeniu domykają łańcuch, aby nieodebrane połączenie nie pozostawało w stanie `calling` bez końca.

Numer kierowcy nie może być dyktowany, ponieważ nie trafia do modelu

Filtr wyjściowy przechodzi rekurencyjnie przez wynik narzędzia i usuwa pola kontaktowe kierowcy, zachowując numery dyspozytorni. Jest zapisany w kodzie, stosowany punktowo do integracji, gdzie występuje problem. Powód jest prosty: interfejs dostawcy zwracał numery kierowców w odpowiedzi, a polityka firmy zabraniała, by agent przekazywał je klientom. Jednej instrukcji w prompcie można by uniknąć, zadając dobrze sformułowane pytanie; usuniętego pola nie da się obejść.

Kto oddzwania, jest rozpoznawany po numerze

Kurier oddzwaniający jest identyfikowany przez dedykowaną funkcję, więc nie trafia do ogólnego przepływu klientów i nie jest odczytywane od początku menu. Wygląda na detal; to różnica między systemem, którego kierowcy używają, a takim, który omijają, dzwoniąc bezpośrednio do dyspozytora, co unieważnia całą pracę.

Przekazanie do dyspozytora, pod ręką osoby mówiącej

Ślepy transfer przez `##` i transfer wspomagany przez `*2`, z kontekstem lądowania w planie wybierania, który odróżnia wewnętrzne rozszerzenia czterocyfrowe od numerów zewnętrznych. Gdy klient uporczywie prosi o człowieka — a w transporcie prosi, bo jego ładunek się spóźnia — transfer nie powinien przechodzić przez menu.

Agenta można przerwać i reguluje się to liczbami

W ścieżce OpenAI Realtime: semantyczna detekcja mowy z progiem 0,5, bufor 300 ms, 500 ms ciszy, przerwanie dozwolone domyślnie. W ścieżce ElevenLabs event przerwania jest przekazywany centrali, aby zatrzymać odtwarzanie. `turn_timeout` ustawia się per agent. W rozmowie transportowej, gdzie rozmówca często jest w hałaśliwej kabinie, te progi stanowią połowę odczuwanej jakości.

Czego agent głosowy w transporcie nie robi

Nie decyduje o trasie i nie optymalizuje ponownie dostaw. Nie podaje stawki, jeśli nie jest podłączony do źródła, które ją oblicza. Nie wie, gdzie jest ładunek, jeśli nikt mu tego nie powiedział — ani kurier, ani Twój system. I nie zastępuje dyspozytora: przejmuje powtarzalne połączenia i zostawia mu wyjątki, które są dokładnie tą częścią, za którą jest opłacany.

Traseul

Jak przechodzi zgłoszenie przez system.

01

Najpierw ustalamy, na jakim hoście SIP wchodzą Twoje numery

Pierwszy etap to nie scenariusz agenta, lecz telefonia: przez jaki trunk wchodzi numer, kto nim zarządza, co dzieje się, gdy host nie odpowiada. Dostarczamy pisemną weryfikację trasy i, jeśli trasa nie jest pewna, mówimy to przed zbudowaniem czegokolwiek na niej. Świetny agent na hoście, który się zawiesza, to agent, który nie odpowiada.

02

Piszemy scenariusz dyspozycji, wraz z jego wyjątkami

O co agent pyta kuriera, w jakiej kolejności, co robi, gdy kurier nie odpowiada przy trzeciej próbie, co się dzieje, gdy odpowiedź jest niejasna, kiedy przekazuje do ludzkiego dyspozytora. Dostarczamy napisany scenariusz i listę stanów, do których może trafić połączenie — także tych nieprzyjemnych.

03

Łączymy źródło zamówień i ustawiamy filtry na wyjściu

Kontekst zamówienia pochodzi z Twojego systemu, a zanim wynik narzędzia trafi do modelu, przechodzimy przez listę pól, które nie mogą wyjść. Dostarczamy integrację, pisaną listę pól filtrowanych oraz dowód, że filtr stosuje się do wyniku, a nie do instrukcji.

04

Uruchamiamy na małym wolumenie, z transkryptami czytanymi przez człowieka

Startujemy na części połączeń, z szeroko skonfigurowanym przekazaniem do dyspozytora, i czytamy transkrypty. Na tej podstawie reguluje się progi przerwania, `turn_timeout`, formułowanie pytań oraz próg, od którego agent rezygnuje. Dostarczamy raport z tych połączeń, z decyzjami regulacyjnymi, a nie tylko uruchomionego agenta.

1Clientul întreabă2agentul cheamăfuncția de apel3apel către curier, custare proprie4până la treiîncercări, la douăminute5rezultat structurat(rezumat, timpestimat, poziție)6răspuns la client, cunumărul șoferuluifiltrat din drum
Traseul, în 6 pași

Dane

Czego dotykamy, gdzie to leży i jak długo zostaje

Zasady różnią się w zależności od branży. To są te, które obowiązują w transporcie i logistyce.

Numer kierowcy to dane osobowe człowieka, nie pole techniczne
Kurier lub podwykonawca-kierowca jest osobą fizyczną. Jego numer, jego pozycja i jego nagranie głosu są jego danymi. Dlatego filtr wyjścia nie jest kaprysem bezpieczeństwa, lecz minimalizacją zastosowaną u źródła: pole nie trafia do modelu, więc nie może trafić do rozmowy ani do transkryptu.
Co jest zachowywane z połączenia
Numer dzwoniącej osoby i numer, na który dzwoniono, moment, czas trwania, wynik, nagranie audio, transkrypt oraz analiza po połączeniu. W przypadku połączeń nieodebranych istnieją numer, moment i przyczyna braku odpowiedzi — audio nie istnieje, bo nie powstało. Wszystko jest powiązane z przestrzenią roboczą Twojej firmy; nie ma wspólnego repozytorium ponad klientami.
Komunikat na początku połączenia to Twoja decyzja, nie ustawienie
To, że rozmówca rozmawia z systemem automatycznym, że połączenie jest nagrywane i na jakiej podstawie — ustala się wspólnie z Tobą i trafia do scenariusza, w obu kierunkach: zarówno do klienta, jak i do kuriera. Kurier dzwoniący przez agenta musi wiedzieć, z czym rozmawia, tak samo jak klient.
Usuwanie na żądanie istnieje; automatyczne usuwanie po terminie jeszcze nie
Mówimy to tak, jak jest, bo to różnica między obietnicą a funkcją. Usuwanie na żądanie jest zaimplementowane: dedykowana funkcja usuwa obiekty z repozytorium plików, wywołuje procedurę usuwania z bazy i unieważnia sesje. Konfigurowalna retencja per przestrzeń robocza nie jest zaimplementowana — pojawia się w dokumencie projektowym, w żadnej migracji. Dopóki nie będzie, usuwanie po terminie odbywa się przez procedurę.
Gdzie są dane
PostgreSQL przez Supabase na własnej infrastrukturze, z wersjonowanymi migracjami, z których część aktywuje izolację na poziomie wiersza. Pliki — nagrania, dokumenty wiedzy, próbki głosu — są przechowywane w oddzielnych repozytoriach, ze ścieżką zaczynającą się od identyfikatora przestrzeni roboczej.

Przykład

Połączenie ze stanem, nie tylko z wynikiem

Sytuacja

W przepływie dostawy pytanie „gdzie jest moje zamówienie” nie ma odpowiedzi w żadnym systemie: odpowiedź ma kurier. Prosta wersja — agent pisze do kuriera wiadomość i ma nadzieję — pada przy pierwszym kurierze, który prowadzi i nie patrzy na telefon.

Co zbudowaliśmy

Zbudowaliśmy dyspozycję jako tabelę, nie jako funkcję. Każde połączenie do kuriera ma wiersz z siedmioma możliwymi stanami, numerem próby, maksimum trzema próbami, dwu­minutową przerwą między nimi i zachowanym strukturalnie wynikiem — podsumowaniem, szacowanym czasem, pozycją. Wiersz zachowuje powiązanie z rozmową klienta, z której wyszedł. Wokół tabeli: funkcja, która uruchamia połączenie, ta, która sprawdza wynik, miotła dla połączeń pozostawionych w zawieszeniu, identyfikacja kuriera, który oddzwania, oraz webhook po połączeniu.

Co z tego wyszło

Można odpowiedzieć, w dowolnym momencie i na podstawie danych, na pytania, które dyspozytornia otrzymuje codziennie: czy zadzwoniono, ile razy, co odpowiedziano, dlaczego nie zadzwoniono. Nieodebrane połączenie nie pozostaje już zablokowane w stanie pośrednim, ponieważ jest kto je uprzątnie.

Czego nie mówi ten przypadek

Mechanizm jest napisany i przeniesiony do platformy; część telefoniczna zależy od hosta SIP, a ta, przez którą przechodzą nasze linie testowe, nie odpowiada na dzień pisania. Nie przedstawiamy dyspozycji jako czegoś, co można przetestować, dzwoniąc dziś na nasz numer.

Pytania

Co pyta ktoś z transportu i logistyki

Czy agent sam dzwoni do kuriera, czy tylko wysyła mu wiadomość?

Dzwoni. Istnieje funkcja serwerowa, która uruchamia połączenie do kuriera, powiązane z rozmową, z której wyszło, z kontekstem zamówienia przekazanym jako struktura. Połączenie ma własny wiersz w tabeli, ze stanem, numerem próby i wynikiem — więc można w dowolnym momencie odpowiedzieć na pytanie „czy zadzwoniono i co zostało powiedziane”.

Co się dzieje, jeśli kierowca nie odpowiada?

Próba jest ponawiana. Domyślnie trzy razy, w odstępie dwóch minut, wartości zapisane w tabeli i w konfiguracji procesu. Jeśli i za trzecim razem nie ma odpowiedzi, połączenie pozostaje w stanie `no_answer` — stanie odrębnym od `failed`, który oznacza, że coś padło u nas. To rozróżnienie jest powodem, dla którego warto mieć tabelę, a nie dziennik.

Czy agent może podać klientowi numer kierowcy?

Nie, i nie dlatego, że tak mu powiedzieliśmy. Pola kontaktowe kierowcy są rekurencyjnie usuwane z wyniku narzędzia, zanim ten wynik trafi do modelu. Numery dyspozytorni pozostają. To, co nie trafia do modelu, nie może zostać podyktowane, niezależnie od tego, jak sprawnie sformułowane jest pytanie.

Czy może powiedzieć, gdzie jest teraz paczka?

Może powiedzieć, co powiedział mu kurier przy ostatnim połączeniu, z godziną tego połączenia, albo co odczytuje z Twojego systemu, jeśli jest z nim połączony. Tego nie robi — i jest to decyzja, nie ograniczenie — że sam zgaduje. Wymyślona przez agenta estymacja staje się obietnicą, za którą na progu odpowiada kierowca.

Czy mogę teraz zadzwonić na numer demonstracyjny?

Nie dziś. Część telefoniczna przechodzi przez hosta SIP, a host, przez który idą nasze linie testowe, nie odpowiada na dzień pisania tej strony. Nie umieszczamy na stronie numeru, którego nie moglibyśmy podnieść przed Tobą. Trasa głosowa w sieci to inna historia: tam można to sprawdzić od razu.

Czy mówi po rosyjsku z klientem i po rumuńsku z dyspozytorem?

Konfiguracja agenta obsługuje 32 języki, a rumuński jest domyślnym językiem nowego agenta. Język ustawia się dla każdego agenta osobno, więc agent, który rozmawia z klientem, i ten, który dzwoni do kuriera, mogą być skonfigurowani różnie. Co warto wiedzieć: dla syntezy głosu w językach innych niż angielski domyślny model jest szybki, a wariant wyższej jakości jest wyraźnie wolniejszy — kompromis wybiera się świadomie.

Co się dzieje, gdy klient przerywa?

Zatrzymuje się. Semantyczna detekcja mowy ma próg 0,5, bufor 300 ms i 500 ms ciszy, a przerywanie jest domyślnie dozwolone; na drugim torze zdarzenie przerwania jest przesyłane do centrali, aby uciąć odtwarzanie. Jeśli agentu nie można przerwać, to nie jest problem tonu, lecz konfiguracji — i zbyt długich odpowiedzi.

Jak długo przechowywane są nagrania rozmów z kierowcami?

Decidecie Państwo, ponieważ to Państwo są operatorem danych. Co trzeba wiedzieć o dzisiejszym stanie platformy: usuwanie na żądanie jest zaimplementowane jako funkcja, a automatyczne usuwanie po terminie, konfigurowalne dla każdego obszaru roboczego, nie jest — odbywa się procedurą. Wolimy, żeby dowiedzieli się Państwo tego od nas, a nie z audytu.

Zastępuje dyspozytora?

Nie. Zabiera mu część powtarzalną — to samo pytanie, ten sam telefon, ta sama odpowiedź — a zostawia wyjątki. Przekazanie do niego nadal odbywa się kodem z klawiatury, a w transporcie wyjątki są częste: odrzucony towar, błędny adres, klient, który nie odpowiada. Tam potrzebna jest osoba, i lepiej, żeby była to osoba, która wcześniej nie odpowiadała już na sto „gdzie jest paczka”.

Co chcesz, żeby działało lepiej?

Opowiedz nam o swoim procesie. Wspólnie ustalimy, co warto zbudować, co da się połączyć i jak sprawdzimy wynik.

Porozmawiajmy