Pular para o conteúdo principal
Este guia cobre a implantação do servidor e dashboard do AgentEye em produção.

Visão Geral da Arquitetura

  • Server: Serviço HTTP em Rust; recebe lotes de eventos, grava-os no ClickHouse e mantém o estado relacional no PostgreSQL.
  • Dashboard: Aplicação web em Next.js; lê e escreve exclusivamente por meio da API do servidor.
  • agenteye-collector: implantado nas máquinas do agente, não no host do servidor.
  • Postgres 15+: OBRIGATÓRIO. (Elevado da versão 14 na release multi-tenant; o esquema org-membership usa uma foreign key ON DELETE SET NULL com lista de colunas, que é Postgres 15+. Atualize o Postgres antes de implantar esta versão.) Armazena o estado OLTP: api_keys, users, sessions, evaluation_jobs (fila), dashboards, saved_queries, otp_codes, além das tabelas multi-tenant orgs, org_memberships, org_settings.
  • ClickHouse 24+: OBRIGATÓRIO. O armazenamento analítico para cada evento ingerido. Engine: ReplacingMergeTree, particionado por mês, ordenado por (session_id, ts, dedup_key). O servidor se conecta via CLICKHOUSE_URL; o deploy/base/clickhouse/ incluído no pacote traz uma configuração de nó único otimizada para desempenho. Requisito multi-tenant: a configuração incluída habilita o gerenciamento de acesso SQL + users_without_row_policies_can_read_rows=false para que o servidor possa criar um usuário ClickHouse somente leitura + row policy por organização (o limite de isolamento imposto pela engine para o editor SQL e o agente de IA). Se você fornecer sua própria configuração do ClickHouse, mantenha essas configurações (veja deploy/base/clickhouse/configmap.yaml).
  • Redis 7+: opcional — cache compartilhado + backend de rate limit. O servidor e o dashboard se conectam via REDIS_URL. Se ausente, ambos degradam graciosamente para caminhos somente com Postgres. Veja Redis (cache opcional) abaixo.

Servidor

Obtendo a imagem

As builds atuais são publicadas sob beta-latest; latest é atribuído apenas a releases estáveis. Para produção, fixe uma tag específica :v<versão>; veja Tags de Imagem Disponíveis.

Variáveis de ambiente

