logo

Dale Voz a tu Agente

Tus usuarios hablan, tu agente escucha y responde — en tiempo real, en su idioma.

Quick Start — React SDK

Instala el SDK @formmy.app/chat y agrega voz a tu app React en segundos.

El hook maneja todo: WebSocket, micrófono, playback, barge-in y transcripciones. Tú solo pones tu UI.

useFormmyVoice — API

PropiedadTipoDescripción
start(opts?)(opts?: { systemPrompt?: string }) => Promise<void>Inicia la sesión de voz. Opcional: { systemPrompt: '...' } para override per-session
stop()() => voidCierra sesión y libera recursos
toggleMute()() => voidAlterna silencio del micrófono
setMuted(muted)(boolean) => voidControl explícito de mute (complementa toggleMute)
clearTranscripts()() => voidLimpia el array de transcripciones
statusVoiceStatus"idle" | "connecting" | "ready" | "speaking" | "error"
isMutedbooleanSi el mic está silenciado
isSpeakingbooleanShortcut: status === 'speaking'
isListeningbooleanShortcut: status === 'ready'
errorError | nullÚltimo error (conexión, mic, etc.)
transcriptsVoiceTranscript[]Transcripciones en tiempo real

Cada VoiceTranscript tiene role ("user" | "assistant"), text y isFinal (boolean).

Options

OpciónTipoDescripción
agentIdstringID del agente (requerido)
voiceIdstringVoz a usar (default: "carlos")
sensitivity"HIGH" | "MEDIUM" | "LOW"Turn-taking: HIGH (~1.5s), MEDIUM (~1.75s, default), LOW (~2.0s)
onStatusChange(status: VoiceStatus) => voidCallback en cada cambio de status — evita useEffect
onError(error: Error) => voidCallback en errores — evita useEffect
onTranscript(transcript: VoiceTranscript) => voidCallback por cada transcript — para logging, analytics, o sync externo
onMicAudio(float32: Float32Array) => voidRaw mic audio por frame — para visualizaciones de intensidad o waveforms
onServerEvent(type: string, payload: unknown) => voidCatch-all para eventos del servidor (artifacts, toolUse, custom)
audioDestinationAudioNodeNodo intermedio para playback (ej. GainNode para volumen, AnalyserNode para visualizar)
wsUrlstringOverride de la URL WebSocket — para conexiones self-hosted o first-party

systemPrompt per-session: Pasa un system prompt custom al llamar start({ systemPrompt: '...' }). Esto override las instrucciones del agente solo para esa sesión — útil para cambiar tono, idioma o comportamiento sin tocar el dashboard.

FormmyVoiceClient — Vanilla JS

El cliente headless sin React. Maneja WebSocket, mic, playback, barge-in y transcripciones. El hook useFormmyVoice lo usa internamente.

Config

PropiedadTipoDescripción
baseUrlstringURL base del servidor (requerido)
publishableKeystringTu pk_live key
agentIdstringID del agente (requerido)
voiceIdstringVoz (default: "carlos")
sensitivity"HIGH" | "MEDIUM" | "LOW"Turn-taking sensitivity
wsUrlstringOverride de URL WebSocket (ignora baseUrl + pk)
audioDestinationAudioNodeNodo destino para playback (GainNode, AnalyserNode, etc.)
toolsArrayClient-side tools (name, description, inputSchema)
onToolUseFunctionHandler para tool calls del agente

Event Handlers

HandlerTipoDescripción
onStatusChange(status: VoiceStatus) => void"idle" | "connecting" | "ready" | "speaking" | "error"
onTranscript(t: VoiceTranscript) => voidStreaming + final transcripts (role, text, isFinal)
onMicAudio(float32: Float32Array) => voidRaw mic frame por cada chunk — para waveforms o intensidad
onServerEvent(type: string, payload: unknown) => voidArtifacts, toolUse, y eventos custom del servidor
onError(error: Error) => voidErrores de conexión, mic, etc.

Métodos

MétodoDescripción
connect(opts?)Conecta WebSocket, pide mic, inicia handshake. Opcional: { systemPrompt: '...' } para override per-session
disconnect()Cierra sesión y libera todos los recursos
sendText(text)Envía texto durante la llamada (cross-modal)
setMuted(bool)Silencia/activa el micrófono
getStatus()VoiceStatus actual
getIsPlaying()true si el agente está reproduciendo audio
getPlaybackContext()AudioContext de playback (24kHz) — para análisis externo

WebSocket Nativo — Quick Start

Si no usas React, conéctate directo por WebSocket.

Qué Necesitas

Publishable Key

Empieza con formmy_pk_live_

Agent ID

Desde tu dashboard

Plan Pro

