Identificação sem senha
O agente descobre quem é o cliente por vínculo de canal com código de uso único — nenhuma senha passa pela conversa — e só então consulta plano e faturas.
Atualizado em 01 de set. de 2026
A pergunta que aparece em toda implantação: "e quando o cliente precisa se identificar? Peço usuário e senha?"
Não. Senha digitada no chat vira mensagem — e mensagem vai para o histórico da conversa, para o contexto do modelo e para o stream de quem acompanha o run. Uma vez lá, não sai.
O que se faz no lugar é o que este fluxo mostra: vincular o canal à conta uma única vez, com um código de uso único enviado ao e-mail cadastrado. Depois disso, o próprio sistema sabe de quem é aquele WhatsApp — e o agente nunca precisa perguntar quem é a pessoa, nem manipular um id de conta.
A propriedade que torna isto seguro
As rotas de dado pessoal (meu_plano, minhas_faturas) não recebem id de conta. Elas recebem channel + identifier — o endereço do canal, que não é segredo — e é o seu back-end que resolve de quem é a conta a partir do vínculo. Assim, mesmo que o modelo erre ou alguém tente induzi-lo, não existe id de outra pessoa para ele passar.
Como importar
Na plataforma: Agents → Importar, escolha o arquivo baixado. Ele entra como um rascunho novo (nada existente é alterado), com ids de observabilidade renovados. Depois preencha o que é do seu ambiente — credenciais, URLs e bases de conhecimento — e publique.
{
"format": "hinow.agent",
"version": 1,
"exported_at": "2026-09-01T00:00:00Z",
"credentials_included": false,
"agent": {
"name": "Identificação sem senha",
"description": "O agente descobre quem é o cliente por vínculo de canal com código de uso único — nenhuma senha passa pela conversa — e só então consulta plano e faturas.",
"avatar": null,
"model": null,
"system_prompt": null,
"config": {},
"tools": null,
"workflow": {
"nodes": [
{
"id": "start",
"type": "start",
"position": {
"x": 300,
"y": 0
},
"data": {
"label": "Início",
"variables": [
{
"name": "channel",
"type": "input",
"required": true,
"description": "Canal em que a conversa chegou: whatsapp, webchat ou email."
},
{
"name": "identifier",
"type": "input",
"required": true,
"description": "Identificador da pessoa neste canal (telefone, id de sessão). Não é segredo: é só o endereço do canal."
}
]
}
},
{
"id": "guard-1",
"type": "guardrails",
"position": {
"x": 288,
"y": 150
},
"data": {
"name": "Porteiro",
"config": {
"target": "input",
"checks": {
"pii": true
},
"fail_message": "A mensagem parece conter um dado sensível (documento, cartão ou telefone completo)."
}
}
},
{
"id": "agent-1",
"type": "agent",
"position": {
"x": 295,
"y": 330
},
"data": {
"name": "conta",
"model": "hinow/himax",
"system_prompt": "Você é o assistente da conta do cliente na Vega Telecom, atendendo pelo canal em que a pessoa escreveu.\n\nDADOS DESTE CANAL — use exatamente estes valores nas ferramentas, sem perguntar e sem inventar:\n- channel: {{channel}}\n- identifier: {{identifier}}\n\nIDENTIDADE — LEIA ANTES DE QUALQUER COISA\nVocê NÃO sabe quem é a pessoa até o sistema dizer. E você NUNCA pede senha, token, número de cartão ou documento — nem para \"confirmar identidade\". Se a pessoa mandar algo assim por conta própria, peça para não repetir e siga sem usar o valor.\n\nO caminho correto é sempre este:\n1. verificar_canal — descobre se este canal já está ligado a uma conta. Faça isso ANTES de qualquer consulta de dado pessoal.\n2. Se já estiver ligado: siga normalmente, chamando a pessoa pelo nome.\n3. Se não estiver: peça só o E-MAIL da conta e chame solicitar_codigo. Explique que vai chegar um código de 6 dígitos no e-mail.\n4. Quando a pessoa disser o código, chame confirmar_codigo. Se der certo, o canal fica ligado para sempre — nunca mais peça código.\n5. Se o código falhar, diga o motivo (errado, expirado) e ofereça pedir outro. Depois de 3 tentativas sem sucesso, ofereça atendimento humano.\n\nRepare: você nunca informa o id da conta para as ferramentas de dado pessoal. É o sistema que resolve a conta a partir do canal ligado — e é por isso que este desenho é seguro.\n\nO QUE VOCÊ RESPONDE\n- Fatura, consumo, plano e status do serviço: sempre pelas ferramentas, com o valor exato.\n- Como funciona o serviço, prazos, regras e procedimentos: pela base de conhecimento.\n- Quando não souber: diga que não sabe e ofereça abrir atendimento humano.\n\nTOM\nCurto, claro, sem jargão. Uma pergunta de cada vez.",
"config": {
"temperature": 0.3,
"max_tool_loops": 12
}
}
},
{
"id": "agent-pii",
"type": "agent",
"position": {
"x": 55,
"y": 330
},
"data": {
"name": "aviso",
"model": "hinow/himax",
"system_prompt": "A mensagem do cliente traz um dado sensível (documento, cartão ou telefone completo). Peça, com gentileza e em uma frase, que ele não envie esse tipo de dado por aqui, explique que não é necessário para o atendimento, e convide a continuar com a dúvida em palavras. Não repita o valor recebido.",
"config": {
"temperature": 0.4,
"tools_filter": []
}
}
},
{
"id": "rag-1",
"type": "rag_search",
"position": {
"x": 575,
"y": 260
},
"data": {
"label": "Base da operadora",
"config": {
"rag_ids": [],
"top_k": 4,
"min_score": 0.35
}
}
},
{
"id": "hook-1",
"type": "webhook",
"position": {
"x": 575,
"y": 405
},
"data": {
"label": "API de contas",
"config": {
"name": "Contas Vega",
"baseUrl": "https://api.suaempresa.com/accounts/v1",
"timeout": 15000,
"auth": {
"type": "bearer",
"token": "COLE_SEU_TOKEN_AQUI"
},
"retryOnError": true,
"maxRetries": 2,
"routes": [
{
"id": "r-verificar_canal",
"name": "verificar_canal",
"method": "GET",
"path": "/identity/channel",
"description": "Diz se este canal (WhatsApp, e-mail, chat) já está ligado a uma conta e, se estiver, o primeiro nome do titular.",
"whenToUse": "SEMPRE no início da conversa, antes de qualquer consulta de dado pessoal.",
"responseDescription": "Se está ligado, o primeiro nome do titular; se não, a indicação de que precisa vincular.",
"parameters": [
{
"name": "channel",
"type": "string",
"required": true,
"description": "Canal desta conversa: whatsapp, webchat ou email",
"howToObtain": "É o canal em que a mensagem chegou",
"example": "whatsapp"
},
{
"name": "identifier",
"type": "string",
"required": true,
"description": "Identificador da pessoa neste canal",
"howToObtain": "No WhatsApp é o telefone de quem escreve; no webchat é o id da sessão",
"example": "5511987654321"
}
],
"enabled": true,
"queryParams": {
"channel": "{{channel}}",
"identifier": "{{identifier}}"
}
},
{
"id": "r-solicitar_codigo",
"name": "solicitar_codigo",
"method": "POST",
"path": "/identity/link/request",
"description": "Envia um código de 6 dígitos para o e-mail cadastrado na conta, para ligar este canal a ela.",
"whenToUse": "Quando verificar_canal disser que o canal não está ligado e a pessoa informar o e-mail da conta. Nunca peça senha no lugar disso.",
"responseDescription": "Confirmação de envio (sem revelar o e-mail completo) ou aviso de que o e-mail não corresponde a nenhuma conta.",
"parameters": [
{
"name": "email",
"type": "string",
"required": true,
"description": "E-mail cadastrado na conta",
"howToObtain": "Pergunte à pessoa qual o e-mail da conta",
"example": "cliente@exemplo.com"
},
{
"name": "channel",
"type": "string",
"required": true,
"description": "Canal desta conversa",
"howToObtain": "O mesmo de verificar_canal",
"example": "whatsapp"
},
{
"name": "identifier",
"type": "string",
"required": true,
"description": "Identificador neste canal",
"howToObtain": "O mesmo de verificar_canal",
"example": "5511987654321"
}
],
"enabled": true,
"bodyTemplate": "{\"email\": \"{{email}}\", \"channel\": \"{{channel}}\", \"identifier\": \"{{identifier}}\"}"
},
{
"id": "r-confirmar_codigo",
"name": "confirmar_codigo",
"method": "POST",
"path": "/identity/link/confirm",
"description": "Confere o código recebido por e-mail e liga este canal à conta em definitivo.",
"whenToUse": "Logo depois que a pessoa disser o código. Se der certo, nunca mais peça código neste canal.",
"responseDescription": "Se o canal foi ligado e o nome do titular, ou o motivo da recusa (código errado, expirado, sem pedido).",
"parameters": [
{
"name": "code",
"type": "string",
"required": true,
"description": "Código de 6 dígitos",
"howToObtain": "A pessoa dita na conversa",
"example": "482913"
},
{
"name": "channel",
"type": "string",
"required": true,
"description": "Canal desta conversa",
"howToObtain": "O mesmo de solicitar_codigo",
"example": "whatsapp"
},
{
"name": "identifier",
"type": "string",
"required": true,
"description": "Identificador neste canal",
"howToObtain": "O mesmo de solicitar_codigo",
"example": "5511987654321"
}
],
"enabled": true,
"bodyTemplate": "{\"code\": \"{{code}}\", \"channel\": \"{{channel}}\", \"identifier\": \"{{identifier}}\"}"
},
{
"id": "r-meu_plano",
"name": "meu_plano",
"method": "GET",
"path": "/account/plan",
"description": "Plano contratado, velocidade, franquia e valor mensal do titular deste canal.",
"whenToUse": "Depois que o canal estiver ligado, quando a pergunta for sobre plano, pacote ou mensalidade.",
"responseDescription": "Nome do plano, valor, benefícios e data de renovação.",
"parameters": [
{
"name": "channel",
"type": "string",
"required": true,
"description": "Canal desta conversa",
"howToObtain": "O mesmo de verificar_canal",
"example": "whatsapp"
},
{
"name": "identifier",
"type": "string",
"required": true,
"description": "Identificador neste canal",
"howToObtain": "O mesmo de verificar_canal",
"example": "5511987654321"
}
],
"enabled": true,
"queryParams": {
"channel": "{{channel}}",
"identifier": "{{identifier}}"
}
},
{
"id": "r-minhas_faturas",
"name": "minhas_faturas",
"method": "GET",
"path": "/account/invoices",
"description": "Últimas faturas do titular deste canal, com status de pagamento.",
"whenToUse": "Depois que o canal estiver ligado, quando a pergunta for sobre fatura, boleto, vencimento ou pagamento.",
"responseDescription": "Lista com competência, valor, vencimento, status e link da segunda via.",
"parameters": [
{
"name": "channel",
"type": "string",
"required": true,
"description": "Canal desta conversa",
"howToObtain": "O mesmo de verificar_canal",
"example": "whatsapp"
},
{
"name": "identifier",
"type": "string",
"required": true,
"description": "Identificador neste canal",
"howToObtain": "O mesmo de verificar_canal",
"example": "5511987654321"
},
{
"name": "limite",
"type": "number",
"required": true,
"description": "Quantas faturas trazer. Use 3 quando a pessoa não especificar — nunca deixe em branco",
"example": "3"
}
],
"enabled": true,
"queryParams": {
"channel": "{{channel}}",
"identifier": "{{identifier}}",
"limite": "{{limite}}"
}
}
]
}
}
},
{
"id": "end-1",
"type": "end",
"position": {
"x": 305,
"y": 510
},
"data": {
"label": "Fim",
"status": "success"
}
}
],
"edges": [
{
"id": "e-start-guard-1-d",
"source": "start",
"target": "guard-1"
},
{
"id": "e-guard-1-agent-1-pass",
"source": "guard-1",
"target": "agent-1",
"sourceHandle": "pass"
},
{
"id": "e-guard-1-agent-pii-fail",
"source": "guard-1",
"target": "agent-pii",
"sourceHandle": "fail"
},
{
"id": "e-rag-1-agent-1-slot-1",
"source": "rag-1",
"target": "agent-1",
"targetHandle": "slot-1"
},
{
"id": "e-hook-1-agent-1-tool",
"source": "hook-1",
"target": "agent-1",
"sourceHandle": "tool",
"targetHandle": "slot-2"
},
{
"id": "e-agent-1-end-1-d",
"source": "agent-1",
"target": "end-1"
},
{
"id": "e-agent-pii-end-1-d",
"source": "agent-pii",
"target": "end-1"
}
]
}
}
}| Card | Por que está aqui | O que faz |
|---|---|---|
| **Início** | Traz o endereço do canal. | channel e identifier chegam no variables do run. Não são segredo — são o telefone/sessão de quem escreveu. |
| **Porteiro (guardrails)** | Rede de proteção. | Checagem pii (determinística, sem custo): CPF, CNPJ, cartão, e-mail e telefone. Saída fail desvia antes de o agente ver. |
**Agent aviso** | O caminho do dado sensível. | Pede gentilmente para não enviar aquilo, sem repetir o valor. tools_filter: []: sem nenhuma ferramenta. |
**Agent conta** | O atendimento de verdade. | Segue o roteiro de identidade: verificar canal → (se preciso) código → consultar. Nunca pede senha. |
| **Webhook** (5 rotas) | Identidade e dados da conta. | 3 rotas de vínculo + 2 de consulta. Todas por channel/identifier. |
| **Conhecimento (RAG)** | O que não é pessoal. | Como funciona o serviço, prazos, procedimentos. Não depende de saber quem é a pessoa. |
- 1
`verificar_canal`
Sempre primeiro. Diz se este WhatsApp já está ligado a uma conta e o primeiro nome do titular.
- 2
Já vinculado? Segue a vida
O agente chama pelo nome e responde. Nenhuma pergunta de identidade.
- 3
Não vinculado: pede só o e-mail
solicitar_codigomanda um código de 6 dígitos para o e-mail cadastrado — quem não tem acesso ao e-mail não avança. - 4
`confirmar_codigo`
A pessoa dita o código, o canal fica ligado em definitivo. Nunca mais se pede código nesse canal.
- 5
Consulta liberada
meu_planoeminhas_faturasrespondem pelo titular do canal — sem id de conta trafegando.
Três coisas que o seu back-end precisa fazer
1. Expirar o código (5–10 minutos) e limitar tentativas. 2. Nunca revelar o e-mail completo na resposta de solicitar_codigo (c***@exemplo.com) — senão a rota vira ferramenta de descoberta de e-mail. 3. Responder igual para e-mail que existe e que não existe, pelo mesmo motivo.
Aí a troca acontece fora da conversa, não dentro dela:
- A sua aplicação já autenticou a pessoa (app, área logada, portal): ela manda o identificador no
variablesdo run e você nem precisa deste fluxo — é o padrão do Suporte com chamados. - A conversa começa em canal aberto (WhatsApp, Instagram): use este fluxo. O código de uso único substitui a senha com segurança melhor, não pior.
- Precisa mesmo de credencial por usuário na chamada HTTP: existe um caminho em que o segredo não passa pelo modelo — o card MCP resolve
{{variáveis}}nos headers da conexão. Está explicado em Credenciais e identidade.
O que nunca funciona bem é pedir a senha no chat e mandá-la numa rota de login: o valor fica no histórico, o token de volta também, e você acabou de transformar uma conversa num cofre.
- Outro canal:
channelaceita o que você quiser (whatsapp,webchat,instagram,email) — o vínculo é por par canal+identificador. - Outro segundo fator: SMS no lugar do e-mail, se o cadastro tiver telefone verificado. O desenho não muda.
- Mais consultas: cada dado do titular vira uma rota nova por
channel/identifier. Nunca por id de conta vindo do modelo. - Guardrails mais rígido:
blocklistpara termos proibidos ejailbreak/moderation(esses custam uma classificação por mensagem).
Todos os fluxos prontos
Outros agents completos para importar e adaptar.

