Framework Python para deployar agentes de IA no WhatsApp em menos de 24h
Project description
🤖 whatsapp-agent-ipnet
Framework Python para criar e deployar agentes de Inteligência Artificial no WhatsApp — do zero ao ar em menos de 24 horas.
📋 Índice
- O que é isso?
- Como funciona por dentro?
- O que você vai precisar
- 🔐 IAM — Roles necessárias no GCP ← leia antes de começar
- Configuração passo a passo
- Seu primeiro agente
- Entendendo o system prompt
- Adicionando ferramentas (Tools)
- Conectando o WhatsApp (QR Code)
- Variáveis de ambiente
- Deploy em produção (Cloud Run)
- CLI — todos os comandos
- Exemplos práticos
- Perguntas frequentes
- Solução de problemas
💡 O que é isso?
O whatsapp-agent-ipnet é um framework Python que permite criar um agente de Inteligência Artificial que conversa com pessoas pelo WhatsApp.
O que é um "agente de IA"?
Um agente de IA é diferente de um chatbot comum. Um chatbot segue um fluxo fixo de respostas pré-programadas ("se o usuário digitar X, responda Y"). Um agente é capaz de:
- Entender linguagem natural em qualquer formato
- Decidir sozinho qual ação tomar com base no contexto
- Chamar funções do seu sistema (consultar banco de dados, APIs externas, etc.)
- Lembrar do histórico da conversa
- Raciocinar para resolver problemas complexos
O que este framework faz por você?
Sem ele, para criar um agente no WhatsApp você precisaria construir do zero:
- Integração com a API do WhatsApp
- Servidor web para receber mensagens
- Lógica para não responder antes do usuário terminar de digitar
- Banco de dados para guardar o histórico de cada conversa
- Integração com o modelo de IA (Gemini)
- Sistema de "ferramentas" que o agente pode usar
- Script de deploy para nuvem
Com o whatsapp-agent-ipnet, tudo isso já está pronto. Você só precisa escrever o comportamento do seu agente e as funções que ele pode usar.
🔍 Como funciona por dentro?
Usuário digita no WhatsApp
│
▼
Evolution API ← Plataforma que conecta ao WhatsApp
│ webhook (HTTP)
▼
Seu servidor (FastAPI)
│
▼
Debouncer (5 segundos) ← Espera o usuário terminar de digitar
│ antes de processar
▼
Agente Agno + Gemini ← A IA pensa e decide o que fazer
│
├──→ Consulta histórico da conversa (PostgreSQL)
├──→ Verifica sessão ativa (Redis)
└──→ Chama suas ferramentas (funções Python)
│
▼
Evolution API ← Envia a resposta de volta
│
▼
Usuário recebe a resposta no WhatsApp
Por que o "Debouncer de 5 segundos"?
Imagine que o usuário está digitando:
[12:00:01] "oi"
[12:00:02] "quero saber"
[12:00:04] "sobre os planos"
[12:00:05] "disponíveis"
Sem o debouncer, o agente responderia 4 vezes, uma para cada mensagem, causando respostas estranhas e gastando tokens desnecessariamente.
Com o debouncer, o sistema aguarda 5 segundos após a última mensagem e só então processa tudo junto como uma única pergunta: "oi\nquero saber\nsobre os planos\ndisponíveis".
✅ O que você vai precisar
| Requisito | Onde fica | Para que serve |
|---|---|---|
| Python 3.11+ | Sua máquina local | Escrever e testar o agente |
| Google Cloud Project | GCP | Onde tudo roda em produção |
| Google Gemini API Key | Google AI Studio | O cérebro do agente (IA) |
| Cloud SQL (PostgreSQL) | GCP — via gcloud CLI | Histórico de conversas |
| Memorystore (Redis) | GCP — via gcloud CLI | Sessões ativas em memória |
| Cloud Run | GCP — via gcloud CLI | Servidor do agente |
| Evolution API | VPS ou serviço externo | Conectar ao WhatsApp |
| Um número de WhatsApp | Seu chip | Para o agente operar |
Toda a infraestrutura de banco, cache e servidor fica no GCP. Você não instala Redis nem PostgreSQL na sua máquina — apenas o Python para escrever o código.
🔐 IAM — Roles necessárias no GCP
Leia isso antes de começar. Sem as permissões certas, qualquer passo da configuração vai falhar. Este mapeamento cobre as três identidades que precisam de acesso no GCP.
Existem três identidades que precisam de permissões diferentes no GCP. Entender isso evita os erros mais frustrantes do deploy.
┌─────────────────────────────────────────────────────────┐
│ 1. Sua conta Google (desenvolvedor) │
│ Roda os comandos gcloud para criar infraestrutura │
├─────────────────────────────────────────────────────────┤
│ 2. whatsapp-agent-sa (Service Account do Cloud Run) │
│ Identidade do agente em produção │
├─────────────────────────────────────────────────────────┤
│ 3. Cloud Build SA (criada automaticamente pelo GCP) │
│ Roda o build e faz o deploy da imagem │
└─────────────────────────────────────────────────────────┘
Identidade 1 — Sua conta de desenvolvedor
Roles mínimas para rodar todos os comandos de infraestrutura deste guia:
# Substitua developer@suaempresa.com pelo seu e-mail do GCP
DEVELOPER="developer@suaempresa.com"
PROJECT="SEU_PROJECT_ID"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/servicemanagement.admin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/iam.serviceAccountAdmin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/resourcemanager.projectIamAdmin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/cloudsql.admin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/redis.admin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/compute.networkAdmin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/secretmanager.admin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT --member="user:$DEVELOPER" --role="roles/iam.serviceAccountUser"
O que cada role permite:
| Role | O que permite | Qual comando usa |
|---|---|---|
roles/servicemanagement.admin |
Ativar APIs (gcloud services enable) |
Passo 3 |
roles/iam.serviceAccountAdmin |
Criar a Service Account | Passo 4 |
roles/resourcemanager.projectIamAdmin |
Conceder roles a outros via add-iam-policy-binding |
Passos 4 e 8 |
roles/cloudsql.admin |
Criar instância, banco, usuário no Cloud SQL | Passo 5 |
roles/redis.admin |
Criar instância do Memorystore | Passo 6 |
roles/compute.networkAdmin |
Criar o VPC Connector | Passo 7 |
roles/secretmanager.admin |
Criar e gerenciar secrets | Passo 8 |
roles/cloudbuild.builds.editor |
Disparar builds via gcloud builds submit |
Deploy |
roles/run.admin |
Criar e atualizar serviços no Cloud Run | Deploy |
roles/iam.serviceAccountUser |
Fazer deploy com --service-account |
Deploy |
Não tem acesso para se dar essas roles? Peça para o administrador do projeto executar o bloco acima com a sua conta. Se o projeto for seu, sua conta provavelmente já é
roles/ownere pode pular esse passo.
Identidade 2 — Service Account do Cloud Run
Esta é a identidade que o agente usa em produção para acessar o banco, o Redis e os secrets.
💡 Dica: Use o comando
whatsapp-agent setup-sapara criar a SA e atribuir todas as roles abaixo automaticamente, com o nome gerado a partir do seu nome e do projeto.
SA="whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com"
PROJECT="SEU_PROJECT_ID"
# OBRIGATÓRIO — conectar ao Cloud SQL em runtime
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:$SA" --role="roles/cloudsql.client"
# OBRIGATÓRIO — ler secrets em runtime (Gemini key, Redis URL, DB password)
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:$SA" --role="roles/secretmanager.secretAccessor"
# RECOMENDADO — acesso de leitura/escrita ao Memorystore
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:$SA" --role="roles/redis.editor"
# OBRIGATÓRIO — gravar logs no Cloud Logging
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:$SA" --role="roles/logging.logWriter"
| Role | Por que é necessária | Erro se faltar |
|---|---|---|
roles/cloudsql.client |
Cloud SQL Auth Proxy usa para autenticar a conexão | Cloud SQL client does not have permission to access the instance |
roles/secretmanager.secretAccessor |
Lê as variáveis sensíveis no startup | Agente sobe sem as credenciais — falha silenciosa |
roles/redis.editor |
Escreve sessões ativas no Memorystore | Timeout ao tentar salvar sessão |
roles/logging.logWriter |
Envia logs para o Cloud Logging | Logs não aparecem no console do GCP |
Identidade 3 — Cloud Build Service Account
O Cloud Build cria automaticamente uma SA no formato [PROJECT_NUMBER]@cloudbuild.gserviceaccount.com. Ela precisa de permissão para fazer deploy no Cloud Run e publicar a imagem Docker.
Pegar o número do projeto:
gcloud projects describe SEU_PROJECT_ID --format='value(projectNumber)'
# Exemplo de saída: 123456789012
Conceder as roles:
PROJECT_NUMBER=$(gcloud projects describe SEU_PROJECT_ID --format='value(projectNumber)')
CB_SA="${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com"
# OBRIGATÓRIO — fazer deploy no Cloud Run
gcloud projects add-iam-policy-binding SEU_PROJECT_ID \
--member="serviceAccount:$CB_SA" --role="roles/run.admin"
# OBRIGATÓRIO — publicar imagem Docker no Container Registry
gcloud projects add-iam-policy-binding SEU_PROJECT_ID \
--member="serviceAccount:$CB_SA" --role="roles/storage.admin"
# OBRIGATÓRIO — fazer deploy usando a SA do agente (--service-account no deploy)
gcloud iam service-accounts add-iam-policy-binding \
whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com \
--member="serviceAccount:$CB_SA" \
--role="roles/iam.serviceAccountUser"
| Role | Por que é necessária | Erro se faltar |
|---|---|---|
roles/run.admin |
O Cloud Build deploya o serviço no final do build | Build step failed: run.services.create permission denied |
roles/storage.admin |
Push da imagem para gcr.io/SEU_PROJECT_ID/... |
denied: requested access to the resource is denied |
roles/iam.serviceAccountUser |
Permite usar --service-account no deploy |
The caller does not have permission to act as the service account |
Visão consolidada — todas as roles de uma vez
Sua conta (desenvolvedor)
├── roles/servicemanagement.admin
├── roles/iam.serviceAccountAdmin
├── roles/resourcemanager.projectIamAdmin
├── roles/cloudsql.admin
├── roles/redis.admin
├── roles/compute.networkAdmin
├── roles/secretmanager.admin
├── roles/cloudbuild.builds.editor
├── roles/run.admin
└── roles/iam.serviceAccountUser
whatsapp-agent-sa (runtime)
├── roles/cloudsql.client ← OBRIGATÓRIO
├── roles/secretmanager.secretAccessor ← OBRIGATÓRIO
├── roles/redis.editor ← RECOMENDADO
└── roles/logging.logWriter ← RECOMENDADO
Cloud Build SA (build/deploy)
├── roles/run.admin ← OBRIGATÓRIO
├── roles/storage.admin ← OBRIGATÓRIO
└── roles/iam.serviceAccountUser ← OBRIGATÓRIO
Como verificar as roles atuais de qualquer identidade
# Ver roles da sua conta
gcloud projects get-iam-policy SEU_PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:developer@suaempresa.com" \
--format="table(bindings.role)"
# Ver roles da Service Account do agente
gcloud projects get-iam-policy SEU_PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com" \
--format="table(bindings.role)"
# Ver roles da Cloud Build SA
PROJECT_NUMBER=$(gcloud projects describe SEU_PROJECT_ID --format='value(projectNumber)')
gcloud projects get-iam-policy SEU_PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--format="table(bindings.role)"
🚀 Configuração passo a passo
1. Instalar o Python (na sua máquina)
O framework requer Python 3.11 ou superior.
Verificar se já tem Python instalado:
python3 --version
# Deve mostrar: Python 3.11.x ou superior
Se não tiver ou a versão for antiga:
- macOS:
brew install python@3.11 - Ubuntu/Debian:
sudo apt install python3.11 python3.11-venv python3-pip - Windows: Baixe em python.org/downloads e marque a opção "Add Python to PATH" durante a instalação
2. Instalar o gcloud CLI (na sua máquina)
O gcloud é a ferramenta de linha de comando do Google Cloud. Todos os comandos de infraestrutura são executados por ela.
macOS:
brew install --cask google-cloud-sdk
Linux:
curl https://sdk.cloud.google.com | bash
exec -l $SHELL # recarrega o terminal
Windows: Baixe o instalador em cloud.google.com/sdk/docs/install
Autenticar e configurar o projeto:
gcloud auth login
# Abre o navegador para login com sua conta Google
gcloud config set project SEU_PROJECT_ID
# Substitua SEU_PROJECT_ID pelo ID do seu projeto no GCP
# Ex: gcloud config set project minha-empresa-prod
Não sabe o Project ID? Acesse console.cloud.google.com e ele aparece no topo da página.
3. Ativar as APIs necessárias no GCP
Execute este bloco de uma vez. Cada API habilita um serviço diferente:
gcloud services enable \
sqladmin.googleapis.com \
redis.googleapis.com \
vpcaccess.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
secretmanager.googleapis.com \
servicenetworking.googleapis.com \
compute.googleapis.com
Isso pode levar alguns minutos. Você só precisa fazer isso uma vez por projeto.
4. Criar a Service Account (identidade do agente no GCP)
A Service Account é a "identidade" que o Cloud Run usa para acessar os outros serviços do GCP com segurança.
# Criar a service account
gcloud iam service-accounts create whatsapp-agent-sa \
--display-name="WhatsApp Agent Service Account"
# Dar permissão para acessar o Cloud SQL
gcloud projects add-iam-policy-binding SEU_PROJECT_ID \
--member="serviceAccount:whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
# Dar permissão para acessar o Memorystore (Redis)
gcloud projects add-iam-policy-binding SEU_PROJECT_ID \
--member="serviceAccount:whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/redis.viewer"
# Dar permissão para ler secrets do Secret Manager
gcloud projects add-iam-policy-binding SEU_PROJECT_ID \
--member="serviceAccount:whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
Substitua
SEU_PROJECT_IDem todos os comandos pelo seu Project ID real.
5. Criar o Cloud SQL — PostgreSQL (banco de dados)
O Cloud SQL é o PostgreSQL gerenciado do GCP. Guarda todo o histórico de conversas.
# Criar a instância PostgreSQL (leva ~5 minutos)
gcloud sql instances create whatsapp-agent-db \
--database-version=POSTGRES_15 \
--tier=db-f1-micro \
--region=us-central1 \
--storage-type=SSD \
--storage-size=10GB \
--storage-auto-increase
# Criar o banco de dados dentro da instância
gcloud sql databases create agentdb \
--instance=whatsapp-agent-db
# Criar o usuário do banco com senha
gcloud sql users create agentuser \
--instance=whatsapp-agent-db \
--password=TROQUE_POR_UMA_SENHA_FORTE
# Pegar o "connection name" (você vai precisar depois)
gcloud sql instances describe whatsapp-agent-db \
--format='value(connectionName)'
# Saída: SEU_PROJECT_ID:us-central1:whatsapp-agent-db
# Guarde esse valor!
Tiers disponíveis:
db-f1-micro— ~$7/mês, para desenvolvimento e baixo volumedb-g1-small— ~$25/mês, para produção com volume médiodb-custom-2-8192— 2 vCPU + 8GB RAM, para alto volume
As tabelas são criadas automaticamente
O framework cria todas as tabelas necessárias na primeira vez que o agente sobe. Você não precisa rodar nenhum SQL manualmente para começar.
As tabelas criadas automaticamente são:
| Tabela | Criada por | Para que serve |
|---|---|---|
ipnet_conversation_history |
ConversationHistory.setup() |
Histórico de mensagens por número |
ipnet_agno_sessions |
PostgresStorage do Agno |
Estado interno do agente (memória do loop) |
Como conectar no Cloud SQL via terminal (quando precisar)
Para verificar tabelas, rodar SQL manual ou importar dados existentes, use o gcloud sql connect:
# Conectar diretamente no banco via terminal
# (requer que o Cloud SQL Auth Proxy esteja instalado — o gcloud instala automaticamente)
gcloud sql connect whatsapp-agent-db \
--user=agentuser \
--database=agentdb
# Vai pedir a senha que você definiu no passo anterior
Dentro do psql, você pode rodar qualquer SQL:
-- Ver tabelas criadas pelo framework
\dt
-- Ver histórico de conversas
SELECT phone, role, content, created_at
FROM ipnet_conversation_history
ORDER BY created_at DESC
LIMIT 20;
-- Contar mensagens por número
SELECT phone, COUNT(*) as total
FROM ipnet_conversation_history
GROUP BY phone
ORDER BY total DESC;
-- Sair do psql
\q
Importar dados de um banco existente
Se você já tem um banco PostgreSQL com dados e quer migrar para o Cloud SQL:
# 1. Exportar do banco atual (na sua máquina ou servidor antigo)
pg_dump -U usuario -d banco_atual -f backup.sql
# 2. Enviar o arquivo para o Cloud Storage
gsutil cp backup.sql gs://SEU_PROJECT_ID-backups/backup.sql
# 3. Importar no Cloud SQL
gcloud sql import sql whatsapp-agent-db \
gs://SEU_PROJECT_ID-backups/backup.sql \
--database=agentdb
Se não tiver um bucket no Cloud Storage ainda:
gsutil mb -l us-central1 gs://SEU_PROJECT_ID-backups
6. Criar o Memorystore — Redis (cache de sessão)
O Memorystore é o Redis gerenciado do GCP. Guarda as sessões ativas das conversas em andamento.
⚠️ Importante: O Memorystore usa IP interno (VPC). O Cloud Run precisa de um VPC Connector para acessá-lo — veja o passo seguinte.
# Criar a instância Redis (leva ~3 minutos)
gcloud redis instances create whatsapp-agent-redis \
--size=1 \
--region=us-central1 \
--tier=basic \
--redis-version=redis_7_0 \
--network=projects/SEU_PROJECT_ID/global/networks/default
# Pegar o IP interno do Redis (você vai precisar depois)
gcloud redis instances describe whatsapp-agent-redis \
--region=us-central1 \
--format='value(host)'
# Saída: 10.x.x.x
# Guarde esse IP!
O Redis no GCP não tem URL como
redis://localhost— ele tem um IP interno como10.0.0.27. A porta é sempre6379.
7. Criar o VPC Connector (ponte entre Cloud Run e Redis)
O Cloud Run roda em ambiente isolado. Para acessar o Memorystore (que está na VPC), precisa de um conector.
# Criar o VPC Connector
gcloud compute networks vpc-access connectors create whatsapp-agent-connector \
--region=us-central1 \
--network=default \
--range=10.8.0.0/28 \
--min-instances=2 \
--max-instances=10 \
--machine-type=e2-micro
# Verificar se foi criado corretamente
gcloud compute networks vpc-access connectors describe whatsapp-agent-connector \
--region=us-central1
# O campo "state" deve mostrar: READY
O que é o
--range=10.8.0.0/28? É um bloco de IPs reservado para o conector dentro da sua rede. Certifique-se de que esse range não conflita com outros já usados na sua VPC. Se der erro, tente10.9.0.0/28.
8. Salvar credenciais no Secret Manager
Nunca coloque senhas diretamente em variáveis de ambiente ou código. O Secret Manager do GCP guarda tudo com segurança.
# URL do PostgreSQL (usando o IP do Cloud SQL Auth Proxy)
echo -n "postgresql+asyncpg://agentuser:TROQUE_POR_UMA_SENHA_FORTE@127.0.0.1:5432/agentdb" | \
gcloud secrets create ipnet-postgres-url --data-file=-
# URL do Redis (substitua 10.x.x.x pelo IP que você obteve no passo 6)
echo -n "redis://10.x.x.x:6379/0" | \
gcloud secrets create ipnet-redis-url --data-file=-
# Chave do Gemini (obtenha em https://aistudio.google.com/app/apikey)
echo -n "AIzaSy..." | \
gcloud secrets create ipnet-gemini-key --data-file=-
# API Key da Evolution API
echo -n "sua-api-key-da-evolution" | \
gcloud secrets create ipnet-evolution-key --data-file=-
Dar permissão para a service account ler os secrets:
for secret in ipnet-postgres-url ipnet-redis-url ipnet-gemini-key ipnet-evolution-key; do
gcloud secrets add-iam-policy-binding $secret \
--member="serviceAccount:whatsapp-agent-sa@SEU_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
done
9. Configurar a Evolution API
A Evolution API é o intermediário entre seu agente e o WhatsApp. Você precisa de uma instância rodando em algum lugar acessível publicamente (não pode ficar só dentro do GCP sem IP externo).
Opção A — VPS com Docker (recomendado):
Em qualquer VPS (DigitalOcean, Hetzner, etc.):
docker run -d \
--name evolution-api \
-p 8080:8080 \
-e SERVER_URL=https://SEU_DOMINIO_OU_IP:8080 \
-e AUTHENTICATION_API_KEY=TROQUE_POR_KEY_SEGURA \
atendai/evolution-api:latest
Opção B — Railway / Render: Consulte a documentação em doc.evolution-api.com para deploy com um clique.
Anote a URL e a API Key da Evolution API — você vai precisar no próximo passo.
5. Instalar o pacote
💡 Todo esse processo é feito no terminal do VS Code. Abra com
Ctrl + ```` ` (backtick) ou pelo menu Terminal → New Terminal.
Passo 1 — Criar uma pasta para o projeto e abrir no VS Code
# Crie e entre na pasta onde ficará seu agente
mkdir meus-agentes
cd meus-agentes
code .
O VS Code vai abrir. A partir daqui, use o terminal integrado dele (Ctrl + `).
Passo 2 — Criar um ambiente virtual isolado
O ambiente virtual evita conflitos com outros pacotes Python instalados no seu computador.
# No terminal do VS Code:
python3 -m venv .venv
Passo 3 — Ativar o ambiente virtual
macOS/Linux:
source .venv/bin/activate
Windows (PowerShell):
.venv\Scripts\Activate.ps1
Windows (CMD):
.venv\Scripts\activate.bat
Quando ativado corretamente, você verá (.venv) no início da linha do terminal:
(.venv) Usuario@MacBook meus-agentes %
⚠️ Importante: Sempre que abrir um novo terminal no VS Code, você precisa ativar o ambiente virtual novamente com o comando acima. O VS Code pode fazer isso automaticamente — veja abaixo.
Passo 4 — Configurar o VS Code para ativar automaticamente
- Pressione
Ctrl+Shift+P(ouCmd+Shift+Pno Mac) - Digite "Python: Select Interpreter"
- Selecione a opção que mostra
.venvna lista (ex:Python 3.11.x ('.venv'))
Pronto — o VS Code vai ativar o .venv automaticamente em todo novo terminal.
Passo 5 — Instalar o framework
Com o ambiente virtual ativado (veja o (.venv) no terminal):
pip install whatsapp-agent-ipnet
Verificar a instalação:
whatsapp-agent --help
# Deve mostrar os comandos disponíveis
Conflitos de versão? Se aparecer um aviso
ERROR: pip's dependency resolver..., pode ignorar com segurança. São avisos sobre outros pacotes instalados globalmente, não afetam o funcionamento do framework.
🛠️ Seu primeiro agente
Todos os comandos abaixo são executados no terminal do VS Code (
Ctrl + `````) com o ambiente virtual ativado (você deve ver(.venv)no início da linha).
Passo 1 — Criar o projeto
whatsapp-agent init meu-primeiro-agente
cd meu-primeiro-agente
Após o
cd, o VS Code pode perguntar se deseja abrir a pasta no explorer — clique em "Sim" para navegar pelos arquivos pelo painel lateral.
Isso vai criar a seguinte estrutura:
meu-primeiro-agente/
├── main.py ← Seu agente (edite aqui)
├── .env ← Configurações e senhas (NUNCA suba pro Git)
├── .env.example ← Modelo de configuração sem senhas
├── .gitignore ← Já ignora o .env automaticamente
├── Dockerfile ← Para deploy em produção
└── requirements.txt ← Dependências do projeto
Passo 2 — Configurar as credenciais
Abra o arquivo .env e preencha:
# Sua chave do Google Gemini
# Obtenha em: https://aistudio.google.com/app/apikey
IPNET_GEMINI_API_KEY=AIzaSy...
# URL onde a Evolution API está rodando
IPNET_EVOLUTION_API_URL=http://localhost:8081
# A chave que você definiu na Evolution API
IPNET_EVOLUTION_API_KEY=minha-chave-secreta
# Nome único para sua instância do WhatsApp
IPNET_INSTANCE_NAME=meu-primeiro-agente
# Conexão com o PostgreSQL
# Formato: postgresql+asyncpg://USUARIO:SENHA@HOST:PORTA/BANCO
IPNET_POSTGRES_URL=postgresql+asyncpg://postgres:suasenha@localhost:5432/agentdb
# Conexão com o Redis
IPNET_REDIS_URL=redis://localhost:6379/0
Passo 3 — Escrever o agente
Abra o main.py. Você vai ver algo assim:
from whatsapp_agent_ipnet import WhatsAppAgent
agent = WhatsAppAgent.from_env(
name="Meu Agente",
system_prompt="""
Você é um assistente virtual inteligente.
Responda sempre em português de forma clara e objetiva.
""",
)
if __name__ == "__main__":
agent.start()
Passo 4 — Rodar localmente
python main.py
Você verá no terminal:
INFO: Iniciando Meu Agente...
INFO: Redis conectado: redis://localhost:6379/0
INFO: ConversationHistory pronto.
INFO: Meu Agente pronto na porta 8080
INFO: Uvicorn running on http://0.0.0.0:8080
Passo 5 — Escanear o QR Code
Em outro terminal (com o ambiente virtual ativado):
whatsapp-agent qrcode
Um QR Code vai aparecer no terminal. Escaneie com o WhatsApp do celular que vai ser usado pelo agente:
WhatsApp → Menu (3 pontinhos) → Dispositivos conectados → Conectar dispositivo
⚠️ Importante: Use um número separado para o agente, não o seu número pessoal principal. Uma vez conectado, o WhatsApp vai operar como um dispositivo vinculado.
📝 Entendendo o System Prompt
O system_prompt é a instrução principal que define como o agente vai se comportar. É como um "manual de conduta" que o agente segue em todas as conversas.
Como escrever um bom system prompt
Estrutura recomendada:
system_prompt="""
[IDENTIDADE]
Você é [nome/papel] da empresa [nome da empresa].
[OBJETIVO]
Seu objetivo principal é [o que o agente deve fazer].
[REGRAS DE COMPORTAMENTO]
- Regra 1
- Regra 2
- Regra 3
[TOM DE VOZ]
- [Como deve falar]
[LIMITAÇÕES]
- Nunca [o que não deve fazer]
- Sempre [o que sempre deve fazer]
"""
Exemplo completo para uma clínica:
system_prompt="""
Você é a assistente virtual da Clínica Saúde Total, chamada Sofia.
Seu objetivo é ajudar pacientes a:
- Agendar, remarcar e cancelar consultas
- Informar sobre especialidades disponíveis
- Explicar como funciona o convênio
- Tirar dúvidas gerais sobre a clínica
Regras de comportamento:
- Sempre se apresente pelo nome "Sofia" no primeiro contato
- Trate todos com muito respeito, usando "senhor" ou "senhora"
- Nunca dê diagnósticos médicos ou conselhos de saúde
- Se não souber a resposta, diga que vai verificar com a equipe
Tom de voz: acolhedor, profissional e empático.
Horário de atendimento: segunda a sexta, das 8h às 18h, sábados das 8h às 12h.
"""
Dicas importantes
- Seja específico: Quanto mais detalhado o prompt, mais previsível o comportamento
- Defina limitações: Diga o que o agente NÃO deve fazer
- Use português claro: O modelo entende bem PT-BR
- Teste bastante: Simule conversas reais para ajustar o comportamento
🔧 Adicionando ferramentas (Tools)
Ferramentas são funções Python que você dá ao agente para que ele possa executar ações no mundo real. O agente decide sozinho quando e como usar cada ferramenta com base no contexto da conversa.
Como funciona na prática
@agent.tool
def consultar_saldo(cpf: str) -> str:
"""Consulta o saldo disponível de um cliente pelo CPF"""
# Aqui você coloca sua lógica real
saldo = seu_banco_de_dados.buscar_saldo(cpf)
return f"Saldo disponível: R$ {saldo:.2f}"
Quando o usuário disser "qual meu saldo?" e fornecer o CPF, o agente vai automaticamente chamar essa função e usar o resultado para formular a resposta.
Regras para escrever boas ferramentas
1. A docstring é obrigatória e crucial
O LLM usa a docstring para decidir quando chamar a ferramenta. Seja descritivo:
# ❌ Ruim — docstring vaga
@agent.tool
def buscar(x: str) -> str:
"""Busca algo"""
...
# ✅ Bom — docstring clara
@agent.tool
def buscar_produto_por_nome(nome_produto: str) -> str:
"""
Busca informações detalhadas de um produto pelo nome exato ou parcial.
Retorna preço, disponibilidade em estoque e prazo de entrega.
Use quando o cliente perguntar sobre um produto específico.
"""
...
2. Use type hints nos parâmetros
O framework usa os tipos para gerar o schema da ferramenta automaticamente:
@agent.tool
def agendar_consulta(
nome_paciente: str,
data: str, # formato: DD/MM/AAAA
horario: str, # formato: HH:MM
especialidade: str,
) -> str:
"""Agenda uma consulta médica para o paciente"""
...
3. Sempre retorne strings descritivas
O retorno da função é o que o agente vai receber como resultado. Seja informativo:
# ❌ Ruim — retorno obscuro
return True
# ✅ Bom — retorno descritivo
return "Consulta agendada com sucesso para 15/06/2025 às 14:30 com Dr. Silva (Cardiologia). ID de confirmação: #4821"
4. Trate erros dentro da ferramenta
@agent.tool
def consultar_cep(cep: str) -> str:
"""Busca o endereço completo a partir de um CEP brasileiro"""
import httpx
try:
cep_limpo = "".join(c for c in cep if c.isdigit())
if len(cep_limpo) != 8:
return "CEP inválido. Por favor, informe um CEP com 8 dígitos."
resp = httpx.get(f"https://viacep.com.br/ws/{cep_limpo}/json/", timeout=5)
data = resp.json()
if data.get("erro"):
return f"CEP {cep} não encontrado."
return f"{data['logradouro']}, {data['bairro']}, {data['localidade']}-{data['uf']}, CEP: {data['cep']}"
except Exception as e:
return f"Não foi possível consultar o CEP no momento. Tente novamente em instantes."
Exemplos de tools comuns
Consultar banco de dados:
@agent.tool
def buscar_pedido(numero_pedido: str) -> str:
"""Busca o status e informações de um pedido pelo número"""
import psycopg2
conn = psycopg2.connect(os.environ["DATABASE_URL"])
cur = conn.cursor()
cur.execute("SELECT status, data_entrega FROM pedidos WHERE numero = %s", (numero_pedido,))
row = cur.fetchone()
if not row:
return f"Pedido {numero_pedido} não encontrado."
status, data_entrega = row
return f"Pedido {numero_pedido}: {status}. Previsão de entrega: {data_entrega}"
Chamar uma API externa:
@agent.tool
def verificar_clima(cidade: str) -> str:
"""Verifica a previsão do tempo para uma cidade brasileira"""
import httpx
resp = httpx.get(
"https://wttr.in/{cidade}?format=3&lang=pt".format(cidade=cidade),
timeout=5
)
return resp.text
Enviar e-mail:
@agent.tool
def enviar_confirmacao_email(email: str, mensagem: str) -> str:
"""Envia um e-mail de confirmação para o cliente"""
import smtplib
# sua lógica de envio de e-mail
return f"E-mail de confirmação enviado para {email}"
📱 Conectando o WhatsApp (QR Code)
Como funciona a conexão
O framework usa a Evolution API que, por sua vez, usa a biblioteca Baileys para conectar ao WhatsApp Web. Isso significa que você precisa de um número de WhatsApp real (não é a API oficial do Meta para empresas).
Passo a passo
1. Com o servidor rodando (python main.py), execute:
whatsapp-agent qrcode
2. No celular:
- Abra o WhatsApp
- Toque nos 3 pontinhos (Android) ou em "Configurações" (iPhone)
- Selecione "Dispositivos conectados"
- Toque em "Conectar dispositivo"
- Aponte a câmera para o QR Code no terminal
3. Aguarde a confirmação:
✅ WhatsApp conectado: meu-primeiro-agente
Configurar o webhook
Após conectar, você precisa dizer para a Evolution API para onde enviar as mensagens recebidas. Isso é feito automaticamente quando você cria a instância, mas verifique se o webhook está configurado:
URL do webhook (onde seu servidor está rodando):
http://SEU_IP_OU_DOMINIO:8080/webhook/NOME_DA_INSTANCIA
Exemplo local (usando ngrok para expor localmente):
# Instale ngrok: https://ngrok.com/download
ngrok http 8080
# Vai gerar uma URL como: https://abc123.ngrok.io
# Webhook: https://abc123.ngrok.io/webhook/meu-primeiro-agente
Por que preciso do ngrok localmente? A Evolution API precisa conseguir enviar mensagens para o seu servidor. Como seu computador não tem um IP público direto, o ngrok cria um "túnel" temporário.
⚙️ Variáveis de ambiente (.env)
O arquivo .env guarda todas as configurações e credenciais do seu agente. Nunca suba esse arquivo para o Git (o .gitignore já cuida disso automaticamente).
Todas as variáveis disponíveis
# ─── Inteligência Artificial (Gemini) ────────────────────────────────────────
# Obtenha em: https://aistudio.google.com/app/apikey
IPNET_GEMINI_API_KEY=AIzaSy...
# Modelo a usar (gemini-3.5-flash é o recomendado para texto + imagem + áudio)
IPNET_GEMINI_MODEL=gemini-3.5-flash
# Criatividade das respostas: 0.0 = mais preciso/previsível, 2.0 = mais criativo
# Para atendimento: 0.5 a 0.8 | Para conteúdo criativo: 1.0 a 1.5
IPNET_GEMINI_TEMPERATURE=0.7
# Tamanho máximo das respostas (em tokens, ~1 token = 0.75 palavra)
IPNET_GEMINI_MAX_TOKENS=2048
# ─── WhatsApp (Evolution API) ─────────────────────────────────────────────────
# URL onde a Evolution API está rodando
IPNET_EVOLUTION_API_URL=https://evolution.seudominio.com
# Chave de autenticação da Evolution API
IPNET_EVOLUTION_API_KEY=sua-api-key-aqui
# Nome único desta instância (use só letras, números e hífens)
IPNET_INSTANCE_NAME=meu-agente
# ─── Banco de dados (PostgreSQL) ─────────────────────────────────────────────
# Formato: postgresql+asyncpg://USUARIO:SENHA@HOST:PORTA/BANCO
# Local:
IPNET_POSTGRES_URL=postgresql+asyncpg://postgres:suasenha@localhost:5432/agentdb
# Cloud SQL no Cloud Run (via Auth Proxy sidecar):
# IPNET_POSTGRES_URL=postgresql+asyncpg://postgres:suasenha@127.0.0.1:5432/agentdb
# ─── Cache de sessão (Redis) ──────────────────────────────────────────────────
# Formato: redis://HOST:PORTA/BANCO_NUMERO
IPNET_REDIS_URL=redis://localhost:6379/0
# ─── Comportamento do Agente ─────────────────────────────────────────────────
# Tempo de espera após a última mensagem antes de processar (segundos)
# Aumente se seus usuários costumam enviar muitas mensagens rápidas
IPNET_DEBOUNCE_SECONDS=5
# Quantas mensagens anteriores o agente "lembra" por conversa
IPNET_MAX_HISTORY_MESSAGES=20
# Por quanto tempo manter a sessão ativa no Redis (segundos)
# 3600 = 1 hora | 86400 = 1 dia
IPNET_SESSION_TTL_SECONDS=3600
# Tempo máximo para buscar mídia na Evolution quando ela não vier no webhook (segundos)
IPNET_MEDIA_FETCH_TIMEOUT_SECONDS=10
# Tamanho máximo de mídia aceito para análise multimodal (bytes)
# 10485760 = 10 MB
IPNET_MAX_MEDIA_BYTES=10485760
# ─── Segurança ────────────────────────────────────────────────────────────────
# Secret opcional para validar que o webhook vem da Evolution API
# Se definido, a Evolution API deve enviar este valor no header x-webhook-secret
# IPNET_WEBHOOK_SECRET=um-secret-bem-longo-e-aleatorio
# ─── Servidor ─────────────────────────────────────────────────────────────────
IPNET_HOST=0.0.0.0
IPNET_PORT=8080
Observabilidade básica
Depois que o agente estiver rodando, existem dois endpoints úteis para operação:
GET /webhook/health: healthcheck simples do webhook.GET /metrics: snapshot JSON das métricas internas do runtime, incluindo contadores de lotes processados, falhas, retries de mídia, fallbacks multimodais e latência média de processamento.
As mensagens recebidas também passam a carregar correlation_id interno nos logs e no histórico, o que facilita rastrear um lote desde o webhook até a resposta enviada ao usuário.
Como obter a chave do Gemini
- Acesse aistudio.google.com
- Faça login com sua conta Google
- Clique em "Create API Key"
- Copie a chave e cole no
.env
O Google oferece um plano gratuito generoso para o Gemini. Para produção com volume alto, verifique os limites em ai.google.dev/pricing.
📦 Versionamento e Release
- A versão do pacote fica sincronizada entre
pyproject.tomlewhatsapp_agent_ipnet/version.py. - O histórico de mudanças fica em
CHANGELOG.md. - A release é disparada ao subir uma tag no formato
vX.Y.Z.
Fluxo recomendado:
git checkout main
git pull
# atualizar versão + CHANGELOG
git commit -am "Release 0.2.0"
git tag v0.2.0
git push origin main --tags
Ao receber a tag, o GitHub Actions:
- valida se a tag bate com a versão do pacote;
- gera os artefatos (
sdist+wheel); - cria a GitHub Release;
- publica no PyPI, se o ambiente
pypiestiver configurado.
☁️ Deploy no Google Cloud Run
Com toda a infraestrutura criada (passos 3 a 9 da seção anterior), o deploy é feito com um único comando.
Arquitetura final
Internet
│
▼
Cloud Run (seu agente Python)
│
├─→ Cloud SQL Auth Proxy ──→ Cloud SQL PostgreSQL (histórico)
│
├─→ VPC Connector ──────────→ Memorystore Redis (sessões)
│
└─→ Evolution API (externa) ─→ WhatsApp
Passo 1 — Build e deploy
whatsapp-agent deploy \
--project-id SEU_PROJECT_ID \
--region us-central1 \
--service meu-agente \
--sql-instance SEU_PROJECT_ID:us-central1:whatsapp-agent-db \
--vpc-connector whatsapp-agent-connector \
--public
O comando faz automaticamente:
- ✅ Build da imagem Docker via Cloud Build
- ✅ Push para o Container Registry
- ✅ Deploy no Cloud Run com Cloud SQL Auth Proxy
- ✅ Conecta o serviço ao VPC Connector para alcançar o Redis privado
- ✅ Configura o webhook da Evolution API automaticamente
- ✅ Retorna a URL pública do agente
Passo 2 — O que o comando valida antes de subir
- Variáveis obrigatórias do runtime no
.envou no ambiente (IPNET_GEMINI_API_KEY,IPNET_EVOLUTION_API_URL,IPNET_EVOLUTION_API_KEY,IPNET_POSTGRES_URL,IPNET_REDIS_URL) --sql-instancequando oIPNET_POSTGRES_URLaponta para127.0.0.1/localhost--vpc-connectorquando oIPNET_REDIS_URLusa IP privado oulocalhost--publicquando o webhook automático está habilitado
Se alguma dessas condições não for atendida, o deploy falha antes de publicar um serviço quebrado.
Passo 3 — Serviço privado vs. público
- Se você usar
--public, o comando já publica o serviço e configura o webhook na Evolution API. - Se você quiser um serviço privado no Cloud Run, rode com
--skip-webhooke sem--public. - O modo privado é útil para cenários internos, mas não serve para receber webhook direto da Evolution pela internet pública.
Passo 4 — Verificar se tudo está funcionando
# Ver logs do Cloud Run em tempo real
gcloud run services logs tail meu-agente --region=us-central1
# Verificar estado do Cloud SQL
gcloud sql instances describe whatsapp-agent-db \
--format='value(state)'
# Deve retornar: RUNNABLE
# Verificar estado do Redis
gcloud redis instances describe whatsapp-agent-redis \
--region=us-central1 \
--format='value(state)'
# Deve retornar: READY
Custos estimados (GCP)
| Serviço | Tier | Custo estimado |
|---|---|---|
| Cloud Run | Escala para zero | ~$0–5/mês (baixo volume) |
| Cloud SQL | db-f1-micro |
~$7/mês |
| Memorystore Redis | 1GB Basic | ~$35/mês |
| VPC Connector | e2-micro x2 |
~$15/mês |
| Cloud Build | 120 min/dia grátis | ~$0/mês |
O Memorystore tem custo fixo mesmo sem uso. Para projetos em fase inicial, você pode usar um Redis externo (ex: Upstash tem plano gratuito) e pular os passos 6 e 7.
💻 CLI — Todos os comandos
whatsapp-agent init
Cria a estrutura de um novo projeto.
whatsapp-agent init NOME_DO_PROJETO [--dir DIRETÓRIO]
| Argumento | Obrigatório | Descrição |
|---|---|---|
NOME_DO_PROJETO |
Sim | Nome do projeto (ex: agente-vendas) |
--dir |
Não | Diretório onde criar (padrão: pasta atual) |
# Exemplos:
whatsapp-agent init agente-suporte
whatsapp-agent init agente-vendas --dir /projetos
whatsapp-agent deploy
Realiza o build e deploy no Google Cloud Run.
whatsapp-agent deploy \
--project-id PROJETO \
--region REGIAO \
[--service NOME_SERVICO] \
[--instance NOME_INSTANCIA] \
[--sql-instance CONNECTION_NAME] \
[--vpc-connector NOME_CONNECTOR] \
[--vpc-egress private-ranges-only] \
[--service-account EMAIL_DA_SA] \
[--env-file .env] \
[--tag TAG_IMAGEM] \
[--skip-build] \
[--skip-push] \
[--public] \
[--configure-webhook/--skip-webhook]
| Flag | Obrigatório | Padrão | Descrição |
|---|---|---|---|
--project-id |
✅ Sim | — | ID do projeto Google Cloud |
--region |
Não | us-central1 |
Região do Cloud Run |
--service |
Não | valor de IPNET_INSTANCE_NAME |
Nome do serviço Cloud Run |
--instance |
Não | valor de --service |
Nome da instância WhatsApp / webhook |
--sql-instance |
Não | — | Connection name do Cloud SQL |
--vpc-connector |
Não | — | VPC Connector usado para Redis privado |
--vpc-egress |
Não | private-ranges-only |
Política de egress do VPC Connector |
--service-account |
Não | IPNET_SERVICE_ACCOUNT |
Service Account do Cloud Run |
--env-file |
Não | .env |
Arquivo com as variáveis IPNET_* do deploy |
--tag |
Não | latest |
Tag da imagem Docker |
--skip-build |
Não | false | Pula a etapa de build |
--skip-push |
Não | false | Mantido por compatibilidade; o fluxo com Cloud Build ignora esse flag |
--public |
Não | false | Expõe o serviço publicamente no Cloud Run |
--configure-webhook |
Não | true | Configura o webhook da Evolution automaticamente |
whatsapp-agent qrcode
Exibe o QR Code da instância no terminal para escanear com o WhatsApp.
whatsapp-agent qrcode \
[--url URL_EVOLUTION] \
[--key API_KEY] \
[--instance NOME_INSTANCIA]
Se as variáveis de ambiente IPNET_EVOLUTION_API_URL, IPNET_EVOLUTION_API_KEY e IPNET_INSTANCE_NAME estiverem configuradas no .env, basta rodar:
whatsapp-agent qrcode
whatsapp-agent status
Verifica o estado atual da conexão WhatsApp.
whatsapp-agent status
Saída esperada quando conectado:
╭─────────────────────────╮
│ WhatsApp Status │
│ Instância meu-agente │
│ Estado OPEN │
│ URL http://... │
╰─────────────────────────╯
Estados possíveis:
- OPEN — Conectado e funcionando ✅
- CLOSE — Desconectado ❌ (precisa escanear o QR novamente)
- CONNECTING — Tentando reconectar ⏳
📚 Exemplos práticos
Agente de Suporte ao Cliente
from whatsapp_agent_ipnet import WhatsAppAgent
agent = WhatsAppAgent.from_env(
name="Suporte TechCorp",
system_prompt="""
Você é o assistente de suporte da TechCorp, chamado Max.
Seu trabalho é:
- Ajudar clientes com problemas técnicos
- Registrar chamados de suporte
- Consultar o status de chamados existentes
- Escalar para humanos quando necessário
Regras:
- Seja empático — o cliente pode estar frustrado
- Peça o número do pedido antes de consultar qualquer coisa
- Se não conseguir resolver em 3 tentativas, ofereça falar com um humano
- Nunca prometa prazos sem consultar o sistema
""",
)
@agent.tool
def abrir_chamado(nome: str, email: str, descricao_problema: str) -> str:
"""Abre um novo chamado de suporte técnico com os dados do cliente"""
# Aqui você integraria com seu sistema de tickets (Zendesk, Jira, etc.)
numero = "TKT-" + str(hash(email + descricao_problema))[-6:]
return f"Chamado {numero} aberto com sucesso! Você receberá atualizações no email {email}."
@agent.tool
def consultar_chamado(numero_chamado: str) -> str:
"""Consulta o status atual de um chamado de suporte pelo número"""
# Consulta no seu banco de dados
return f"Chamado {numero_chamado}: Em análise pela equipe técnica. Previsão: 2 horas úteis."
@agent.tool
def escalar_para_humano(motivo: str) -> str:
"""Escala a conversa para um atendente humano quando o problema é complexo"""
# Dispara notificação para a equipe
return "Transferindo para um especialista. Você será atendido em até 5 minutos."
agent.start()
Agente de Agendamentos
from whatsapp_agent_ipnet import WhatsAppAgent
from datetime import datetime
agent = WhatsAppAgent.from_env(
name="Agenda Fácil",
system_prompt="""
Você é o assistente de agendamentos da Barbearia do Zé.
Você pode:
- Mostrar horários disponíveis
- Agendar cortes
- Confirmar e cancelar agendamentos
Serviços disponíveis:
- Corte simples: R$ 35 (30 min)
- Corte + barba: R$ 55 (1 hora)
- Barba: R$ 25 (30 min)
Funcionamento: Segunda a sábado, 9h às 19h.
Sempre confirme o nome do cliente e o serviço antes de agendar.
""",
)
@agent.tool
def verificar_horarios_disponiveis(data: str) -> str:
"""
Verifica horários livres para agendamento em uma data específica.
A data deve estar no formato DD/MM/AAAA.
"""
# Consulta no seu sistema de agenda
horarios = ["09:00", "10:30", "14:00", "15:30", "17:00"]
return f"Horários disponíveis em {data}: {', '.join(horarios)}"
@agent.tool
def criar_agendamento(
nome_cliente: str,
telefone: str,
servico: str,
data: str,
horario: str,
) -> str:
"""
Cria um novo agendamento para o cliente.
Requer: nome, telefone, serviço desejado, data (DD/MM/AAAA) e horário (HH:MM).
"""
# Salva no banco de dados
codigo = f"AG{hash(nome_cliente + data + horario) % 10000:04d}"
return (
f"✅ Agendamento confirmado!\n"
f"Código: {codigo}\n"
f"Cliente: {nome_cliente}\n"
f"Serviço: {servico}\n"
f"Data: {data} às {horario}\n"
f"Endereço: Rua das Flores, 123 — Centro"
)
agent.start()
Agente com notificação de QR Code por e-mail
import smtplib
from email.mime.text import MIMEText
from whatsapp_agent_ipnet import WhatsAppAgent
agent = WhatsAppAgent.from_env(
name="Meu Agente",
system_prompt="Você é um assistente virtual...",
)
@agent.on_qrcode
async def notificar_qrcode(instance_name: str, base64_qr: str):
"""Envia e-mail para o admin quando o QR Code precisar ser escaneado novamente"""
msg = MIMEText(
f"O agente '{instance_name}' precisa ser reconectado.\n"
f"Escaneie o QR Code no painel da Evolution API."
)
msg["Subject"] = f"⚠️ Agente {instance_name} desconectado"
msg["From"] = "sistema@suaempresa.com"
msg["To"] = "admin@suaempresa.com"
with smtplib.SMTP("smtp.gmail.com", 587) as s:
s.starttls()
s.login("sistema@suaempresa.com", "sua-senha-app")
s.send_message(msg)
@agent.on_connection_change
async def monitorar_conexao(instance_name: str, state: str):
"""Loga mudanças de estado para monitoramento"""
print(f"[{instance_name}] Estado: {state.upper()}")
agent.start()
❓ Perguntas frequentes
O agente pode responder mais de um usuário ao mesmo tempo?
Sim. Cada número de telefone tem seu próprio contexto, sessão e histórico. O sistema processa múltiplas conversas em paralelo sem conflito.
O agente lembra de conversas anteriores?
Sim. Cada conversa é salva no PostgreSQL com o número do usuário como identificador. Nas próximas mensagens, o agente carrega o histórico recente (configurável via IPNET_MAX_HISTORY_MESSAGES). Após o IPNET_SESSION_TTL_SECONDS sem mensagens, a sessão Redis expira, mas o histórico do banco permanece.
Posso usar grupos do WhatsApp?
O framework atualmente processa mensagens de conversas individuais. Mensagens de grupos são ignoradas por padrão (o remoteJid de grupos termina em @g.us).
Qual é o custo?
- Gemini 2.5 Flash: ~$0.075 por 1 milhão de tokens de entrada / ~$0.30 por 1 milhão de saída. Um atendimento médio de 10 mensagens custa frações de centavo.
- Cloud Run: Cobra por requisição. Com escala para zero quando inativo, o custo pode ser de poucos dólares por mês para volumes médios.
- Cloud SQL: A partir de ~$7/mês para a menor instância.
Posso usar outro modelo de IA além do Gemini?
A versão atual usa o Gemini via Agno. O Agno suporta outros modelos (OpenAI, Anthropic, etc.). Contribuições são bem-vindas!
O número fica banido no WhatsApp?
O risco existe em qualquer integração não-oficial. Recomendações para minimizar o risco:
- Use um número específico para o agente (não o seu pessoal)
- Não envie mensagens em massa ou spam
- Mantenha um comportamento humano (não responda instantaneamente a todos — o debouncer ajuda nisso)
- Evite enviar muitas mensagens seguidas para o mesmo número em pouco tempo
🔧 Solução de problemas
ModuleNotFoundError: No module named 'whatsapp_agent_ipnet'
O ambiente virtual não está ativado ou o pacote não foi instalado. No terminal do VS Code:
source .venv/bin/activate # macOS/Linux
# ou
.venv\Scripts\Activate.ps1 # Windows PowerShell
pip install whatsapp-agent-ipnet
O terminal do VS Code não mostra (.venv) ao abrir
O interpretador Python não foi selecionado corretamente:
Ctrl+Shift+P→ "Python: Select Interpreter"- Escolha a opção com
.venvna lista - Feche o terminal (
Ctrl+````) e abra um novo
Se .venv não aparecer na lista:
python3 -m venv .venv
E repita os passos acima.
pip install instala mas whatsapp-agent não é encontrado
O executável foi instalado no ambiente errado. Certifique-se de que o (.venv) está visível antes de instalar:
# Verificar qual pip está sendo usado:
which pip # macOS/Linux — deve mostrar um caminho com .venv
where pip # Windows — deve mostrar um caminho com .venv
# Se não estiver no .venv, ative e reinstale:
source .venv/bin/activate
pip install --force-reinstall whatsapp-agent-ipnet
Aviso dependency resolver ao instalar
ERROR: pip's dependency resolver does not currently take into account...
Isso é apenas um aviso, não um erro. O pacote foi instalado corretamente. Acontece quando há outros pacotes instalados globalmente que têm versões conflitantes. O ambiente virtual isola o seu projeto e o agente funcionará normalmente.
Erro de conexão com o Redis (Memorystore)
O Cloud Run não consegue atingir o Redis. Verifique:
- O VPC Connector está com
state: READY?
gcloud compute networks vpc-access connectors describe whatsapp-agent-connector \
--region=us-central1 --format='value(state)'
# Deve retornar: READY
- O
--vpc-connectorfoi aplicado ao serviço?
gcloud run services describe meu-agente \
--region=us-central1 \
--format='value(spec.template.metadata.annotations)'
# Deve conter: run.googleapis.com/vpc-access-connector
- O IP do Redis na variável
IPNET_REDIS_URLestá correto?
gcloud redis instances describe whatsapp-agent-redis \
--region=us-central1 --format='value(host)'
Erro de conexão com o PostgreSQL (Cloud SQL)
- O connection name está correto?
gcloud sql instances describe whatsapp-agent-db \
--format='value(connectionName)'
# Formato: SEU_PROJECT_ID:us-central1:whatsapp-agent-db
- A service account tem permissão
roles/cloudsql.client?
gcloud projects get-iam-policy SEU_PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:whatsapp-agent-sa" \
--format='table(bindings.role)'
- O
--add-cloudsql-instancesfoi passado no deploy?
gcloud run services describe meu-agente \
--region=us-central1 \
--format='value(spec.template.metadata.annotations)'
# Deve conter: run.googleapis.com/cloudsql-instances
QR Code não aparece ou dá erro 404
A instância ainda não existe na Evolution API. Verifique se:
- A Evolution API está acessível na URL configurada em
IPNET_EVOLUTION_API_URL - A
IPNET_EVOLUTION_API_KEYestá correta - O servidor do agente está rodando (
python main.py)
Tente criar a instância manualmente:
curl -X POST "http://localhost:8081/instance/create" \
-H "apikey: minha-chave-secreta" \
-H "Content-Type: application/json" \
-d '{"instanceName": "meu-agente", "qrcode": true}'
Agente não responde às mensagens
Verifique nessa ordem:
- Deploy público com webhook automático foi usado? Se não, confirme se o serviço foi publicado com
--publicou se o webhook foi configurado manualmente. - URL acessível? O servidor precisa ser acessível pela Evolution API (use ngrok localmente).
- Logs do servidor:
python main.pymostra os eventos recebidos. - Estado do WhatsApp:
whatsapp-agent status— deve mostrarOPEN.
Error: gcloud CLI não encontrado ao fazer deploy
Instale o gcloud CLI:
Após instalar:
gcloud auth login
gcloud config set project SEU_PROJECT_ID
Respostas lentas ou timeout
O Gemini 2.5 Flash geralmente responde em 2-5 segundos. Se estiver mais lento:
- Reduza
IPNET_MAX_HISTORY_MESSAGES(menos contexto = resposta mais rápida) - Reduza
IPNET_GEMINI_MAX_TOKENSse as respostas estiverem muito longas - Verifique sua conexão com a internet e a latência para a API do Gemini
🤝 Contribuindo
Contribuições são bem-vindas! Para reportar bugs, sugerir funcionalidades ou enviar código:
- Abra uma issue descrevendo o problema ou sugestão
- Fork o repositório
- Crie uma branch:
git checkout -b feature/minha-feature - Faça suas alterações com testes
- Abra um Pull Request
📄 Licença
MIT License — veja o arquivo LICENSE para detalhes.
Desenvolvido por IPNET Tecnologia
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file whatsapp_agent_ipnet-0.2.0.tar.gz.
File metadata
- Download URL: whatsapp_agent_ipnet-0.2.0.tar.gz
- Upload date:
- Size: 98.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd7d74bfc3c50a03bc785270bb6665a891291f9db1bc24fe2390653b618524eb
|
|
| MD5 |
e17419b904a9f84835eabb1d4c0141c3
|
|
| BLAKE2b-256 |
4f98f9a99c9aa33e70ffcfc8788fed3e6f3ee79cf3b5221820c1dcdb06b878f9
|
File details
Details for the file whatsapp_agent_ipnet-0.2.0-py3-none-any.whl.
File metadata
- Download URL: whatsapp_agent_ipnet-0.2.0-py3-none-any.whl
- Upload date:
- Size: 60.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
819747a2ad5307d2c2994662fca82327f0bd104b466536fde236d09b6efc0b33
|
|
| MD5 |
bc2b36291d567d48af8341cc27aee684
|
|
| BLAKE2b-256 |
bb3fec6af1137e5797237fd04661a4c703b982358bef79f3fc85e35afa2b1345
|