En una llamada web (el widget, la página alojada, tu app), quien llama ve un chat junto a la voz, de modo que el agente puede hacer más que hablar. Quienes llaman por teléfono no tienen nada de esto.
Activa Agente → Herramientas → Enviar a quien llama (send_to_caller en la API de agentes) y el agente podrá poner hasta cinco tarjetas a la vez en la pantalla de quien llama: un título, una línea debajo, una descripción, una imagen, un enlace y hasta dos botones de respuesta cada una; también puede ofrecer hasta tres respuestas rápidas bajo una pregunta. Los enlaces nunca se leen en voz alta.
El agente solo puede enviar enlaces e imágenes que se le hayan dado en esa llamada: sus instrucciones y saludo, la base de conocimiento (un documento leído de una página web lleva su dirección), las respuestas de tus funciones y las tarjetas predefinidas. Además, un enlace debe estar en uno de los allowed_hosts (el propio sitio de una tarjeta predefinida siempre lo está). Los enlaces que el agente se inventa, o que quien llama dicta en voz alta, no se envían. Los enlaces a esos sitios web en las palabras del agente se pueden pulsar en el 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": "" }
]
}
Cada envío te llega como el webhook call.message_sent (channel, items con title y url, quickReplies, blocked). Una llamada envía como máximo 10 veces.
Durante la llamada, quien llama también puede escribir (una dirección de correo, un número de pedido) o tocar un botón de respuesta; el agente lo responde como si fuera voz, dejando de hablar primero si estaba hablando. Hasta 500 caracteres por mensaje, uno por segundo, 100 por llamada. En el registro de la llamada, estos turnos se marcan como escritos o tocados.
Los visitantes también pueden empezar escribiendo en lugar de hablar: el widget y la página alojada ofrecen ambas opciones, o solo una si así lo eliges en Agent → Deploy. Una conversación escrita no tiene voz y se cobra por mensaje. Para chatear con un agente desde tu propio servidor, usa la Chat API.
El widget da a tu página un objeto evasay. Todo es opcional, y el marco de la llamada solo escucha a tu página si es uno de los sitios web permitidos del widget (Agente → Desplegar):
<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 rellenan {{name}} en las instrucciones y el saludo. Vienen del navegador del visitante, así que al agente se le dice que no están verificados, y nunca llegan a tus funciones ni a la consulta de inicio.update cuenta al agente lo que ocurre en la página sin hacer que responda; una actualización más reciente con la misma key sustituye a la anterior."kind": "page", sin url) y registra en tu página una función con el mismo nombre. El agente solo puede llamarla en llamadas desde una página que la haya registrado; espera hasta timeout_sec (1–10, por defecto 5) la respuesta, salvo que wait_for_result sea false. Se ejecuta con la sesión del visitante, como un clic suyo: pide confirmación en tu propia página antes de cualquier cosa que cueste dinero o no se pueda deshacer. Los enlaces de su respuesta pueden enviarse como tarjetas.Configura Quién puede iniciar una llamada en Solo con un token, y haz que tu servidor obtenga un token de un solo uso para el usuario con sesión iniciada:
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 respuesta incluye token (una llamada, dentro de expires_in segundos, 30–3600, por defecto 600), agent (el slug) y web_call_url. Entrega el token a la página con data-token-url="/your/endpoint" en el script del widget (hace un POST allí con las cookies del visitante y lee { "token": "…" }) o con agent.setToken(async () => token). Las variables del token están verificadas: las instrucciones, la consulta de inicio y las plantillas de tus funciones pueden usarlas, igual que user_id, que la llamada conserva (userId en la llamada, user_id para filtrar llamadas). Mantén tu clave de API en tu servidor.
En tu propia app, haz POST de { "token": "…", "pageTools": ["add_to_cart"] } a https://evasay.com + web_call_url. La respuesta es la conexión de la llamada (una dirección de oferta WebRTC, o una dirección WebSocket, con su token de llamada), para un cliente RTVI como el SDK de cliente de Pipecat; para iOS, Android y React Native consulta Apps móviles. Las tarjetas, las funciones de página y los avisos llegan como server-message de RTVI (evasay.cards, evasay.tool, evasay.notice); envía las palabras escritas con send-text y los informes y respuestas de la página como client-message evasay.context y evasay.tool_result. O transporta tú mismo el audio con Audio por WebSocket, pasando user_id y page_tools.