VariávelObrigatóriaPadrãoDescrição
DATABASE_URLSimnenhumDSN do Postgres. Formato de string de conexão libpq padrão com esquema postgres://. Suporta ?sslmode=require e outros parâmetros libpq. A senha não deve conter /, + ou =; use openssl rand -hex para gerar senhas seguras para URL.
ADMIN_KEYNãonenhumChave de API admin inicial. Inserida/atualizada com todas as permissões a cada inicialização. Troque alterando o valor e reiniciando.
LISTEN_ADDRNão0.0.0.0:8080Endereço TCP para vincular
MAX_BODY_BYTESNão134217728 (128 MB)Tamanho máximo do corpo da requisição
ADMIN_EMAILNãonenhumE-mail do usuário admin inicial. Inserido/atualizado com todas as permissões a cada inicialização e marcado como protegido: não pode ser desabilitado nem ter suas permissões modificadas via dashboard/API. Para trocar o admin inicial, altere ADMIN_EMAIL e reinicie; o novo e-mail é inserido como protegido, e o anterior mantém sua proteção até ser limpo manualmente no banco de dados.
ALLOWED_EMAILSNãonenhum (todos bloqueados)Lista de e-mails permitidos para criação de usuário e login, separados por vírgula. Suporta endereços exatos (user@example.com) e curingas de domínio (*@example.com). Se não definido, nenhum usuário pode ser criado ou fazer login. Apenas na primeira inicialização: alimenta a lista de permissões da org padrão na primeira inicialização; a partir daí, a página /<org>/settings de cada org é a fonte da verdade e alterar esta variável de ambiente não tem efeito.
SMTP_HOSTNãonenhumNome do host do servidor SMTP para envio de e-mails OTP. Se não definido, os códigos OTP são registrados no stdout.
SMTP_PORTNão587Porta do servidor SMTP
SMTP_USERNAMENãonenhumNome de usuário para autenticação SMTP
SMTP_PASSWORDNãonenhumSenha para autenticação SMTP
SMTP_FROMNãonenhumEndereço de e-mail do remetente para e-mails OTP
SMTP_TLSNãoSTARTTLSSTARTTLS é usado, a menos que você o desative explicitamente: false ou 0 envia em texto simples (sem TLS); qualquer outro valor — inclusive não definido — habilita STARTTLS.
DASHBOARD_URLNãopadrão internoOrigem do dashboard usada para construir tanto o magic link do e-mail OTP quanto os magic links de incidentes nas notificações de alerta. Se não definido, usa um padrão interno (e, apenas para OTP, a origem derivada da requisição do dashboard primeiro). Defina para configurações de domínios separados, para que tanto o e-mail quanto os links do Slack/incidentes apontem para o seu dashboard. Veja URL do magic link de e-mail abaixo; a maioria dos operadores não precisa definir isso.
SESSION_TTL_SECSNão86400 (24 h)Duração da sessão do dashboard em segundos. Apenas na primeira inicialização: edite por org via /<org>/settings após o primeiro deploy.
OTP_TTL_SECSNão600 (10 min)Período de validade do código OTP em segundos. Apenas na primeira inicialização: edite por org via /<org>/settings após o primeiro deploy.
REDIS_URLNãonenhumBackend opcional de cache compartilhado + rate limit, ex.: redis://redis:6379/0. Quando definido, o servidor faz cache de lookups de API keys autenticadas, o agregado /models do dashboard, a lista de sessões e a faceta de lista de ambientes; também move o rate limiting de requisições OTP do Postgres COUNT para o Redis INCR. Se não definido ou inacessível, o servidor funciona sem o cache (o limite OTP recai para o Postgres; todas as outras chamadas de cache passam direto para a fonte da verdade). Veja Redis (cache opcional) abaixo.
CLICKHOUSE_URLSimnenhumURL base da instância do ClickHouse, ex.: http://clickhouse:8123. O servidor aplica o esquema de eventos a esse banco de dados a cada inicialização e se recusa a iniciar se não conseguir alcançar o ClickHouse. Veja ClickHouse (armazenamento analítico obrigatório) abaixo.
CLICKHOUSE_DATABASENãoagenteyeNome do banco de dados (schema) do ClickHouse. O servidor o cria na inicialização se não existir.
ORG_CH_SECRETNão (single-tenant) / Sim (multi-org)padrão de desenvolvimentoChave HMAC da qual a senha ClickHouse por tenant de cada organização é derivada. O editor SQL e o run_query do agente de IA são executados como o usuário ClickHouse somente leitura da org, cuja row policy impõe o isolamento de tenant na engine. Deployments single-tenant funcionam bem com o padrão de desenvolvimento interno; antes de provisionar uma segunda org, você DEVE definir um valor forte e estável, pois o CLI agenteye-orgctl org create se recusa a executar com o padrão de desenvolvimento interno. Rotacionar esse valor torna órfão o usuário ClickHouse de cada org até a próxima inicialização reaprovisioná-los (a reconciliação na inicialização corrige isso automaticamente). Mantenha-o secreto e inalterado em todas as réplicas. O provisionamento de orgs é exclusivo do operador; veja Organizações (multi-tenancy) abaixo.
DEFAULT_ORG_NAMENãoDefaultNome de exibição inserido para a org padrão integrada. Apenas na primeira inicialização, e somente enquanto a org ainda mantém sua identidade genérica recém-migrada, aplicado na inicialização e depois ignorado. Após renomear a org (agenteye-orgctl org rename), o novo nome é autoritativo e esta variável não tem mais efeito.
DEFAULT_ORG_SLUGNãodefaultSlug de URL para a org padrão integrada, o caminho do dashboard onde ela reside (/<slug>/…). Mesma semântica de apenas na primeira inicialização / apenas quando em estado original que DEFAULT_ORG_NAME. Deve ter entre 1 e 40 caracteres alfanuméricos minúsculos com hífens internos simples e não ser uma palavra reservada; um valor inválido é ignorado (a org mantém default). Permite que uma instalação single-tenant se apresente como, por exemplo, /acme em vez de /default sem nenhuma etapa de CLI pós-deploy.
RUST_LOGNãoinfoVerbosidade de log (debug, warn, error, agenteye_server=trace)
EVALUATOR_ENDPOINTNãonenhumURL base do seu serviço avaliador (ex.: http://evaluator:9000). Quando não definido, todo o pipeline de avaliação é um no-op; nenhuma linha de fila é escrita, nenhum worker é executado. Veja Suite de Avaliação.
EVALUATOR_TOKENNãonenhumEnviado como Authorization: Bearer <token> para o avaliador. Deve ser igual ao valor com o qual o serviço avaliador está configurado. Opcional apenas se o seu avaliador estiver configurado sem token.
EVALUATOR_WORKERSNão2Concorrência: número de tarefas worker por instância do servidor que despacham avaliações. Seguro para executar em vários servidores com escala horizontal.
EVALUATOR_CLAIM_BATCHNão4Número máximo de avaliações que um único worker reivindica por tick. Os lotes são despachados concorrentemente, portanto a concorrência total no seu endpoint avaliador é EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH.
EVALUATOR_POLL_IDLE_SECSNão2Quanto tempo um worker dorme entre tentativas de despacho quando nada está pendente.
EVALUATOR_POLLING_INTERVAL_SECSNão10Cadência de fallback final (segundos) para polls GET /evaluate/{id} quando o avaliador não retorna um next_poll_secs por resposta e não anuncia um default_poll_interval_secs de GET /config.
EVALUATOR_REQUEST_TIMEOUT_MSNão30000Timeout por requisição HTTP contra o avaliador (milissegundos).
EVALUATOR_MAX_ATTEMPTSNão5Após esse número de tentativas com falha, uma avaliação é registrada como error terminal (ou timeout se as falhas foram timeouts de requisição).
EVALUATOR_CONFIG_REFRESH_SECSNão300 (5 min)Com que frequência o servidor re-busca GET /config do avaliador.
EVALUATOR_MAX_POLL_DURATION_SECSNão3600 (1 h)Tempo máximo de relógio de parede que uma sessão pode permanecer na fila de polling antes de o AgentEye encerrá-la como timeout. Protege contra um avaliador que retorna pending indefinidamente.
ALERT_WORKERSNão1Concorrência: número de tarefas worker por instância do servidor que avaliam regras de alerta. Veja Alertas.
ALERT_CLAIM_BATCHNão16Número máximo de alertas que um único worker reivindica por tick.
ALERT_POLL_IDLE_SECSNão5Quanto tempo um worker de alertas dorme quando a fila está vazia.
ALERT_REQUEST_TIMEOUT_MSNão15000Timeout de avaliação por disparo (consultas ClickHouse + HTTP de canal de saída).
ALERT_MAX_ATTEMPTSNão5Falhas transitórias consecutivas antes de um alerta ser reagendado em sua cadência normal em vez de backoff exponencial.
AUDIT_WORKERSNão1Concorrência: número de tarefas worker por instância do servidor que executam auditorias. Veja Auditorias.
AUDIT_CLAIM_BATCHNão1Número máximo de auditorias pendentes que um único worker reivindica por tick. Uma investigação agêntica é um longo loop, então o padrão é 1.
AUDIT_POLL_IDLE_SECSNão30Quanto tempo um worker de auditorias dorme quando nenhuma auditoria está pendente.
AUDIT_REQUEST_TIMEOUT_MSNão30000Timeout por consulta de política contra o ClickHouse (milissegundos).
AUDIT_LLM_TIMEOUT_MSNão1440000Timeout para a chamada de investigação agêntica ao serviço de assistente de IA. Um loop de agente completo dura minutos; mantenha isso ACIMA do próprio AGENTEYE_AUDIT_TIMEOUT_MS do agente para que ele retorne seus resultados parciais antes de o servidor desistir.
AUDIT_MAX_ATTEMPTSNão5Falhas transitórias consecutivas antes de uma auditoria ser reagendada em sua cadência normal em vez de backoff exponencial.
AGENTEYE_AGENT_URL / AGENTEYE_AGENT_TOKENNãoA investigação agêntica da auditoria chama o serviço agent do assistente de IA, reutilizando a mesma conexão do assistente — portanto, defina esses dois no servidor também (os manifestos/compose incluídos fazem isso). Ambos definidos ⇒ as auditorias executam a investigação de IA; qualquer um não definido ⇒ as auditorias executam somente política (o passo de política SQL determinístico ainda é executado), independentemente da flag llm_enabled por auditoria. O agente também deve ter um LLM configurado — veja assistant.md.
Serviço de assistente de IA — configurações de auditoria + sandbox. A investigação agêntica e seu sandbox Python no pod são ajustados no serviço de agente (não no servidor), todos com o prefixo AGENTEYE_AUDIT_* e todos opcionais:
VariávelPadrãoSignificado
AGENTEYE_AUDIT_MAX_STEPS200Máximo de turnos do agente por investigação.
AGENTEYE_AUDIT_TIMEOUT_MS1200000Tempo de relógio de parede para uma investigação (20 min). Deve ficar abaixo do AUDIT_LLM_TIMEOUT_MS do servidor.
AGENTEYE_AUDIT_MAX_CONCURRENCY1Investigações simultâneas por pod de agente (separado do orçamento do assistente de chat).
AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS / _MEM_MB / _CPU_SECS / _OUTPUT_MAX_BYTES / _SCRIPT_MAX_BYTES20000 / 768 / 10 / 64000 / 64000Limites por script para o sandbox bubblewrap.
Requisito de plataforma do sandbox. O sandbox de código de auditoria executa o Python do modelo dentro de uma jaula bubblewrap, que precisa de namespaces de usuário sem privilégios. O pod do agente deve permitir as flags clone() — defina seccompProfile: Unconfined (k8s) ou security_opt: [seccomp:unconfined] (compose) no agente. Onde o kernel do nó desabilita namespaces de usuário sem privilégios (ex.: algumas imagens GKE COS), o sandbox falha no preflight e o auditor degrada automaticamente para somente SQL — sem erro, apenas um sandbox_available: false no /health do agente.

Executar

Defina DATABASE_URL em seu ambiente e passe para o container:
O servidor executa as migrações de banco de dados automaticamente na inicialização; nenhuma etapa de migração separada é necessária.

Health check

Nenhuma autenticação necessária. Use /health para probes de liveness e /ready para probes de readiness / balanceador de carga. /ready verifica as dependências obrigatórias sem as quais o servidor não pode operar (Postgres + ClickHouse), portanto, um servidor em execução que não consegue alcançar seu banco de dados é retirado de rotação e exibido como NotReady; o Redis é reportado, mas nunca falha o readiness. Nos manifestos Kubernetes incluídos, a probe de readiness já aponta para /ready e o liveness permanece em /health. Veja enterprise-docs/health-monitoring.md para o quadro completo, incluindo alertas opcionais de falha de pod nativos do Kubernetes para o Slack. Os e-mails de login OTP contêm um botão abrir o dashboard com um único toque. Ao clicar, o usuário é direcionado para /login?token=<code>&email=<address>; o dashboard troca esse par por uma sessão e redireciona para o aplicativo, sem necessidade de inserir o código manualmente. O servidor resolve a origem do dashboard usada para construir o link em três níveis:
  1. Header X-AgentEye-Dashboard-Url: definido automaticamente pelo proxy /api/auth/otp/request do dashboard a partir de sua própria origem pública. Em um deploy no mesmo domínio (servidor e dashboard compartilham um host atrás de um único ingress que encaminha os headers do proxy), nenhuma configuração é necessária.
  2. Variável de ambiente DASHBOARD_URL: defina isso se o seu dashboard estiver acessível em uma origem diferente daquela que o endpoint de requisição OTP do servidor vê (domínios separados api.example.com / app.example.com), ou se o seu ingress não propaga o host público para o pod do dashboard (para que request.nextUrl.origin não resolva para um endereço bind curinga como 0.0.0.0:3000). Exemplo: DASHBOARD_URL=https://app.example.com.
  3. Padrão: https://app.befailproof.ai, usado apenas se nenhum dos itens acima estiver presente.
O valor do header é validado: apenas origens https://* e loopback (http://localhost*, http://127.0.0.1*) são aceitos, e endereços bind curinga (0.0.0.0, [::]) são rejeitados mesmo com o esquema https://. Qualquer outra coisa passa para o nível 2. Defina em um cluster em execução com um comando de uma linha; sem arquivo, sem rebuild do kustomize:
Isso aciona um rollout; os novos pods capturam o valor na primeira requisição. Observe que a substituição reside apenas no Deployment; um kustomize build | kubectl apply subsequente contra o overlay irá apagá-la, a menos que você adicione a mesma variável de ambiente ao patch server-env.yaml do seu overlay.

Dashboard

Obtendo a imagem

Variáveis de ambiente

VariávelObrigatóriaPadrãoDescrição
AGENTEYE_SERVER_URLSimnenhumURL base do servidor, ex.: http://localhost:8080
AGENTEYE_API_KEYSimnenhumChave de API que o dashboard usa para se autenticar no servidor. Precisa de todas as permissões (chave admin recomendada).
AE_LOG_LEVELNãoinfoVerbosidade de log do lado do servidor: debug, info, warn, error. Defina como debug para ver linhas de requisição/resposta upstream e rastreamentos de validação de sessão ao diagnosticar problemas.
AE_LOG_JSONNãoautomático1 força saída JSON por linha; 0 força saída legível por humanos. Quando não definido, o JSON é habilitado automaticamente se NODE_ENV=production. JSON é recomendado em produção para que os logs sejam analisados corretamente com jq ou um agregador de logs.
AE_ANALYTICS_DISABLEDNãonenhumDefina como 1/true para desabilitar a telemetria anônima de uso de produto do dashboard. Veja Telemetria e privacidade abaixo.
REDIS_URLNãonenhumBackend opcional de cache compartilhado, ex.: redis://redis:6379/0. Quando definido, o dashboard faz cache dos resultados de validateSession() entre réplicas e compartilha o cache de fetch do Next.js para as rotas proxy de latência-agregada / lista de ambientes. Os rate limits OTP de requisição e verificação do lado do edge também usam Redis quando disponível (falhando abertos se o Redis estiver inacessível; o limite do lado do servidor é a salvaguarda de segurança). Veja Redis (cache opcional) abaixo.
AGENTEYE_AGENT_URLNãonenhumURL base do serviço agent do assistente de IA opcional, ex.: http://agent:9100. Deixe não definido para ocultar o assistente completamente: nenhuma bolha do assistente aparece no dashboard. Veja enterprise-docs/assistant.md.
AGENTEYE_AGENT_TOKENNãonenhumSegredo compartilhado que o dashboard apresenta ao serviço agent. Deve corresponder ao AGENTEYE_AGENT_TOKEN configurado no agente. Veja enterprise-docs/assistant.md.

Executar

Telemetria e privacidade

O dashboard envia análises anônimas de uso de produto para o serviço de análise da Exosphere (PostHog): quais páginas do dashboard são visualizadas e um conjunto de ações de interface como criar uma chave de API ou reavaliar uma sessão. Esse sinal de uso informa quais funcionalidades são priorizadas.
  • Nenhum dado de agente, sessão ou evento sai da sua infraestrutura. Apenas o uso da interface do dashboard é reportado. As URLs de página são removidas de identificadores antes do envio, e os operadores são identificados apenas por um id interno opaco, nunca por e-mail.
  • A telemetria está habilitada por padrão. Para desativá-la completamente, defina AE_ANALYTICS_DISABLED=1 no container do dashboard e reinicie.
  • As análises são enviadas para o próprio caminho /ingest do dashboard, que o dashboard faz proxy reverso para o PostHog (https://us.i.posthog.com). Manter as requisições como first-party significa que bloqueadores de anúncios do navegador não as descartam. O container do dashboard precisa de acesso de saída para o PostHog; se estiver bloqueado, a telemetria silenciosamente não faz nada e o dashboard não é afetado.

Assistente de IA (opcional)

Um assistente de IA integrado ao dashboard permite que sua equipe faça perguntas sobre os dados do agente em linguagem natural (resumindo sessões, redigindo SQL para o editor /queries e transformando consultas salvas em tiles do dashboard) sem sair do dashboard. Ele é executado como um container agent interno separado (no Agents SDK) que somente o dashboard pode alcançar, e permanece desabilitado até que você configure um endpoint de LLM. Para habilitá-lo, você define no serviço agent uma conexão de LLM (Portkey via PORTKEY_API_KEY + um slug de catálogo de modelos AGENTEYE_AGENT_MODEL=@<slug>/<model>, Anthropic direto via ANTHROPIC_API_KEY, outro gateway via ANTHROPIC_BASE_URL, ou Bedrock/Vertex), uma chave de dados dedicada e um AGENTEYE_AGENT_TOKEN compartilhado correspondente ao dashboard. Os usuários do dashboard também precisam da permissão agent:use. Para a chave de dados do assistente, você não cria nada manualmente: escolha um segredo aleatório, defina-o como AGENTEYE_API_KEY no agent e como AGENT_API_KEY no server, e o servidor o inicializa com um conjunto fixo de permissões na inicialização. Seu acesso aos dados é somente leitura (events:read, evaluations:read, dashboards:read, queries:read), e ele adicionalmente possui escopos de autoria com aprovação (dashboards:write, queries:write, queries:run) para que possa redigir e validar consultas salvas e criar tiles de dashboard em nome do usuário; todo SQL ainda é executado pelo role ClickHouse somente leitura da org, portanto isso amplia o que o assistente pode criar, não os dados que ele pode acessar. Os escopos são fixos no código e não podem ser ampliados por configuração. Essa chave é protegida; não pode ser desabilitada ou regenerada via API, apenas rotacionada alterando o valor e reiniciando. Nunca reutilize a chave admin/dashboard para isso. A configuração completa, a referência completa de variáveis de ambiente, as opções de telemetria e o modelo de segurança estão em enterprise-docs/assistant.md.

ClickHouse (armazenamento analítico obrigatório)

O ClickHouse mantém seus dashboards responsivos em altos volumes de eventos e permite que o editor SQL /queries faça joins entre eventos, avaliações e sessões em um único armazenamento. É o armazenamento canônico obrigatório para cada evento ingerido, cada resultado de avaliação terminal e os agregados derivados por sessão. O PostgreSQL mantém as tabelas relacionais/de estado mutável (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); a camada analítica reside no ClickHouse para que os rollups do dashboard e suas próprias consultas SQL possam escaneá-la e fazer joins nativamente, sem round-trips entre bancos de dados. O servidor se recusa a iniciar sem CLICKHOUSE_URL.

Schema

Três objetos ClickHouse são criados na inicialização do servidor, todos idempotentes (CREATE IF NOT EXISTS):
  • agenteye.events: ReplacingMergeTree(ingested_at), particionado por toYYYYMM(ts), ordenado por (session_id, ts, dedup_key). Inserções duplicadas (retentativas do collector) colapsam para uma única linha no momento do merge; o servidor computa um dedup_key SHA-256 determinístico para cada evento, tornando as retentativas seguras.
  • agenteye.evaluations: ReplacingMergeTree(ingested_at), particionado por toYYYYMM(finished_at), ordenado por (session_id, finished_at, dedup_key). Escrito uma vez por resultado de avaliação terminal pelo pipeline do avaliador. Mesmo modelo de dedup-key que events.
  • agenteye.agent_sessions: uma VIEW sobre agenteye.events, não uma tabela física. Cada coluna é derivada (started_at = min(ts), last_event_at = max(ts), ended_at = max(if event_type='agent_end', ts, NULL), event_count = count(), etc.). Sem upsert por evento e sem backfill separado; a view reflete automaticamente o que estiver em events.
Para compatibilidade retroativa com consultas salvas que referenciam analytics.evaluations / analytics.sessions, o servidor também cria um banco de dados analytics no ClickHouse com views sobre as tabelas agenteye.*; analytics.events, analytics.evaluations, analytics.agent_sessions, analytics.sessions resolvem corretamente.

Configuração

O docker-compose incluído e deploy/base/clickhouse/ trazem um serviço ClickHouse ajustado para a carga de trabalho do AgentEye:
  • 2 GiB solicitado / 4 GiB limite de memória no overlay base incluído (dimensionado para caber em nós pequenos de POC/staging); clientes de produção devem aumentar — o mínimo recomendado é 2c / 4Gi de request, 6c / 8Gi de limit. max_server_memory_usage_to_ram_ratio=0.9
  • 5 GiB de mark cache + 8 GiB de uncompressed cache
  • background_pool_size=16, background_merges_mutations_concurrency_ratio=2
  • MergeTree: parts_to_throw_insert=3000, parts_to_delay_insert=1500, non_replicated_deduplication_window=1000
  • local_io_method=auto (io_uring em kernels suportados)
  • fsync_metadata=0: aceitável devido à ingestão at-least-once + dedup ReplacingMergeTree
  • query_log habilitado com TTL de 30 dias; query_thread_log removido (caro em alto QPS)
  • max_execution_time=30 para consultas do usuário
  • PVC de 100 GiB no template StatefulSet (os overlays do cliente DEVEM substituir por uma storage class SSD rápida para produção)

Backups

Seu conjunto de dados completo é capturado diariamente em um único arquivo restaurável, portanto uma perda de cluster ou armazenamento é recuperável. O ClickHouse tem backup automático feito pelo CronJob agenteye-backup diário, que faz dump do PostgreSQL e do ClickHouse em uma única passagem. O ClickHouse é lido pela sua API HTTP: agenteye.events e agenteye.evaluations são dumpados no formato nativo do ClickHouse (as views e row policies são recriadas pelo servidor na inicialização, portanto os dados da tabela são o quadro completo) e empacotados com o dump do Postgres em um único arquivo comprimido enviado para o seu armazenamento de objetos. O bucket de destino e as credenciais de nuvem são configurados por overlay. Veja a seção Backups de enterprise-docs/kubernetes-deployment.md para configuração de upload e etapas de restauração.

Redis (cache opcional)

O Redis é um backend opcional de cache compartilhado + rate limit usado pelo servidor e pelo dashboard. Com o Redis implantado e REDIS_URL definido em ambos os serviços:
  • Servidor faz cache de lookups de API keys autenticadas, as listas /events/environments + /evaluations/environments, o rollup /events/latency_aggregate (a consulta mais pesada que o dashboard realiza periodicamente), a lista /sessions, e troca o rate limiting de requisições OTP de um COUNT(*) Postgres para um INCR + EXPIRE Redis.
  • Dashboard faz cache dos resultados de validateSession() para que as 10-20 chamadas de API autenticadas que um carregamento de página típico realiza compartilhem uma única verificação de sessão upstream. Também aplica rate limit nas requisições OTP e na verificação OTP na borda do dashboard.
Ambos os serviços degradam graciosamente se o Redis estiver inacessível. Cada chamada de cache retorna Err dentro de um timeout limitado e o chamador recai para a fonte da verdade (Postgres no servidor, o servidor Rust upstream no dashboard). O rate limiting OTP recai para o caminho COUNT(*) do Postgres no servidor (a propriedade de segurança é preservada); o limite OTP de borda do dashboard falha aberto enquanto o limite do lado do servidor ainda vale. O Redis fora do ar degrada a latência, não a correção.

Configuração

O pacote docker-compose já inclui um serviço Redis e conecta REDIS_URL=redis://redis:6379/0 ao servidor e ao dashboard. Para usar um Redis externo, defina REDIS_URL para o seu endpoint e remova o serviço redis do arquivo compose.

Memória e persistência

A imagem Redis incluída é executada com --appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru. A persistência AOF significa que o cache sobrevive a reinicializações do container; everysec é o equilíbrio certo entre durabilidade e desempenho, pois perder o último segundo de escritas de cache é inofensivo. A evicção LRU limita o crescimento da memória.

Quando NÃO implantar o Redis

  • Dev/QA de instância única. Os caches em processo no servidor sozinho entregam a maior parte do benefício por réplica; o Redis adiciona o compartilhamento entre réplicas que as configurações de instância única não precisam.
  • Instalações air-gapped onde o custo operacional de executar mais um serviço supera o ganho de latência.

Docker Compose (recomendado)

Um docker-compose.yml está disponível no repositório agenteye-enterprise/releases. Ele inicializa o Postgres, o servidor e o dashboard com um único comando.
Substitua os padrões via .env:
Parar (mantém o volume de dados):
Parar e apagar todos os dados:

Configurações operacionais

Um pequeno conjunto de ajustes operacionais que costumavam ser fixados por variáveis de ambiente agora é editável por organização na página /<org>/settings do dashboard; cada org configura a sua própria. As alterações entram em vigor em segundos, sem reinicialização e sem redeploy.
ConfiguraçãoVariável de ambiente inicialO que controla
Logins permitidosALLOWED_EMAILSE-mails (ou curingas *@domain.com) com permissão para receber um OTP e ser adicionados como usuários
Permissões padrão do usuárioDEFAULT_USER_PERMISSIONSTokens de permissão separados por vírgula pré-selecionados quando um admin abre + novo usuário. Cada token deve ser uma das strings listadas em Permissões de chave de API. O padrão é o preset standard: acesso somente leitura mais as ações cotidianas de plantão (acionar reavaliações, executar consultas, reconhecer incidentes, usar o assistente).
Tempo de vida da sessãoSESSION_TTL_SECSPor quanto tempo um login no dashboard permanece válido antes de nova autenticação. O dashboard re-verifica a sessão upstream a cada 5 segundos, portanto uma atualização de permissão em /<org>/users entra em vigor na próxima requisição do usuário afetado, sem novo login.
Tempo de vida do código únicoOTP_TTL_SECSPor quanto tempo um OTP / magic link permanece utilizável
Canais de notificação de alertaALERTS_ENABLED_CHANNELSLista separada por vírgula de tipos de canais que o dispatcher de alertas tem permissão para usar: email, slack, webhook. A configuração por alerta ainda é criada em /<org>/alerts/<id>, mas o dispatcher filtra cada entrega de saída por esse conjunto; um canal desabilitado aqui curto-circuita com uma linha de auditoria skipped_disabled. O canal dashboard (a inserção de auditoria local) é sempre permitido. O padrão é todos os três habilitados.

Como o bootstrap funciona

As configurações são armazenadas por organização em org_settings. Na primeira inicialização, o servidor alimenta as linhas ausentes da org padrão a partir da variável de ambiente correspondente (ou um padrão razoável se a variável não estiver definida). Após isso, o valor armazenado é a fonte da verdade e a variável de ambiente é ignorada; alterar a variável de ambiente em uma reinicialização posterior não afetará o valor de uma org em funcionamento, e orgs adicionais começam com os padrões e configuram as suas próprias. Isso significa:
  • Para um deploy novo, defina as variáveis de ambiente conforme mostrado acima e a org padrão as lerá na primeira inicialização.
  • Para alterar um valor posteriormente, faça login no dashboard e edite em /<org>/settings. A alteração se aplica em segundos em todas as réplicas do servidor; sem reinicialização necessária.
  • Uma linha de log na inicialização registra o que foi alimentado versus o que já estava presente, para que você possa confirmar que o bootstrap teve efeito:

Semântica de login entre organizações

Uma sessão e um OTP são globais para o usuário, não para uma única org, portanto duas regras reconciliam as configurações por org no momento do login:
  • Tempo de vida da sessão / OTP: o mais restritivo (mais curto) entre as orgs às quais o usuário pertence prevalece.
  • Logins permitidos: a verificação faz OR de todas as listas de permissão de cada org com a associação à org: um usuário pode solicitar um OTP se a lista de permissão de qualquer org admitir seu e-mail ou ele já for membro de qualquer org.

Permissões

O acesso a uma página /<org>/settings é controlado por duas permissões:
  • settings:read: ver a página e os valores atuais.
  • settings:write: salvar alterações.
O usuário admin inicial (alimentado de ADMIN_EMAIL) recebe ambas automaticamente, junto com todas as outras permissões. Conceda-as a outros usuários em /<org>/users conforme necessário.

Organizações (multi-tenancy)

Um único deploy pode servir múltiplas organizações (tenants) isoladas; cada linha de dados pertence a exatamente uma org e o isolamento é imposto no engine do banco de dados. Uma instalação single-tenant não precisa de nada aqui; todos os dados residem em uma org default integrada. (Você pode dar a essa org um nome mais amigável e slug de URL, para que ela fique em, por exemplo, /acme em vez de /default, definindo DEFAULT_ORG_NAME / DEFAULT_ORG_SLUG antes da primeira inicialização, ou renomeando-a a qualquer momento com agenteye-orgctl org rename.) O provisionamento de tenants é exclusivo do operador. Organizações e suas associações são criadas e gerenciadas com o CLI agenteye-orgctl, que vem dentro da imagem do servidor (ao lado de agenteye-server) e é executado dentro do pod do servidor existente; não há pod/Job separado, sem API HTTP e sem botão no dashboard. Ele reutiliza o DATABASE_URL, CLICKHOUSE_URL e ORG_CH_SECRET do servidor.
Verbos disponíveis: org create | list | rename | delete | purge e member add | list | update | remove, com conjuntos de permissões integrados admin, standard e read-only. Membros adicionados recebem um OTP no primeiro login no dashboard. Antes de criar uma segunda org: defina um ORG_CH_SECRET forte e estável (o comando org create se recusa a executar com o padrão de desenvolvimento interno) e certifique-se de que o Postgres seja 15+. Inalterado: chaves de API por org ainda são criadas no dashboard/API por membros da org; apenas o ciclo de vida da org + membro foi movido para o CLI. Referência completa de comandos e um exemplo prático: enterprise-docs/tenant-management.md.

Preenchimento de janela de contexto

Cada evento model_response exibe uma pílula de context-fill — tokens de entrada mais saída como percentual da janela de contexto desse modelo. As faixas são healthy (0–24%), watch (25–49%), compacting (50–74%) e reset context (75–100%). O AgentEye resolve IDs de modelos comuns automaticamente, portanto nenhuma configuração inicial é necessária. Cada modelo que uma organização envia aparece em Configurações → janelas de contexto de modelos. Usuários com settings:write podem substituir sua janela ou adicionar um modelo privado/proxy (0–1.000.000 tokens); 0 significa “desconhecido” e suprime a pílula. As alterações se aplicam a eventos recém-ingeridos. Usuários com settings:read podem visualizar a lista. Novos eventos recebem o preenchimento a partir do momento em que você atualiza. Para também popular eventos históricos (e a lista por modelo) em um deploy existente, execute o backfill único — ele vem dentro da imagem do servidor (como agenteye-orgctl) e é executado no pod do servidor existente:
É idempotente (seguro para re-executar) e reutiliza DATABASE_URL / CLICKHOUSE_URL / REDIS_URL do pod. Re-execute-o após editar as janelas de modelos se quiser que os eventos existentes sejam recomputados.

Considerações de produção

  • Postgres: Use um serviço Postgres gerenciado ou uma instância dedicada com backups regulares. O DATABASE_URL suporta todos os parâmetros libpq padrão, incluindo sslmode=require para conexões criptografadas.
  • TLS: Coloque o servidor e o dashboard atrás de um proxy reverso (nginx, Caddy, Traefik) que encerre o TLS.
  • Firewall: A porta do servidor (padrão 8080) deve ser acessível apenas a partir das máquinas do collector e do host do dashboard, não da internet pública.
  • Chave admin: Defina ADMIN_KEY como um segredo aleatório forte. Após o bootstrap, crie chaves com escopo dedicado para collectors e o dashboard em vez de usar a chave admin em todo lugar.
  • Tags de imagem: Fixe na versão nos manifestos de release (por exemplo, server:v0.0.1-beta.48) em produção, em vez de uma tag flutuante, para evitar upgrades não intencionais. As builds beta atuais são publicadas sob beta-latest; latest é atribuído apenas a releases estáveis.
  • Monitoramento de saúde: No Kubernetes, a probe de readiness usa /ready (acessibilidade do Postgres + ClickHouse) enquanto o liveness permanece em /health. Para alertas “o AgentEye está funcionando?” em toda a frota para o Slack, habilite o add-on Robusta opcional; veja enterprise-docs/health-monitoring.md.

Tags de Imagem Disponíveis

TagDescrição
latestÚltima release estável
beta-latestÚltima pré-release (beta)
v<version>Versão fixada, ex.: v0.0.1-beta.48 (recomendado para produção)