Voice AI requiere un plan de pago

Parámetros de conexión

ParamRequeridoDescripción
chatbotIdEl ID de tu agente
pkPublishable key (formmy_pk_live_)
voiceIdNoVoz a usar (default: carlos)
sensitivityNoTurn-taking: HIGH (~1.5s), MEDIUM (~1.75s, default), LOW (~2.0s)

Voces Disponibles

🇲🇽

carlos

Hombre · Español

🇲🇽

lupe

Mujer · Español

🇺🇸

tiffany

Mujer · Inglés (US)

🇺🇸

matthew

Hombre · Inglés (US)

🇬🇧

amy

Mujer · Inglés (GB)

🇫🇷

ambre

Mujer · Francés

🇫🇷

florian

Hombre · Francés

🇮🇹

beatrice

Mujer · Italiano

🇮🇹

lorenzo

Hombre · Italiano

🇩🇪

greta

Mujer · Alemán

🇩🇪

lennart

Hombre · Alemán

Esto no es Text-to-Speech

La mayoría de las soluciones de "voz con IA" usan un pipeline de 3 pasos: STT → LLM → TTS. Transcriben tu voz a texto, procesan el texto con un modelo de lenguaje, y luego sintetizan la respuesta a audio. Tres modelos. Tres puntos de latencia. Tres puntos de falla donde se pierde tono, emoción e intención.

Pipeline tradicional (STT + LLM + TTS)

Audio → Whisper → Texto → GPT → Texto → ElevenLabs → Audio

~2-4s de latencia. 3 modelos. 3 facturas.

Formmy Voice (Speech-to-Speech nativo)

Audio → Un solo modelo → Audio

<1s de latencia. 1 modelo. Sin intermediarios.

Formmy Voice usa un modelo speech-to-speech nativo. El audio entra y el audio sale — directamente. No hay transcripción intermedia, no hay síntesis artificial. El modelo entiende tu voz y genera su respuesta como voz, en un solo paso. Resultado: conversaciones que se sienten naturales, con latencia menor a un segundo y a una fracción del costo.

Full-duplex real — sin mute, sin turnos

No es un walkie-talkie. El audio fluye en ambas direcciones al mismo tiempo. Puedes hablar mientras la IA habla — sin bloqueos, sin mute automático, sin esperar turno. La IA te escucha incluso mientras responde, y si la interrumpes, se adapta al instante. Exactamente como una conversación real.

Barge-in y Echo Cancellation

Barge-in — la IA lo maneja

Cuando el usuario habla mientras la IA responde, Formmy detecta la interrupción automáticamente y envía un evento contentEnd con stopReason: "INTERRUPTED".

Tu único trabajo:

  • Detener la reproducción de audio actual
  • Limpiar tu cola de audio (chunks pendientes)
  • Descartar texto buffereado

NO hagas:

  • Implementar detección de voz (VAD) en el cliente
  • Lógica de barge-in manual
  • Detección de silencio

Echo Cancellation — el browser lo maneja

El AEC (Acoustic Echo Cancellation) del browser es suficiente. Nunca pauses el micrófono mientras la IA habla. El audio debe fluir continuamente en ambas direcciones.

Android — Activa AEC del hardware

En Android, usa VOICE_COMMUNICATION como AudioSource. Esto activa el AEC del hardware automáticamente y evita que la voz de la IA se retroalimente como input del usuario.

Transcripciones en Tiempo Real

El servidor envía transcripciones de voz en tiempo real para usuario y asistente via eventos textOutput. Si usas el SDK React, ya están parseadas en transcripts.

Si usas WebSocket directo:

Cómo Funciona

Tú hablas → Formmy → Agente IA → Formmy → Tú escuchas

🔌

1. Conexión

Abre un WebSocket a formmy.app con tu agent ID y publishable key.

🤝

2. Handshake automático

El servidor envía "initialized". Tú envías "sessionStart". El servidor responde "ready".

🎤

3. Audio continuo

Envía audioStart UNA VEZ, luego audioInput continuamente. Nunca pares — el servidor detecta cuándo hablas.

🤖

4. La IA responde

Recibes audioOutput con audio PCM 24kHz mono. Decodifica y reproduce con queue scheduling.

👋

5. Cierre

Envía un evento "close" cuando termine la conversación.

Reglas Críticas

Envía audio siempre. audioStart una vez, luego audioInput sin parar. Nunca pauses el mic.

Reproduce inmediato. No bufferees todo el audio. Queue + play cada chunk que llegue.

Barge-in = solo limpiar queue. Cuando recibas contentEnd(INTERRUPTED), limpia tu cola de audio. Nada más.

NO implementes VAD. No detectes silencio, no detectes voz. El servidor lo maneja todo.

