Lors d’un appel web (widget, page hébergée, votre app), l’appelant voit un chat à côté de la voix, donc l’agent peut faire plus que parler. Les appelants au téléphone n’ont rien de tout cela.
Activez Agent → Connaissances et outils → Envoyer à l’appelant (send_to_caller dans l’API des agents) et l’agent peut afficher jusqu’à cinq cartes à la fois sur l’écran de l’appelant : un titre, une ligne dessous, une description, une image, un lien et jusqu’à deux boutons de réponse chacune ; il peut aussi proposer jusqu’à trois réponses rapides sous une question. Les liens ne sont jamais lus à voix haute.
L’agent ne peut envoyer que des liens et des images qu’on lui a donnés dans cet appel : ses instructions et son accueil, la base de connaissances (un document lu depuis une page web porte son adresse), les réponses de vos fonctions et les cartes prêtes à l’emploi. Un lien doit aussi figurer sur l’un des allowed_hosts (le site d’une carte prête à l’emploi l’est toujours). Les liens que l’agent invente, ou que l’appelant lit à voix haute, ne sont pas envoyés. Les liens vers ces sites dans les paroles de l’agent sont cliquables dans le chat.
"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": "" }
]
}
Chaque envoi vous parvient sous forme de webhook call.message_sent (channel, items avec title et url, quickReplies, blocked). Un appel envoie au plus 10 fois.
Pendant l’appel, l’appelant peut aussi taper (une adresse e-mail, un numéro de commande) ou toucher un bouton de réponse ; l’agent y répond comme à la parole, en s’arrêtant d’abord s’il parlait. Jusqu’à 500 caractères par message, un par seconde, 100 par appel. Dans l’historique de l’appel, ces tours sont marqués comme tapés ou touchés.
Les visiteurs peuvent aussi écrire au lieu de parler : le widget et la page hébergée proposent les deux, ou seulement l’un des deux si vous le choisissez dans Agent → Deploy. Une conversation écrite n’a pas de voix et est facturée par message. Pour discuter avec un agent depuis votre propre serveur, utilisez la Chat API.
Le widget fournit à votre page un objet evasay. Tout est facultatif, et le cadre d’appel n’écoute votre page que si elle fait partie des sites autorisés du widget (Agent → Déployer) :
<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 }); // pour le prochain appel
agent.update('Cart: 2 items, $120', { key: 'cart' }); // pendant l’appel
agent.registerTool('add_to_cart', async function (args) {
// votre code, dans le navigateur du visiteur
return { ok: true, checkout: 'https://shop.example.com/checkout' };
});
agent.on('cards', function (cards) {}); // aussi 'live', 'ended'
});
</script>
setVariables remplissent {{name}} dans les instructions et l’accueil. Elles viennent du navigateur du visiteur, donc l’agent est prévenu qu’elles ne sont pas vérifiées, et elles n’atteignent jamais vos fonctions ni la consultation au démarrage.update indique à l’agent ce qui se passe sur la page sans le faire répondre ; une mise à jour plus récente avec la même key remplace l’ancienne."kind": "page", sans url) et enregistrez une fonction du même nom sur votre page. L’agent ne peut l’appeler que lors d’appels depuis une page qui l’a enregistrée ; il attend la réponse jusqu’à timeout_sec (1–10, 5 par défaut) sauf si wait_for_result vaut false. Elle s’exécute avec la session du visiteur, comme un clic de sa part : demandez une confirmation sur votre propre page avant toute action payante ou irréversible. Les liens de sa réponse peuvent être envoyés sous forme de cartes.Réglez Qui peut lancer un appel sur Uniquement avec un jeton, et faites obtenir par votre serveur un jeton à usage unique pour l’utilisateur connecté :
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 }'
La réponse contient token (un appel, dans les expires_in secondes, 30–3600, 600 par défaut), agent (le slug) et web_call_url. Donnez le jeton à la page avec data-token-url="/your/endpoint" sur le script du widget (il y fait un POST avec les cookies du visiteur et lit { "token": "…" }) ou avec agent.setToken(async () => token). Les variables du jeton sont vérifiées : les instructions, la consultation au démarrage et les modèles de vos fonctions peuvent les utiliser, de même que user_id, que l’appel conserve (userId dans l’appel, user_id pour filtrer les appels). Gardez votre clé API sur votre serveur.
Dans votre propre app, envoyez en POST { "token": "…", "pageTools": ["add_to_cart"] } à https://evasay.com + web_call_url. La réponse est la connexion de l’appel (une adresse d’offre WebRTC ou une adresse WebSocket, avec son jeton d’appel), pour un client RTVI comme le SDK client de Pipecat ; pour iOS, Android et React Native, voir Applications mobiles. Les cartes, fonctions de page et avis arrivent comme server-messages RTVI (evasay.cards, evasay.tool, evasay.notice) ; envoyez les mots tapés avec send-text et les signalements et réponses de la page comme client-messages evasay.context et evasay.tool_result. Ou transportez l’audio vous-même avec Audio via un WebSocket, en passant user_id et page_tools.