Variáveis de ambiente¶
Inventário do código em 14/09/2026: src/core/config/settings.py, src/core/integrations/factory.py, src/crm_sync/app.py, src/webhook_handler/app.py, src/emulator/app.py, .env.example, template.yaml e scripts. Não contém valores de .env nem configuração remota.
Leitura e precedência¶
load_settings() devolve uma dataclass Settings imutável e é cacheado por processo. Alterar env não atualiza uma instância já carregada. Os loaders de .env de dashboard/smoke usam os.environ.setdefault: o valor já presente no processo prevalece. Settings não lê o arquivo .env diretamente.
Tipos: booleano aceita 1,true,yes,y,on sem distinção de caixa; vazio usa o default, demais strings viram falso. Inteiro usa int() e pode falhar com ValueError; não existe validação geral de faixa. CSV remove espaços dos itens e devolve conjunto sem duplicatas. “Cond.” significa obrigatória para a funcionalidade indicada, mesmo que o loader geral aceite ausência. “Pessoal” identifica dado de contato que exige proteção, distinto de credencial.
Ambientes: local = execução por scripts/desenvolvimento; AWS = Lambda/dev/staging/prod; ambos = consumida nos dois. A coluna Default é o código, salvo ressalva explícita. Um valor exemplificado em .env.example não equivale a default em produção.
OpenAI¶
Consumidores: Settings, OpenAIClient, AgentInvokerImpl, reparo e resumo operacional. O worker CRM e o conjunto reduzido de dependências do painel humano têm carregamento próprio, sem exigir chave OpenAI.
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
OPENAI_API_KEY |
string | Cond. | Ausente | Ambos | Sim | _load_openai_api_key() |
Chave direta; vence SSM |
OPENAI_API_KEY_SSM_PARAM |
string | Cond. | Ausente | AWS | Nome, não valor | _load_openai_api_key() |
SSM SecureString quando chave direta ausente; SAM: /gogenetic-agent/${Environment}/openai-api-key |
OPENAI_MODEL_TRIAGE |
string | Não | gpt-4o-mini |
Ambos | Não | Invocador | Modelo Triagem |
OPENAI_MODEL_QUALIFICATION |
string | Não | gpt-4o-mini |
Ambos | Não | Invocador | Modelo Qualificação |
OPENAI_MODEL_COLLECTION |
string | Não | gpt-4o-mini |
Ambos | Não | Invocador | Modelo Coleta |
OPENAI_MODEL_SUMMARY |
string | Não | gpt-4o-mini |
Ambos | Não | Resumo operacional | Modelo do resumo |
OPENAI_REASONING_EFFORT |
string opcional | Não | None |
Ambos | Não | OpenAIClient |
reasoning.effort; compatibilidade não validada localmente |
LLM_TIMEOUT_SECONDS |
int | Não | 30 |
Ambos | Não | OpenAIClient |
Timeout por operação SDK |
LLM_RETRY_MAX |
int | Não | 1 |
Ambos | Não | OpenAIClient |
Retries do wrapper, além da tentativa inicial; SDK tem política própria |
Orquestração¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
DEBOUNCE_WINDOW_SECONDS |
int | Não | 0 |
Ambos | Não | Settings/fluxo legado debounce | Nome preservado; fluxo atual usa receipts imediatos FIFO/latest-message-wins |
MAX_HISTORY_MESSAGES |
int | Não | 50 |
Ambos | Não | Orquestração/replay | Limite de histórico consultado; não altera limites fixos de todos os módulos |
MAX_CONTEXT_ENRICHMENTS_PER_MESSAGE |
int | Não | 2 |
Ambos | Não | Loop dos agentes | Máximo de enriquecimentos s=99 no turno |
DEBOUNCE_QUEUE_URL |
string | Cond. | Ausente | AWS/webhook | Não | _send_sqs_dispatch() |
URL SQS FIFO; SAM injeta referência à fila; fora de Settings |
Identidade e horário¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
AGENT_NAME |
string | Não | DoNA |
Ambos | Não | Prompts/guardas | Identidade do agente |
BUSINESS_HOURS_TZ |
string IANA | Não | America/Sao_Paulo |
Ambos | Não | Horário, disponibilidade e autenticação | Fuso; pode receber override operacional |
BUSINESS_HOURS_DAYS |
CSV inteiros | Não | 1,2,3,4,5 |
Ambos | Não | BusinessHours |
1=segunda a 7=domingo; vazio em Settings significa nenhum dia |
BUSINESS_HOURS_START |
HH:MM |
Não | 08:00 |
Ambos | Não | BusinessHours |
Início operacional |
BUSINESS_HOURS_END |
HH:MM |
Não | 18:00 |
Ambos | Não | BusinessHours |
Fim operacional |
O carregamento reduzido _operator_deps() em src/emulator/app.py usa fallback de dias quando a string está vazia, diferente de load_settings(). Horário comercial não bloqueia notificação a operador que marcou disponibilidade; o fuso e a data local continuam relevantes.
Operadores e acesso humano¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
WHITELIST_PHONE_NUMBERS |
CSV | Cond. | Conjunto vazio | Ambos | Pessoal | Whitelist/comandos/auth | Telefones autorizados; configuração operacional pode substituir o valor de env |
HANDOFF_OPERATOR_AGRO |
string opcional | Não | None |
Ambos | Pessoal | Compatibilidade de settings | Legado; não concede acesso nem dirige o notificador atual |
HANDOFF_OPERATOR_HUMANO |
string opcional | Não | None |
Ambos | Pessoal | Compatibilidade de settings | Legado |
HANDOFF_OPERATOR_GERAL |
string opcional | Não | None |
Ambos | Pessoal | Compatibilidade de settings | Legado |
HANDOFF_OPERATOR_AVAILABILITY_TTL_HOURS |
int | Não | 24 |
Ambos | Não | Disponibilidade de operadores | Limite adicional de idade; expira também na mudança do dia local |
OPERATOR_UI_BASE_URL |
URL opcional | Cond. no deploy WhatsApp | None |
Ambos | Não | Links login/handoff | URL terminando em /atendimento; webhook deriva host/protocolo quando ausente |
OPERATOR_CUSTOM_DOMAIN_NAME |
hostname | Cond. | Vazio no exemplo | Deploy | Não | Script → OperatorCustomDomainName |
Domínio customizado API Gateway; não é campo de Settings |
OPERATOR_CUSTOM_DOMAIN_CERTIFICATE_ARN |
ARN | Cond. | Vazio no exemplo | Deploy | Não | Script → OperatorCustomDomainCertificateArn |
Certificado ACM do domínio; mesma região da API |
Não existe env para duração do link de login: LOGIN_LINK_TTL é constante de 10 minutos em operator_auth.py, limitada ao fim do dia; sessão humana expira no fim do dia local. Também não existe env para o limiar de renotificação/abandono de 24 h: são parâmetros Python do caso de uso.
WhatsApp¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
WHATSAPP_CLOUD_ENABLED |
bool | Não | false |
Ambos | Não | Settings/factory/webhook | Seleciona API real e validação de assinatura |
WHATSAPP_ACCESS_TOKEN |
string | Cond. Cloud | Ausente | Ambos | Sim | WhatsAppCloudClient |
Bearer da Graph API |
WHATSAPP_APP_SECRET |
string | Cond. Cloud | Ausente | Ambos | Sim | Webhook | HMAC SHA-256 do POST |
WHATSAPP_VERIFY_TOKEN |
string | Cond. Cloud | Ausente | Ambos | Sim | GET webhook | Token de verificação de assinatura da URL, distinto do app secret |
WHATSAPP_PHONE_NUMBER_ID |
string | Cond. Cloud | Ausente | Ambos | Não | Client de envio | ID do número do canal, não telefone destinatário |
WHATSAPP_BUSINESS_ACCOUNT_ID |
string opcional | Não | None |
Ambos | Não | Settings/SAM | ID WABA carregado; não usado na URL de envio |
WHATSAPP_GRAPH_API_VERSION |
string | Não | v23.0 |
Ambos | Não | Client | Versão do path Graph |
WHATSAPP_SEND_TIMEOUT_SECONDS |
int | Não | 10 |
Ambos | Não | Client | Timeout por chamada de envio |
WHATSAPP_FREE_ONLY |
bool | Não | true |
Ambos | Não | Settings/factory | Falso é rejeitado; não é uma medição de cobrança/janela |
WhatsAppCloudConfig.retry_max=2 não possui env de configuração. Tokens Meta são parâmetros SAM NoEcho, injetados nas funções que usam o canal; o loader WhatsApp não oferece caminho SSM próprio.
Dashboard e ferramentas locais¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
DEV_UI_ENABLED |
bool | Não | false em Settings |
Ambos | Não | Emulador | Libera dashboard/admin de desenvolvimento; não desliga /atendimento autenticado |
DASHBOARD_PORT |
int | Não | 8080 |
Local | Não | scripts/dashboard.py |
Porta uvicorn; script escuta 0.0.0.0 |
CHAT_REPL_PHONE |
string | Não | Telefone fictício fixo do script, omitido aqui | Local | Pessoal quando substituído | scripts/chat.py |
Identidade da sessão REPL; fora de Settings |
ADMIN_BASE_URL |
URL | Não | http://localhost:8080 |
CLI | Não | scripts/arauc_admin.py |
Default de --base-url |
scripts/dashboard.py inicia moto e remove AWS_ENDPOINT_URL e AWS_ENDPOINT_URL_DYNAMODB antes do mock; portanto não utiliza DynamoDB Local via esses endpoints. .env.example habilita DEV_UI_ENABLED=true; script de deploy força DevUiEnabled=false.
eGestor¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
EGESTOR_ENABLED |
bool | Não | false |
Ambos | Não | Factory | Real quando habilitado; caso contrário stub |
EGESTOR_BASE_URL |
URL | Cond. real | None |
Ambos | Não | Factory/client | Base HTTP; vence SSM |
EGESTOR_API_TOKEN |
string | Cond. real | None |
Ambos | Sim | Factory/client | Bearer ou personal token pela heurística do client |
EGESTOR_BASE_URL_SSM_PARAM |
string | Cond. | None |
AWS | Nome, não valor | Factory | Alternativa à URL direta; SAM /gogenetic-agent/${Environment}/egestor-base-url |
EGESTOR_API_TOKEN_SSM_PARAM |
string | Cond. | None |
AWS | Nome, não valor | Factory | Alternativa ao token; SAM /gogenetic-agent/${Environment}/egestor-api-token |
EGESTOR_TIMEOUT_SECONDS |
int | Não | 10 |
Ambos | Não | Client | Timeout por request, inclusive OAuth |
EGESTOR_RETRY_MAX |
int | Não | 2 |
Ambos | Não | Client | Retries de contatos para rede/429/5xx; não controla OAuth |
URL e token SSM não estão explicitados no .env.example, mas existem no código/SAM. deploy_from_env.ps1 exige os dois valores diretos juntos ou ambos ausentes para usar SSM; quando presentes, grava ambos no SSM. São configurações de deploy, não autorização para executá-lo nesta tarefa.
CRM compatível com HubSpot¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
HUBSPOT_ENABLED |
bool | Não | false |
Ambos | Não | Factory/repository/worker | Ativa adapter e projeção; falso preserva pendências existentes |
HUBSPOT_BASE_URL |
URL | Cond. deploy | https://api.hubapi.com |
Ambos | Não | Client/worker | Define provider efetivo; exemplo aponta CRM próprio |
HUBSPOT_ACCESS_TOKEN |
string | Cond. real | None |
Ambos | Sim | Factory/worker | Bearer direto prioritário |
HUBSPOT_ACCESS_TOKEN_SSM_PARAM |
string | Cond. | None |
AWS | Nome, não valor | Factory/worker | Alternativa SSM; SAM /gogenetic-agent/${Environment}/crm-comercial-access-token |
HUBSPOT_TIMEOUT_SECONDS |
int | Não | 10 |
Ambos | Não | Client/worker | Worker limita a 1–10 segundos |
HUBSPOT_RETRY_MAX |
int | Não | 2 |
Ambos | Não | Client comum | Worker fixa zero; POST de deal desativa retry local |
HUBSPOT_PIPELINE_ID |
string | Cond. real | None |
Ambos | Não | Factory/client/worker | Pipeline para criação de deal |
HUBSPOT_DEALSTAGE_ID |
string | Cond. factory real | None |
Ambos | Não | Factory/client | Stage default legado; não substitui stages explícitos do worker |
HUBSPOT_STAGE_NOVO_LEAD |
string | Cond. worker | None |
Ambos | Não | Settings/worker | Nome lógico novo_lead |
HUBSPOT_STAGE_EM_TRIAGEM |
string | Cond. worker | None |
Ambos | Não | Settings/worker | Nome lógico em_triagem |
HUBSPOT_STAGE_ATENDIMENTO_HUMANO |
string | Cond. worker | None |
Ambos | Não | Settings/worker | HANDOFF_PENDING/HUMAN |
HUBSPOT_STAGE_FINALIZADO |
string | Cond. worker | None |
Ambos | Não | Settings/worker | Terminal normal; diferente de stages ativos |
HUBSPOT_STAGE_PERDIDO |
string | Cond. worker | None |
Ambos | Não | Settings/worker | Abandono; diferente de stages ativos |
HUBSPOT_OWNER_ID |
string | Não | None |
Ambos | Não | Client/worker | Owner estático fallback |
HUBSPOT_OWNER_ROUTING_CONFIG |
string | Não | None |
Ambos | Não | Client comum | Apenas registra presença; distribuição dinâmica não implementada |
Propriedades de Settings: stage_novo_lead usa DEALSTAGE_ID; stage_em_triagem usa stage_novo_lead; stage_atendimento_humano usa DEALSTAGE_ID; stage_finalizado usa stage_atendimento_humano; stage_perdido usa stage_novo_lead. O worker não usa essas propriedades. Lê as cinco envs diretamente e bloqueia ausência/terminal em stage ativo. O comentário de fallback em .env.example não descreve o worker atual.
Handoff¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
HANDOFF_NOTIFIER_ENABLED |
bool | Não | false |
Ambos | Não | Factory | Habilita canal escolhido |
HANDOFF_NOTIFIER_TYPE |
string | Cond. | stub |
Ambos | Não | Factory | stub, whatsapp ou email |
HANDOFF_EMAIL_TO |
CSV | Cond. email | Conjunto vazio | Ambos | Pessoal | SES notifier | Destinatários operacionais |
HANDOFF_EMAIL_FROM |
string | Cond. email | None |
Ambos | Pessoal | SES notifier | Remetente com identidade/permissão SES apropriada |
HANDOFF_EMAIL_SUBJECT_PREFIX |
string | Não | [GoGenetic] |
Ambos | Não | SES notifier | Prefixo do assunto |
HANDOFF_SES_REGION |
string | Não | None |
Ambos | Não | boto3 SES | Ausente usa resolução de região SDK |
HANDOFF_SES_CONFIGURATION_SET |
string | Não | None |
Ambos | Não | SES notifier | ConfigurationSetName opcional |
HANDOFF_TIMEOUT_SECONDS |
int | Não | 10 |
Ambos | Não | SES notifier | Connect/read timeout SES; não substitui timeout WhatsApp |
HANDOFF_RETRY_MAX |
int | Não | 2 |
Ambos | Não | SES notifier | Loop externo de retries SES |
Admin¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
ADMIN_API_KEY |
string | Cond. admin | None |
Ambos | Sim | Rotas admin e CLI | Header X-Admin-API-Key; ausente produz 503 nas rotas protegidas |
ADMIN_EXPORT_EMAIL_TO |
CSV | Não | Conjunto vazio | Ambos | Pessoal | Exportação operacional | Destinatários de relatório/exportação; não são whitelist de operadores |
Smokes manuais¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
SMOKE_ALLOW_REAL_SEND |
bool | Cond. envio | false |
CLI/dashboard | Não | WhatsApp smoke | Autoriza envio real; CLI --allow-real-send |
SMOKE_ALLOW_REAL_WRITE |
bool | Cond. escrita | false |
CLI/dashboard | Não | CRM/eGestor smoke | Autoriza upserts de teste; CLI --allow-real-write |
SMOKE_ALLOW_REAL_EMAIL |
bool | Cond. email | false |
CLI/dashboard | Não | SES smoke | Autoriza email real; CLI --allow-real-email |
SMOKE_WHATSAPP_TO |
string | Cond. smoke WA | None |
CLI/dashboard | Pessoal | WhatsApp smoke | Destino explícito; não reutilizar telefone real em documentação |
Flags não são injetados pelo SAM. O script carrega .env, portanto um flag já verdadeiro nele/processo continua autorizando a operação mesmo quando omitido na CLI. Preflight e smoke com escrita têm resultados diferentes; veja testes de smoke.
AWS, DynamoDB e observabilidade¶
| Variável | Tipo | Obrigatória | Default | Ambiente | Segredo | Consumidor | Descrição |
|---|---|---|---|---|---|---|---|
DYNAMODB_TABLE |
string | Sim no runtime | Nenhum em loader | Ambos | Não | Settings/repos/worker/painel | SAM injeta tabela; dashboard oferece gogenetic-agent-local |
AWS_DEFAULT_REGION |
string | Cond. SDK/CLI | Resolução SDK; scripts usam us-east-1 |
Ambos | Não | boto3/CLI | Região; não é campo Settings |
AWS_REGION |
string | Fornecida pela Lambda | Ambiente AWS | AWS | Não | Runtime/SDK | Região de execução, não substituir pela região de outro stack |
AWS_ENDPOINT_URL |
URL | Não | Ausente no SDK | Local | Não | boto3 | Override geral; exemplo http://localhost:8000; dashboard remove |
AWS_ENDPOINT_URL_DYNAMODB |
URL | Não | Ausente | Local | Não | boto3/dashboard | Override específico; dashboard remove antes de moto |
AWS_LAMBDA_FUNCTION_NAME |
string | Fornecida pela Lambda | Ausente/local em métrica CRM | AWS | Não | Factories/métricas | Ativa emissor eGestor quando contém -orchestrator-; dimensão CRM |
AWS_PROFILE |
string | Cond. CLI | Cadeia SDK | Local/deploy | Não | AWS/SAM CLI | Profile de credenciais, sem valor próprio do projeto |
AWS_ACCESS_KEY_ID |
string | Cond. SDK | Cadeia de credenciais | Local/deploy | Sim | boto3/CLI | Preferir perfil/role; nunca versionar |
AWS_SECRET_ACCESS_KEY |
string | Cond. SDK | Cadeia de credenciais | Local/deploy | Sim | boto3/CLI | Credencial AWS |
AWS_SESSION_TOKEN |
string | Cond. credencial temporária | Cadeia de credenciais | Ambos | Sim | boto3/CLI | Token temporário |
LOG_LEVEL |
string | Não | INFO |
Ambos | Não | shared.logging |
Nível raiz; REPL usa WARNING somente se ausente |
ALERTS_SNS_TOPIC_ARN |
ARN opcional | Não | None |
AWS | Não | Settings/SAM/relatórios | Notificações operacionais; alarmes sem tópico não notificam SNS |
Variáveis AWS de credencial/perfil pertencem ao SDK e não a Settings. O projeto não inventa defaults de credenciais; em Lambda usa role. Não confunda parâmetro SAM Environment (dev, staging, prod) com env Python: ele determina nomes, paths SSM e stack. Região/stack do script são argumentos PowerShell, não variáveis de runtime documentadas como Settings.
Divergências que exigem atenção¶
| Fontes | Diferença e consequência |
|---|---|
| Código × exemplo × SAM | Modelos: gpt-4o-mini × gpt-4o/mini × gpt-5.6-luna; configure os quatro explicitamente |
| Reasoning × script | Exemplo medium; código/SAM ausente; script não mapeia OPENAI_REASONING_EFFORT para o parâmetro SAM |
| CRM URL | Exemplo CRM próprio; código/SAM default HubSpot; nome HUBSPOT_* é legado |
| Stages | Fallback de Settings/exemplo não vale para crm_sync; worker exige valores explícitos |
| Timeout/retry CRM | Worker limita timeout e ignora retry env; client comum usa os valores |
| Env de orquestração × deploy | LLM_*, DEBOUNCE_WINDOW_SECONDS, MAX_*, BUSINESS_HOURS_*, AGENT_NAME e LOG_LEVEL são fixados em Globals no SAM, não repassados pelo script a partir do .env |
| Dev UI | Exemplo/script local habilitam; SAM default falso e deploy força falso |
| SSM | OpenAI/eGestor possuem envs SSM ausentes no exemplo; SAM injeta paths por ambiente |
| Dynamo local | Exemplo aponta porta 8000, mas dashboard remove endpoints e usa moto |
| Operadores | HANDOFF_OPERATOR_* mantidos por legado; whitelist/disponibilidade governam roteamento |
| Defaults numéricos | Settings aceita negativos por int(); não inferir validação de faixa fora das verificações explícitas do consumidor |
tests/unit/test_settings.py, tests/unit/integrations/test_factory.py, tests/unit/scripts/test_deploy_from_env.py e tests/unit/lambdas/test_crm_sync.py são as principais provas automatizadas dessas fronteiras. Para alterar configuração, mantenha código, SAM e deploy coerentes e acrescente regressão na camada que realmente carrega o valor.