W połączeniu webowym (widżet, strona hostowana, Twoja aplikacja) rozmówca widzi czat obok głosu, więc agent może robić coś więcej niż mówić. Rozmówcy dzwoniący przez telefon tego nie mają.
Włącz Agent → Narzędzia → Wyślij rozmówcy (send_to_caller w API agenta), a agent będzie mógł wyświetlać na ekranie rozmówcy do pięciu kart naraz: tytuł, wiersz pod nim, opis, obraz, link i do dwóch przycisków odpowiedzi w każdej; może też zaproponować do trzech szybkich odpowiedzi pod pytaniem. Linki nigdy nie są czytane na głos.
Agent może wysyłać tylko linki i obrazy, które dostał w tym połączeniu: jego instrukcje i powitanie, bazę wiedzy (dokument wczytany ze strony internetowej niesie jej adres), odpowiedzi Twoich funkcji i gotowe karty. Link musi też należeć do jednego z allowed_hosts (własna witryna gotowej karty zawsze jest dozwolona). Linki, które agent zmyśli albo które rozmówca wypowie na głos, nie są wysyłane. Linki do tych witryn w słowach agenta są w czacie klikalne.
"send_to_caller": {
"enabled": true,
"allowed_hosts": ["shop.example.com", "*.cdn.example.com"],
"presets": [
{ "name": "hours", "when": "asked when we open", "title": "Opening hours",
"description": "Mon–Sat 9:00–18:00", "url": "https://shop.example.com/stores", "image_url": "" }
]
}
Każde wysłanie trafia do Ciebie jako webhook call.message_sent (channel, items z title i url, quickReplies, blocked). W jednym połączeniu można wysyłać najwyżej 10 razy.
Podczas połączenia rozmówca może też pisać (adres e-mail, numer zamówienia) lub dotykać przycisku odpowiedzi; agent odpowiada na to jak na mowę, wcześniej przerywając, jeśli mówił. Do 500 znaków na wiadomość, jedna na sekundę, 100 na połączenie. W zapisie połączenia takie tury są oznaczone jako wpisane lub dotknięte.
Odwiedzający mogą też zacząć od pisania zamiast mówienia: widżet i strona hostowana oferują oba sposoby albo tylko jeden, jeśli tak wybierzesz w Agent → Deploy. Rozmowa pisana nie ma głosu i jest rozliczana za wiadomość. Aby czatować z agentem z własnego serwera, użyj Chat API.
Widżet daje Twojej stronie obiekt evasay. Wszystko jest opcjonalne, a ramka połączenia słucha Twojej strony tylko wtedy, gdy należy ona do dozwolonych witryn widżetu (Agent → Wdrożenie):
<script src="https://evasay.com/voice-widget.js" data-agent="AGENT_SLUG" async></script>
<script>
window.evasay = window.evasay || [];
evasay.push(function (agent) {
agent.setVariables({ plan: 'pro', page: location.pathname }); // for the next call
agent.update('Cart: 2 items, $120', { key: 'cart' }); // during it
agent.registerTool('add_to_cart', async function (args) {
// your code, in the visitor's browser
return { ok: true, checkout: 'https://shop.example.com/checkout' };
});
agent.on('cards', function (cards) {}); // also 'live', 'ended'
});
</script>
setVariables wypełniają {{name}} w instrukcjach i powitaniu. Pochodzą z przeglądarki odwiedzającego, więc agent jest informowany, że nie są zweryfikowane, i nigdy nie trafiają do Twoich funkcji ani do zapytania startowego.update informuje agenta, co dzieje się na stronie, bez zmuszania go do odpowiedzi; nowsza aktualizacja z tym samym key zastępuje starszą."kind": "page", bez url) i zarejestruj na swojej stronie funkcję o tej samej nazwie. Agent może ją wywołać tylko w połączeniach ze strony, która ją zarejestrowała; czeka na odpowiedź do timeout_sec (1–10, domyślnie 5), chyba że wait_for_result ma wartość false. Działa na sesji odwiedzającego, jak jego własne kliknięcie: przed wszystkim, co kosztuje pieniądze lub jest nieodwracalne, poproś o potwierdzenie na własnej stronie. Linki w jej odpowiedzi mogą być wysyłane jako karty.Ustaw Kto może rozpocząć połączenie na Tylko z tokenem i niech Twój serwer pobiera jednorazowy token dla zalogowanego użytkownika:
curl https://evasay.com/api/v1/voice/web-calls \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{ "agent_id": "AGENT_ID", "user_id": "u_42", "variables": { "name": "Ann" }, "expires_in": 600 }'
Odpowiedź zawiera token (jedno połączenie, w ciągu expires_in sekund, 30–3600, domyślnie 600), agent (slug) i web_call_url. Przekaż token stronie przez data-token-url="/your/endpoint" w skrypcie widżetu (wysyła tam POST z ciasteczkami odwiedzającego i odczytuje { "token": "…" }) albo przez agent.setToken(async () => token). variables tokenu są zweryfikowane: mogą z nich korzystać instrukcje, zapytanie startowe i szablony Twoich funkcji, tak samo jak z user_id, który połączenie zachowuje (userId w połączeniu, user_id do filtrowania połączeń). Klucz API trzymaj na swoim serwerze.
W własnej aplikacji wyślij POST z { "token": "…", "pageTools": ["add_to_cart"] } na https://evasay.com + web_call_url. Odpowiedzią jest połączenie (adres oferty WebRTC albo adres WebSocket z tokenem połączenia) dla klienta RTVI, takiego jak klienckie SDK Pipecat; iOS, Android i React Native opisuje strona Aplikacje mobilne. Karty, funkcje strony i powiadomienia przychodzą jako RTVI server-message (evasay.cards, evasay.tool, evasay.notice); wpisane słowa wysyłaj przez send-text, a zgłoszenia i odpowiedzi strony jako client-message evasay.context i evasay.tool_result. Możesz też sam przenosić dźwięk przez Dźwięk przez WebSocket, przekazując user_id i page_tools.