Skip to main content
A ligação roda no mesmo client da sessão: sem segundo aparelho e sem segundo QR. Ela funde o sidecar de ligação do Sistema e o voz-bridge (ElevenLabs). Com ela ligada, o voz-bridge pode ser desligado.
Desligada por padrão, em duas camadas. Sem ZAPMEOW_VOICE=1 o meowcaller nem é montado no client. Com a variável, só as sessões com enabled: true o recebem (ele intercepta os eventos de chamada, então as outras ficam como estavam). Habilitar uma sessão que já está no ar pede stop e start dela (a resposta do PUT /call/config traz reiniciar: true). Ligação por WhatsApp não oficial tem risco de banimento: use número de teste até o OK.

Ligar numa sessão

Rotas

Aceitam a chave de admin ou o token da sessão. As de configuração, só a chave de admin. Sem {sessão} no caminho (POST /api/call), vale ?session=, o campo session do corpo ou a única sessão. mode: eleven (a IA atende; padrão quando vem agentId, extra ou callId, que é o contrato do voz-bridge) ou browser (um humano fala pelo /call/audio). extra (objeto JSON) vira as variáveis dinâmicas do agente; o agente vem de agentId do pedido, extra.agentId ou agentId da sessão, nessa ordem; só o tenant Glow cai em ELEVENLABS_AGENT_ID.

Agente, chave e eventos por instância

Cada sessão guarda o próprio agentId e eventUrl (https; http só em localhost) na config. A chave da ElevenLabs (elevenKey) e o token dos eventos (eventToken) vão para o cofre do tenant da sessão, cifrados, sob os nomes elevenlabs_api_key e voz_event_token, e valem para todas as sessões do tenant. Eles só entram: nenhuma resposta nem log devolve o valor, o GET mostra só elevenKeySet e eventTokenSet. Precisa de ZAPMEOW_MASTER_KEY (sem cofre o PUT com segredo devolve 503). No painel admin, em Voz e IA, cada sessão do tenant tem um cartão com esses campos (também por PUT /admin/tenants/{id}/s/{sessão}/call/config); o portal do cliente não alcança essa rota. Sessão sem agente, ou sem chave do próprio tenant, não liga: 422 com sem agente ElevenLabs... ou sem chave ElevenLabs..., antes de discar e sem gastar o teto. Nunca cai na chave de outro tenant. As variáveis ELEVENLABS_API_KEY, ELEVENLABS_AGENT_ID, VOZ_EVENT_URL, VOZ_EVENT_TOKEN e VOZ_TOKEN são só o recuo do tenant Glow (a chave e o token gravados no cofre dele vencem o env).

Códigos

Controles

  • Teto diário (dailyCap, padrão 20 ou ZAPMEOW_VOICE_TETO): contado no Postgres (zm_voice_usage), atômico, vira à meia-noite do fuso da sessão. 409 e 422 não gastam o teto. 0 bloqueia tudo.
  • Janela (windowStart/windowEnd, padrão 08:00 às 21:00 em America/Sao_Paulo): fora dela, 403. Os dois vazios = sem janela. Início maior que o fim vale pela madrugada.
  • Lista de teste (allowed): vazia = qualquer número; com números, só eles.
  • Uma chamada por vez por sessão; teto de 15 minutos e 90 s sem resposta.

Aviso de andamento ao Convex

Com eventUrl na config da sessão (ou VOZ_EVENT_URL, só no tenant Glow) e callId no pedido, o ZapMeow avisa o Convex como o voz-bridge: POST com Authorization: Bearer <eventToken do cofre do tenant> (no tenant Glow, o recuo é $VOZ_EVENT_TOKEN ou $VOZ_TOKEN; sem token, sem o cabeçalho) e corpo {callId, event, error}. Eventos: ringing, answered, ended, rejected, no_answer, cada final uma vez só. A IA entra no aceite do par, sem esperar o primeiro pacote de áudio. Para o Convex trocar o voz-bridge pelo ZapMeow, basta apontar VOZ_BRIDGE_URL para https://<zapmeow>/api/<sessão> e VOZ_BRIDGE_TOKEN (é o nome que o Convex lê) para o token da sessão. scripts/trocar-voz-convex.sh faz a troca e a reversão.

Áudio do lead e latência

A voz do lead passa pelo RNNoise (rede neural, cgo) antes de ir ao agente: ruído de fundo não vira interrupção. VOZ_NOISE_GATE=0 desliga e manda o áudio cru. A latência (fim da fala do lead até o 1º áudio da IA na chamada) sai no log (latência: N ms) e em call/status (chamada.latencia: amostras, mediaMs, minMs, maxMs, ultimasMs). Para comparar com o voz-bridge na mesma chamada, use scripts/ab-latencia.mts.

Variáveis

O agente da ElevenLabs precisa estar configurado com áudio pcm_16000 na entrada e na saída.