Sari la conținut
megapromotingHai să discutăm
Produse Kallina

Agenți vocali AI Platformă

Uma boa conversa continua com uma ação.

Construímos agentes que atendem e fazem chamadas, usam a informação do negócio e trabalham com os seus sistemas. Da primeira pergunta até a um pedido completo, uma confirmação ou a passagem a um colega.

AscultăVerificăAcționeazăVOCE + CONTEXT + ACȚIUNE
Cum funcționează Kallina

Kallina

Da informação ao trabalho feito.

01

Ascultă

Percebe o pedido no contexto da conversa e das regras do negócio.

02

Verifică

Consulta a base de conhecimento e as integrações autorizadas antes de responder.

03

Acționează

Preenche os dados, executa a ação permitida ou passa a conversa a uma pessoa.

Onde se torna útil.

Receção e apoio

Perguntas frequentes, recolha de pedidos e retorno de chamada a quem pediu para ser contactado.

Encomendas e entregas

Confirmações e coordenação, com a informação do sistema de encomendas ligado.

Qualificação e marcações

Reúne os detalhes necessários. O acesso ao calendário e a marcação definem-se para cada integração.

Os cenários, o número de telefone, as línguas e as ações configuram-se para cada implementação. A equipa mantém a possibilidade de assumir a conversa.

A Kallina em detalhe

O que pode fazer com este projeto.

A Kallina é a plataforma sobre a qual construímos agentes que falam ao telefone e na página web. Um agente tem um papel escrito, uma base de conhecimento aprovada, um conjunto de ferramentas que pode chamar e um limite a partir do qual entrega a conversa a uma pessoa. A conversa não acaba no transcript: a chamada tem duração, custo por fornecedor, gravação e análise, tudo ligado à conta do negócio.

O motor de voz não é um só. Na configuração do agente escolhe entre ElevenLabs Conversational AI, OpenAI Realtime, Gemini Live ou «auto», caso em que a Kallina escolhe o fornecedor conforme a língua, a carga e a disponibilidade. Por cima, escolhe à parte o cérebro de texto — o catálogo no código tem 78 entradas da OpenAI, Google, Anthropic, xAI e ElevenLabs, cada uma com a latência e o custo por minuto à vista na interface, para que a escolha seja informada e não de ouvido.

A telefonia é nossa, não alugada ao fornecedor de voz. As chamadas passam por um Asterisk próprio, com encaminhamento por horário e fuso horário, horário noturno (por exemplo 22:00 → 06:00) e correspondência por prioridade: o cabeçalho SIP Diversion, depois o número da Kallina, depois a regra de reserva. Para o OpenAI Realtime existe uma ponte AudioSocket que converte o codec nos dois sentidos, g711_ulaw ↔ PCM16.

01

Três fornecedores de voz mais uma posição «auto»

Em `AGENT_PROVIDERS` há quatro opções: `elevenlabs` (ConvAI), `openai-realtime`, `gemini-live` e `auto`. Para text-to-speech em línguas que não o inglês, a predefinição é `eleven_flash_v2_5` — 32 línguas, cerca de 75 ms de latência; a alternativa de melhor qualidade, `eleven_turbo_v2_5`, custa cerca de 250 ms. A escolha não está escondida no código: é um campo da configuração do agente.

02

Catálogo de modelos com latência e custo à vista

78 modelos em `LLM_MODELS`, agrupados por fornecedor na interface juntamente com a latência medida e o custo por minuto — do `gpt-5-nano`, com cerca de 806 ms e uns 0,0004 $/min, ao `claude-sonnet-4-6`, com cerca de 1,55 s e uns 0,0225 $/min. Um cliente que pergunta «porque é que responde devagar» recebe uma resposta com números, não uma opinião.

03

Telefonia própria sobre Asterisk

O reencaminhamento de chamadas configura-se por horário de trabalho e fuso horário, com suporte para horário noturno e correspondência por prioridade (cabeçalho SIP Diversion → número da Kallina → regra de reserva). A ponte `openai-realtime-bridge` faz a conversão AudioSocket entre g711_ulaw e PCM16 para o fluxo de áudio bidirecional.

04

Embed de voz numa só linha, sem id de agente na página