NO pauses el mic. Ni por agentSpeaking, ni por nada. Full-duplex = siempre abierto.

Ojo con Esto — Errores Comunes

Audio duplicado (SPECULATIVE vs FINAL)

El servidor puede enviar el mismo contenido de audio dos veces: primero como evento SPECULATIVE y luego como FINAL. Es comportamiento normal del modelo.

Solución:

El saludo no se reproduce (patrón speaks-first)

Si tu agente tiene un mensaje de bienvenida configurado, el servidor usa el patrón "speaks first". Después de recibir ready, la IA empieza a enviar audioOutput con el saludo — antes de que el usuario hable.

Secuencia correcta:

No mezcles textInput con audioStart

textInput y audioStart/audioInput son canales independientes.

  • Usa textInput para mensajes escritos — no necesitas audioStart
  • Usa audioStart / audioInput para voz
  • Nunca envíes ambos al mismo tiempo

sendText() — Texto durante una llamada de voz

Usa sendText() del hook useFormmyVoice para enviar mensajes de texto durante una sesión de voz activa.

const { start, stop, sendText, status } = useFormmyVoice({
  agentId: 'agent_123',
});

// During an active voice session:
sendText("Check my order status");

Ejemplos Completos

Web (TypeScript) — WebSocket + AudioWorklet

Android (Kotlin) — OkHttp + Client Tools

Superpoder: Tools del Lado del Cliente

Tu agente puede llamar funciones en TU app — en tiempo real, durante la llamada. Perfecto para consultas GraphQL, búsquedas en base de datos local o cualquier lógica específica de tu cliente.

Comportamiento async de los tools

  • El servidor espera tu respuesta — cuando la IA invoca un client tool, el servidor queda en pausa hasta que envíes el toolResult.
  • Ejecución en paralelo — la IA puede invocar múltiples tools al mismo tiempo. Cada uno tiene su propio toolUseId.
  • Barge-in descarta resultados tardíos — si el usuario interrumpe, el servidor cancela la espera. Resultados tardíos se descartan silenciosamente.
  • Máximo 2,000 caracteres — el campo result se trunca. Sé conciso.

Paso 1: Registra tools antes de sessionStart

Paso 2: El servidor confirma

Paso 3: La IA invoca tu tool a media conversación

Paso 4: Envía el resultado de vuelta

El campo result es un string plano. La IA lo usa para formular su respuesta de voz.

Audio Pipeline

Control avanzado del audio de playback: routing, visualizaciones y acceso al AudioContext del SDK.

audioDestination factory

Pasa una factory function en lugar de un AudioNode directo. La factory recibe el AudioContext del SDK, garantizando que todos los nodos compartan el mismo contexto (evita errores silenciosos de cross-context).

También acepta un AudioNode directo si ya tienes un nodo del mismo contexto.

getPlaybackContext()

Accede al AudioContext que usa el SDK para playback (24kHz). Útil para crear nodos de análisis o conectar visualizadores.

onMicAudio

Callback con el audio raw del micrófono como Float32Array. Ideal para visualizaciones de input o medición de intensidad del usuario.

Referencia

Eventos

DirecciónEventoDescripción
ServidorinitializedServidor listo, contiene chatbotId y chatbotName
ClienteregisterToolsRegistra tools del cliente (antes de sessionStart)
ServidortoolsRegisteredConfirmación de tools registrados
ClientesessionStartInicia la sesión de voz. Opcional: { systemPrompt: '...' } para override per-session
ServidorreadySesión lista, contiene sessionId
ClienteaudioStartAbre stream de audio (enviar UNA VEZ)
ClienteaudioInputChunk de audio (PCM 16kHz mono, base64) — enviar continuamente
ServidoraudioOutputAudio de la IA (PCM 24kHz mono, base64)
ServidorcontentStartInicio de contenido — contiene role y generationStage
ServidortextOutputTranscripción parcial (acumular hasta contentEnd)
ServidorcontentEndFin de contenido. stopReason: END_TURN o INTERRUPTED
ClientetextInputMensaje de texto (alternativa a voz)
ServidorclientToolUseLa IA quiere que el cliente ejecute un tool
ClientetoolResultResultado del tool ejecutado por el cliente
ServidorerrorMensaje de error
ClientecloseCerrar la sesión

Formato de Audio

DirecciónFormatoSample RateCanalesCodificación
Entrada (mic)PCM 16-bit16,000 HzMonoBase64
Salida (bocina)PCM 16-bit24,000 HzMonoBase64

REST: Voice Config

Obtén la configuración de voz antes de conectarte.

¿Necesitas Ayuda?

¿Preguntas sobre el Voice SDK? Estamos para ayudarte.