`<script src="https://app.kallina.info/embed.js" data-widget="WIDGET_ID"></script>`. A página nunca fica a saber que agente responde e não guarda nenhuma chave de fornecedor: pede uma sessão à Kallina, e a Kallina devolve um URL assinado de curta duração. Existe também o modo `data-mode="inline"`, em que o embed não desenha absolutamente nada e a página faz a sua própria interface por cima da API `start()` / `stop()` / `toggle()` / `on(event, fn)`.

05

Campanhas de chamadas de saída

Chamada por lotes com 1–10 chamadas em simultâneo, importação de contactos a partir de CSV, lógica de repetição, acompanhamento em tempo real com pausa, retoma e paragem, mais seguimento por SMS.

06

Limbi

A configuração do agente aceita 32 línguas (`LANGUAGES`), o mapa completo de línguas da plataforma tem 41 entradas e o painel de administração está traduzido em 20 (`src/i18n/locales`). O romeno é a língua predefinida em `DEFAULT_VALUES`.

Dados e funcionamento

O que entra no sistema. O que tem de ser verificado.

Onde estão os dados
PostgreSQL através do Supabase, com Row Level Security e pg_cron; 559 migrações versionadas. A lógica de servidor são funções edge Deno — 472 no repositório à data da verificação.
O que nunca chega à página do cliente
A chave do fornecedor de voz e o identificador do agente. O embed pede `POST /functions/v1/widget-voice-session` com `widget_id` — a chave pública de `chat_widget_configs.widget_id`, não o id interno da linha — e o servidor pede ele próprio à ElevenLabs um URL assinado, através de `convai/conversation/get_signed_url`, e devolve-o. A variante antiga, que punha `agentId` diretamente no HTML, contornava a Kallina por completo.
A base de conhecimento
Documentos carregados na plataforma, sincronizados com o RAG da ElevenLabs. Por cima colocam-se limites de conversa, esquemas de recolha de dados e critérios de avaliação do êxito da chamada, definidos por agente.
Consumo medido antes, não depois
A tabela `usage_events` guarda o consumo repartido por fornecedor e por agente. Antes de qualquer ação que custe, a função `check-can-use` verifica o crédito — a porta está antes da chamada, não na fatura do fim do mês.

Da exploração à implementação

Como preparamos um projeto com a Kallina.

01

Escolhemos um único percurso e escrevemos-lhe as margens

Um cenário com entrada clara e saída clara — chamada recebida na receção, confirmação de encomenda, campanha de chamadas. Escrevemos explicitamente o que o agente não pode fazer e por que via entrega a conversa a uma pessoa.

02

Ligamos o número e verificamos nos dois sentidos

O número entra no trunk SIP do nosso Asterisk. As chamadas recebidas e as de saída testam-se em separado, porque podem avariar em separado: uma restrição do operador nas chamadas de saída deixa as de entrada a funcionar na perfeição.

03

Verificamos o percurso sem gastar minutos

`scripts/verify-voice-path.mjs` percorre exatamente o caminho de um navegador — a linha de configuração, `get-widget-config`, depois `widget-voice-session` — e para no URL assinado, sem abrir o websocket. Corre sobre um único widget ou sobre todos os que têm voz ativa, com 1–3 em paralelo, e devolve código de saída, portanto pode entrar diretamente num cron.

Perguntas que vale a pena esclarecer.

Que motor de voz usa, em concreto?

Escolhe entre ElevenLabs Conversational AI, OpenAI Realtime e Gemini Live, ou deixa em «auto» e decide a Kallina conforme a língua e a disponibilidade. Para a síntese de voz em línguas que não o inglês, a predefinição é o modelo `eleven_flash_v2_5` — 32 línguas, à volta de 75 ms; se quiser mais qualidade e aceitar mais atraso, o `eleven_turbo_v2_5` anda à volta dos 250 ms. As vozes do OpenAI Realtime são dez, e o motor deles vai até ao `gpt-realtime-2.1`.

Como se põe num site?

Uma linha: `<script src="https://app.kallina.info/embed.js" data-widget="WIDGET_ID"></script>`, carregada como script normal, não como módulo. O ficheiro é servido hoje e tem 13 762 bytes. Se quiser a sua própria interface, `data-mode="inline"` não desenha nada e deixa-lhe `start()`, `stop()`, `toggle()` e os eventos `state`, `message`, `error`. Atenção ao anfitrião: o ficheiro está em `app.kallina.info`, não em `kallina.info` — são duas aplicações em dois servidores diferentes.

Gastam-se minutos se o visitante recusar o microfone?

Não. A ordem no `embed.js` é: carregar o SDK, pedir o microfone com `getUserMedia({audio:true})` e só depois chamar `widget-voice-session`. Se a pessoa recusar o microfone, o pedido de sessão deixa de ser feito, logo não é emitido nenhum URL assinado e não se gasta nada.

Pode ligar ele primeiro, e não só atender?

Sim — chamada por lotes, 1–10 em simultâneo, contactos a partir de CSV, repetições e seguimento por SMS. Mas as chamadas de saída dependem do operador telefónico, não só de nós: no nosso registo de problemas está documentado um caso em que a central do operador começou a devolver `403 Forbidden` em todas as saídas, com a nossa configuração inalterada e com as chamadas recebidas a funcionar normalmente. É por isso que testamos as saídas em separado antes de prometer uma campanha.

Em quantas línguas fala e em quantas se administra?

A configuração do agente aceita 32 línguas, o mapa interno de línguas tem 41 entradas e o painel de administração está traduzido em 20. O romeno é a língua predefinida dos agentes novos.

Publica-se automaticamente a cada alteração de código?

Não, e é bom saber isso antes de planear um lançamento. O workflow do GitHub no repositório aponta para um projeto Supabase Cloud que foi apagado, portanto «push na main = publicação» deixou de ser verdade desde a migração para infraestrutura própria. A publicação real faz-se por SSH, com cópia e reinício. Consequência prática: uma alteração urgente precisa de uma pessoa, não apenas de um commit.

O que acontece se o agente não souber a resposta?

A entrega a uma pessoa faz parte do cenário, não é uma exceção. Cada agente tem limites escritos e uma via de transferência configurada na telefonia; e na conversa existem limites e critérios de avaliação do êxito, precisamente para que um caso fora do papel seja travado e não improvisado.

Exemplo ilustrativo

Uma chamada recebida de noite, que vai parar onde deve

Um cenário de utilização, sem dados de cliente nem resultados comerciais atribuídos.

A situação inicial

Alguém liga para o número do negócio às 23:40, fora do horário da receção.

Como trabalha

O Asterisk aplica a regra de horário noturno (por exemplo 22:00 → 06:00) e faz a correspondência por prioridade: o cabeçalho SIP Diversion, depois o número da Kallina, depois a regra de reserva. O agente de noite atende no fornecedor escolhido na configuração, esclarece o pedido e chama as ferramentas que tem autorização para usar.

Rezultatul

A chamada fica no histórico com transcript, gravação áudio, duração e custo repartido por fornecedor. O que ultrapassa o papel do agente é travado e transferido, em vez de ser improvisado.

Ce este necesar:Numărul conectat pe trunkul SIP al Asterisk-ului nostru, apelurile ieșite permise de operator dacă se dorește și sunat înapoi, plus un agent cu prompt, bază de cunoștințe aprobată și limite scrise.

Possibilidades de colaboração

A Kallina, no contexto da sua organização.

Informação e recolha de pedidos

Apoio por voz sobre informação aprovada, com passagem a um operador e regras claras quanto à gravação e à conservação das conversas.

Empresas privadas

Definimos um piloto à volta de um processo real: utilizadores, dados, integrações, custos e critérios de aceitação. O alargamento vem depois da avaliação do resultado.

Instituições e empresas públicas

Definimos os requisitos de acessibilidade, alojamento, proteção de dados e interoperabilidade. Qualquer ligação a serviços da Agência de Governação Eletrónica da Moldávia (AGE) ou do serviço nacional de tecnologias de informação (STISC) exige a validação da elegibilidade, do acesso e das aprovações.

Estes são cenários de adaptação, não declarações sobre contratos ou parcerias existentes. As funções propostas confirmam-se no âmbito de trabalho do projeto.

Discută un pilot

Parte de um ecossistema.

O que gostaria que funcionasse melhor?

Conte-nos o seu processo. Em conjunto decidimos o que vale a pena construir, o que podemos ligar e como verificamos o resultado.

Hai să discutăm