/<org-slug>/…, y el stream de eventos es la página principal de la organización (/<org-slug>/). Los nombres de página en esta guía (por ejemplo /sessions, /queries) se refieren a esas rutas con alcance de organización.
Ver logs
AgentEye no incluye una pila de logging ni monitoreo. Tanto el servidor como el dashboard escriben logs estructurados en stdout, por lo que puedes leerlos directamente conkubectl o docker; no se necesita ningún agregador.
Kubernetes
Sigue los logs en tiempo real del servidor y del dashboard:| Objetivo | Comando |
|---|---|
| Últimas 200 líneas (sin seguimiento) | kubectl logs -n agenteye -l app=server --tail=200 --timestamps |
| Logs del crash anterior | kubectl logs -n agenteye <pod-name> --previous |
| Seguir todas las réplicas a la vez | kubectl logs -n agenteye -l app=server --max-log-requests=10 -f |
| Postgres (StatefulSet) | kubectl logs -n agenteye postgres-0 -f |
Docker Compose
Correlacionar una solicitud individual entre dashboard y servidor
Cada solicitud del dashboard se etiqueta con unrequest_id y se propaga al servidor mediante la cabecera x-request-id. El servidor lo incluye en sus cabeceras de respuesta y en cada línea de log que emite para esa solicitud. Para rastrear una solicitud de extremo a extremo:
- Captura el id desde la cabecera de respuesta, por ejemplo:
- Filtra los logs de ambos pods por ese id:
proxy passthrough, withAuth: authorized y upstream response del dashboard junto con el par http request received / http request completed del servidor, todos compartiendo el mismo request_id.
Logs JSON y jq
Configura AE_LOG_JSON=1 en el dashboard (está activado por defecto cuando NODE_ENV=production) para emitir un objeto JSON por línea. Luego filtra de forma estructurada:
key=value que funcionan bien con grep sin necesidad de jq:
Aumentar el nivel de verbosidad
| Componente | Variable de entorno | Ejemplo |
|---|---|---|
| Servidor | RUST_LOG | RUST_LOG=debug o RUST_LOG=agenteye_server=debug,info |
| Dashboard | AE_LOG_LEVEL | AE_LOG_LEVEL=debug |
debug en el servidor añade una línea api key authenticated por cada autenticación. debug en el dashboard añade líneas upstream request, session validated y proxy passthrough.
Retención de logs
El stdout del contenedor es efímero; kubelet rota los archivos de log (por defecto ~10 MiB por contenedor) y conserva un número reducido en disco. Una vez que el pod se elimina, los logs desaparecen. Si necesitas retención prolongada o búsqueda entre pods, apunta tu clúster a un colector de logs (Loki, CloudWatch, Cloud Logging, Datadog, etc.) que siga/var/log/containers/. AgentEye no requiere ni prescribe ninguna opción específica.
Problemas de autenticación
docker pull falla con “unauthorized”
Asegúrate de haber autenticado Docker contra GHCR con tu AGENTEYE_TOKEN:
read:packages en la organización agenteye-enterprise. Contacta a support@exosphere.host si tu token no funciona.
gh release download devuelve 404 o 401
- Confirma que
AGENTEYE_TOKENestá exportado en tu shell:echo $AGENTEYE_TOKEN - Confirma que estás usando
GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...(la CLIghleeGITHUB_TOKEN) - El token necesita
contents:readenagenteye-enterprise/releases
Problemas del servidor
El servidor falla con “invalid port number”
ElPOSTGRES_PASSWORD (u otra credencial) contiene caracteres especiales de URL (/, +, =) que rompen el análisis de DATABASE_URL. Regenera la contraseña usando codificación hexadecimal:
.env para Docker Compose) y reinicia el servidor. Consulta los pasos completos en enterprise-docs/kubernetes-deployment.md § “PostgreSQL credentials”.
El servidor se cierra inmediatamente al arrancar
Revisa los logs del contenedor:DATABASE_URLno está configurado o está mal formado: el servidor registrará el error y saldrá.- Postgres no es accesible: confirma que el contenedor de Postgres o la base de datos gestionada está en ejecución y que el host/puerto son correctos.
- Las migraciones fallaron: revisa los logs en busca de errores SQL.
GET /health devuelve un código distinto de 200 o agota el tiempo de espera
Es posible que el servidor aún esté ejecutando migraciones en el primer arranque. Espera unos segundos y vuelve a intentarlo:
docker logs agenteye-server en busca de errores.
GET /ready devuelve 503
/ready es la sonda de preparación: devuelve 503 cuando el servidor no puede alcanzar Postgres o ClickHouse. El cuerpo indica la dependencia que falla:
down: ¿el pod de ClickHouse/Postgres está en estado Running? ¿Son correctos y accesibles CLICKHOUSE_URL / DATABASE_URL? En Kubernetes el pod aparece como NotReady hasta que /ready se recupera; eso es lo esperado y es exactamente la señal sobre la que alerta el monitoreo de salud. Redis nunca es la causa: se reporta pero no falla la preparación.
El colector devuelve 401 Unauthorized
La clave API del colector no tiene permisoevents:add, o la clave ha sido desactivada. Crea una nueva clave con el permiso correcto:
Las solicitudes autenticadas se volvieron lentas de repente (~200ms en lugar de ~5ms)
Este es el síntoma de que Redis está caído mientrasREDIS_URL está configurado. Cada llamada a la caché agota el tiempo de espera después de 100ms y recurre a Postgres; en las rutas de autenticación y OTP la solicitud realiza dos de estas recaídas.
Confirma en los logs del servidor:
redis-cli -h <your-redis> pingpara confirmar que Redis es accesible en la red del clúster.- Si Redis estuvo caído momentáneamente y ya volvió, reinicia los pods del servidor. El
redis::aio::ConnectionManagerno restablece la conexión de forma fiable después de que la conexión subyacente se interrumpe; un reinicio del pod toma la nueva conexión limpiamente. Lo mismo aplica al dashboard. - Si por ahora no quieres ejecutar Redis, elimina
REDIS_URLdel despliegue y reinicia. Ambos servicios funcionan sin la caché (la corrección se preserva; la latencia vuelve a la línea base previa a Redis).
El servidor reporta OTP request rate-limited en los logs pero el usuario dice que solo lo intentó una vez
Verifica si Redis era inaccesible. La ruta de respaldo usa SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes', que ve filas de OTP generadas anteriormente. Si el usuario ha estado haciendo clic repetidamente en “Reenviar” durante una hora, la ventana de 15 minutos puede contener aún ≥5 códigos. Resuélvelo esperando a que la ventana expire o ejecutando DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes' (consola del operador).
Cambié ALLOWED_EMAILS / SESSION_TTL_SECS / OTP_TTL_SECS y reinicié; no pasó nada
Estas variables de entorno son valores iniciales de primer arranque únicamente. Una vez que la tabla settings tiene una fila para la clave correspondiente, esa fila es la fuente de verdad; la variable de entorno se lee una sola vez en el primer arranque y luego se ignora en cada reinicio posterior.
Para cambiarlas después del primer arranque, inicia sesión en el dashboard y edítalas en /settings. El cambio se aplica en segundos en todas las réplicas; no es necesario reiniciar.
Si necesitas forzar una re-inicialización desde la variable de entorno (raro, generalmente útil solo en desarrollo), ejecuta DELETE FROM settings WHERE key = '<key>' y reinicia el servidor. El proceso de arranque tomará el valor actual de la variable de entorno en el siguiente inicio. Editar via /settings es la ruta soportada en producción.
Problemas del colector
El colector arranca pero los eventos no aparecen en el dashboard
- Confirma que el colector está en ejecución:
systemctl status agenteye-collector(Linux) o revisa el proceso. - Confirma que
AGENTEYE_URLapunta ahttp(s)://your-server-host:8080/events(nota: la ruta/events). - Ejecuta un flush único para ver la salida inmediata:
- Verifica que el SDK de Python realmente está escribiendo archivos:
ls ${AGENTEYE_HOME:-~/.agenteye}/events/ - Si hay archivos en
${AGENTEYE_HOME:-~/.agenteye}/failed/, las subidas están fallando. Revisa los logs del colector para ver el error, probablemente un 4xx (clave o URL incorrectos) o un problema de red.
Los archivos se acumulan en $AGENTEYE_HOME/events/ y no se suben
- Es posible que el colector no esté en ejecución. Inícialo:
agenteye-collector start; automáticamente envía los eventos pre-existentes al arrancar. - Verifica el estado del colector:
agenteye-collector health - El colector puede estar en ejecución pero sin poder llegar al servidor. Revisa las reglas del firewall entre los hosts del colector y el servidor.
Archivos en $AGENTEYE_HOME/failed/
Los archivos se mueven a failed/ después de agotar todos los reintentos (por defecto: 5 intentos con retroceso exponencial). Esto significa que:
- El servidor devolvió un error 4xx (clave incorrecta, URL incorrecta o problema con el payload)
- El servidor no fue accesible durante toda la ventana de reintentos
El colector reporta network error en cada subida (el handshake TLS falla)
Si curl -k contra AGENTEYE_URL tiene éxito pero el binario del colector falla en cada subida con error sending request for url (...), el servidor AgentEye está presentando un certificado TLS que no está firmado por una CA de confianza pública.
La ruta de producción es el hostname de ingesta ACME configurado en deploy/base/certificates/domain.env (ver kubernetes-deployment.md Fase 3.1 / 4.2). Una vez que INGEST_DOMAIN resuelve al LB público de Traefik y cert-manager ha emitido el certificado de Let’s Encrypt, los colectores verifican el certificado del servidor contra el almacén de confianza del sistema sin necesidad de AGENTEYE_TLS_CA; elimínalo de tu configuración del colector si se configuró para un despliegue anterior con certificado autofirmado.
Síntoma: el colector funcionaba ayer, falla hoy después de ~90 días. Esto significa que el despliegue sigue usando el emisor selfsigned heredado para ingest-tls. El certificado de 90 días rotó y el archivo de CA fijado está desactualizado. Corrige esto de forma permanente cambiando el clúster al emisor ACME (Fase 3.1 de la guía de despliegue). Solución temporal: vuelve a extraer el certificado actual del servidor y actualiza AGENTEYE_TLS_CA:
AGENTEYE_TLS_CA añade un ancla de confianza adicional; las raíces públicas estándar siguen siendo de confianza.
El certificado ingest-tls está atascado en Ready: False después del despliegue
Events y el Order / Challenge referenciado. Causas frecuentes:
- DNS no resuelve al LB público. El validador HTTP-01 no puede alcanzar
INGEST_DOMAIN. Verifica condig +short INGEST_DOMAIN; debería resolver a la misma dirección que elEXTERNAL-IPdel LoadBalancertraefik-public. cert-manager reintenta automáticamente una vez que el DNS se propaga; no es necesario eliminar el Certificate. - Puerto 80 bloqueado en el balanceador de carga / grupo de seguridad. HTTP-01 requiere que el puerto 80 sea accesible desde los validadores públicos de Let’s Encrypt. Si tienes un WAF o SG que restringe
:80, ábrelo (la configuración de Traefik redirige a HTTPS, pero Boulder sigue la redirección y acepta la respuesta). dnsNamesno sustituido. Sikubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'muestraINGEST_DOMAIN_PLACEHOLDER, omitiste el paso dedomain.env; créalo a partir dedomain.env.exampley vuelve a aplicarlo.- Limitado por la tasa de Let’s Encrypt. Los pedidos fallidos repetidos para el mismo hostname activan los límites de certificados duplicados o validaciones fallidas. Espera al menos una hora antes de reintentar; revisa el estado del Order para ver el mensaje exacto del límite de tasa.
El certificado dashboard-tls está atascado en Ready: False / el navegador sigue mostrando una advertencia
El mismo flujo de diagnóstico que ingest-tls anterior (kubectl describe certificate dashboard-tls -n agenteye); las causas de DNS, puerto 80, marcador de posición y límite de tasa aplican todas, más dos específicas del dashboard:
DASHBOARD_DOMAINresuelve al LoadBalancer incorrecto. Debe apuntar al LB de Traefik del dashboard, no al de ingesta pública. Hazdig +shortdel hostname y compáralo con la dirección del LB del dashboard.- La instancia de Traefik del dashboard no puede servir el challenge. Debe instalarse con el archivo de valores del dashboard incluido, que habilita un proveedor Ingress con alcance limitado para el solucionador HTTP-01 de cert-manager. Sin él, el solucionador no tiene ruta y el Order permanece
pendingindefinidamente. Actualiza la instancia con los valores proporcionados; el challenge pendiente se completará solo a continuación. - El LoadBalancer tenía restricciones de IP. Los rangos de origen aplican también al puerto 80, lo que bloquea los validadores de Let’s Encrypt — tanto en la emisión inicial como en cada renovación cada ~75 días. Vuelve a abrir el LB, o coordina un solucionador DNS-01 con soporte antes de restringirlo.
La CLI sigue omitiendo la verificación TLS después de que el dashboard obtuvo un certificado de confianza
--insecure se guarda en cli.json al iniciar sesión. Una vez que el dashboard sirve un certificado de confianza pública, vuelve a iniciar sesión con agenteye --base-url https://<your-dashboard-domain> --secure login; la verificación se guarda nuevamente activada y la advertencia de inicio desaparece.
Problemas del dashboard
No se puede deshabilitar ni editar el usuario ADMIN_EMAIL
Por diseño. El usuario que coincide con ADMIN_EMAIL se marca como protegido en cada arranque del servidor: el dashboard oculta el botón Deshabilitar para esa fila, y la API rechaza DELETE /users/:id y PUT /users/:id contra él con 403 Forbidden. Un trigger de base de datos también rechaza las instrucciones UPDATE directas que deshabilitarían la fila protegida.
Para rotar el administrador de arranque, cambia ADMIN_EMAIL en tu entorno y reinicia el servidor. El nuevo correo electrónico se hace upsert como protegido. El administrador anterior conserva el indicador de protección hasta que se elimine en la base de datos (generalmente está bien, ya que el correo anterior sigue siendo un administrador válido hasta que lo elimines explícitamente).
El dashboard no muestra eventos
- Confirma que la URL del servidor y la clave API son correctas en las variables de entorno del dashboard (
AGENTEYE_SERVER_URL,AGENTEYE_API_KEY). - La clave API del dashboard necesita permiso
events:read. - Confirma que los eventos realmente se han ingestado:
curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"
/errors está vacío pero /events muestra filas rojas
Las versiones más recientes del SDK emiten fallos como eventos agent_end / tool_result / hook_completed con outcome: "error" en el payload, en lugar de como una fila dedicada event_type: "error". La página /errors ahora coincide con ambos: cualquier fila que el stream de /events pinta en rojo (explícito event_type='error', payload outcome/status en el conjunto de fallos, is_error: true, o un campo error con valor verdadero) aparece en /errors. Si anteriormente veías “no hay errores en esta ventana” mientras había filas rojas en /events, actualiza el dashboard + servidor juntos (el filtro ampliado es errored=true en GET /events) y las dos vistas coincidirán.
/models, /tools o /hooks es lento o no carga en rangos de tiempo amplios
Síntoma: en una tabla de eventos grande (millones de filas), abrir /models, /tools o /hooks — o ampliar el rango de tiempo a 7d, 30d o all — hace que los gráficos giren y luego muestren un error de carga. El servidor registra un MEMORY_LIMIT_EXCEEDED de ClickHouse (Código 241) o un timeout de consulta para la solicitud latency_aggregate.
Causa: las versiones anteriores calculaban los agregados de latencia y distribución de estas páginas con una consulta que leía el payload JSON completo del evento sin procesar y emparejaba eventos de solicitud/respuesta con un ordenamiento y unión en memoria. La memoria máxima de la consulta crecía por tanto con el tamaño de la ventana, así que en un tenant ocupado un rango amplio podía superar el límite de memoria por consulta de ClickHouse.
Solución: actualiza a una versión que incluya esta corrección. El agregado ahora solo lee las columnas compactas promovidas y empareja eventos con una agregación en streaming, por lo que la memoria máxima ya no escala con el payload sin procesar — las ventanas amplias se mantienen dentro del límite de memoria y responden en una fracción del tiempo. La mejora es completamente del lado de la consulta: se aplica a todos los datos existentes en la siguiente carga de página, sin necesidad de re-ingestión ni relleno.
El dashboard no carga / página en blanco
Revisa los logs del contenedor del dashboard:AGENTEYE_SERVER_URL o AGENTEYE_API_KEY faltan o apuntan a un servidor inaccesible.
Análisis / telemetría del dashboard
El dashboard envía análisis de uso del producto anónimos a PostHog por defecto, enrutados a través de la propia ruta/ingest del dashboard (un proxy inverso a https://us.i.posthog.com). Enviarlos de forma directa significa que los bloqueadores de anuncios del navegador no los descartan. Esto es independiente de la funcionalidad principal del dashboard:
- Es el contenedor del dashboard (no el navegador) quien llega a PostHog. Si su acceso saliente a
https://us.i.posthog.comestá bloqueado, la telemetría falla silenciosamente; el dashboard funciona con normalidad y no se muestran errores a los usuarios. - No se incluyen datos de agentes, sesiones ni eventos; solo el uso de la interfaz del dashboard.
- Para deshabilitar la telemetría por completo, configura
AE_ANALYTICS_DISABLED=1en el contenedor del dashboard y reinicia. Ver Telemetry & privacy en la guía de despliegue.
Análisis / telemetría de la CLI
La CLIagenteye envía análisis de uso anónimos a PostHog por defecto: qué comandos se ejecutan, estado de éxito/salida y duración. Esto es independiente de la funcionalidad de la CLI:
- La máquina que ejecuta la CLI llega directamente a
https://us.i.posthog.com. Si su acceso saliente está bloqueado, la telemetría falla silenciosamente (el envío tiene un límite de tiempo, por lo que nunca retrasa un comando) y la CLI funciona con normalidad. - No se incluyen datos de agentes, sesiones ni eventos: los argumentos y valores de flags del comando (URL del dashboard, token, correo electrónico, IDs de sesión, filtros de consulta) nunca se envían.
- Para deshabilitarla, configura
AGENTEYE_ANALYTICS_DISABLED=1(o el inter-herramientasDO_NOT_TRACK=1) en el entorno de la CLI. Ver Telemetry & privacy en la guía de la CLI.
Problemas del asistente de IA
Ver enterprise-docs/assistant.md para la configuración completa.La burbuja del asistente no aparece
La burbuja está oculta a menos que todo lo siguiente sea verdad:- El usuario conectado tiene el permiso
agent:use. AGENTEYE_AGENT_URLestá configurado en el dashboard y el servicioagentes accesible.- Hay un endpoint de LLM configurado en el servicio
agent(ANTHROPIC_API_KEY, un gateway viaANTHROPIC_BASE_URL, o Bedrock/Vertex). Sin ninguno configurado, el agente reporta “not configured” y la burbuja permanece oculta.
curl http://agent:9100/health debería devolver {"status":"ok","llm_configured":true,...}.
El asistente dice que no puede leer algo
Las herramientas están restringidas por usuario. Si un usuario no tieneevaluations:read (o events:read, dashboards:read), las herramientas correspondientes no se ofrecen y el asistente dirá que no puede leer esos datos. Otorga el permiso de lectura correspondiente.
”assistant not configured” (HTTP 503) al enviar
El contenedoragent no tiene ningún endpoint de LLM configurado, o el AGENTEYE_AGENT_TOKEN del dashboard no coincide con el del agente. Configura ambos y reinicia.
El contenedor agent se reinicia / se queda sin memoria bajo carga
Cada conversación genera un proceso hijo de corta duración. Asegúrate de que el contenedor se ejecute con un proceso init (la imagen usa tini; en Compose configura init: true) y dale límites de memoria adecuados. Reduce AGENTEYE_AGENT_MAX_STEPS si es necesario.
Problemas de la CLI
agenteye falla al iniciar con ModuleNotFoundError: No module named 'click'
Una instalación nueva de la CLI agenteye en la versión 0.1.6 puede fallar al arrancar con:
click estuviera instalado indirectamente por typer; las versiones actuales de typer ya no lo incluyen, por lo que un entorno limpio termina sin el paquete. Actualiza a la versión 0.1.7 o superior, que depende de click directamente:
Problemas del SDK de Python
No aparecen archivos en $AGENTEYE_HOME/events/
El SDK almacena eventos en buffer y los vacía cada 500 ms por defecto. Si tu proceso termina antes del flush, los eventos pueden perderse. Llama a agenteye.configure(flush_interval=0.1) para un vaciado más rápido en scripts de corta duración, o asegúrate de que tu proceso se ejecute el tiempo suficiente para un ciclo de flush.
Si AGENTEYE_HOME está configurado, verifica que el SDK esté escribiendo en $AGENTEYE_HOME/events/ y no en ~/.agenteye/events/ (requiere SDK ≥ 0.0.1b5).
ValueError: Reserved field names cannot be used as custom fields
Los nombres timestamp, type y environment están reservados y no pueden usarse como campos personalizados. Pasarlos levanta:
session_id y agent_id son parámetros explícitos de la llamada al evento, no campos personalizados; pasar cualquiera de ellos nuevamente como campo personalizado levanta TypeError.
Problemas de monitoreo de salud
No llegan alertas a Slack (Robusta)
Las alertas de salud de Robusta son opcionales; no envía nada hasta que se instala y se apunta a un canal de Slack. Verifica el release y su sink:api_key / slack_channel de Slack no fueron configurados (o el token fue revocado); el api_key es un token de relay en la nube de Robusta (robusta integrations slack) pero el disableCloudRouting: true incluido necesita un bot token de Slack autohospedado (xoxb-…), o configura disableCloudRouting: false; el scope del sink excluye el namespace donde se ejecutan tus pods (los valores incluidos tienen alcance a agenteye); o aún no ha ocurrido ningún fallo. Fuerza una alerta de prueba dejando caer un pod:
El servidor sigue alternando entre NotReady
La sonda de preparación llega a /ready, que falla cuando Postgres o ClickHouse no son accesibles. Si el servidor alterna entre NotReady, una dependencia no está disponible de forma intermitente; revisa los pods de ClickHouse y Postgres y los valores de CLICKHOUSE_URL / DATABASE_URL del servidor. Confirma lo que reporta /ready:
/health, por lo que la alternancia de preparación no reiniciará el pod.
Problemas de monitoreo de certificados
El CronJob no envía notificaciones de Slack
El CronJobcert-renewal-check requiere una URL de webhook de Slack almacenada en un Secret. Verifica que exista:
El certificado de cliente expiró antes de recibir una notificación
El CronJob se ejecuta cada 12 horas. Si no ha estado en ejecución, verifica su estado:collector-mtls-secret.yaml regenerado en el/los clúster(es) que ejecutan tus colectores y reinícialos:
Problemas de copias de seguridad
agenteye-backup falla con “No space left on device”
El CronJob agenteye-backup vuelca Postgres + ClickHouse en un volumen de trabajo emptyDir llamado backup-tmp (por defecto 30Gi), luego transmite el archivo tar directamente a S3 — el archivo comprimido nunca se escribe de vuelta al espacio de trabajo, por lo que el espacio de trabajo solo necesita contener los volcados sin procesar, no los volcados más una segunda copia en disco del archivo. Un pod expulsado / No space left on device por tanto significa que los volcados sin procesar superan el tamaño del espacio de trabajo (el volcado de events de ClickHouse domina y crece con el tiempo). Revisa los logs del job fallido:
sizeLimit del emptyDir backup-tmp del CronJob por encima del total de tus volcados sin procesar, y asegúrate de que el almacenamiento efímero del nodo pueda realmente contenerlo (sizeLimit es un límite, no una reserva). Si los volcados superan el disco de un solo nodo, reemplaza el emptyDir con un PVC (EBS/PD) para backup-tmp, o comprime los volcados en el origen.
Las versiones anteriores escribían el.tar.gzen el mismo espacio de trabajo20Gique los volcados, por lo quevolcados + archivolo desbordaban y el pod se expulsaba antes de que la subida se ejecutara — lo que parece un fallo de S3 pero en realidad es de disco. Transmitir la subida elimina ese doble uso.
agenteye-backup falla al instalar curl
El job se ejecuta en la imagen postgres:16 e instala curl al arrancar para el volcado HTTP de ClickHouse. En un clúster sin acceso de salida a los espejos de paquetes de Debian, el paso apt-get falla. Permite ese acceso de salida desde el pod de backup, o incluye curl en una imagen de backup personalizada/espejada y referencíala en tu overlay.
agenteye-backup se ejecuta pero nada llega al almacenamiento de objetos
La base incluye un BACKUP_BUCKET real (ts-prod-agenteye/backups) y el ServiceAccount agenteye-backup. El job transmite el archivo a S3 (tar cz … | aws s3 cp - s3://…). Si el pod de backup no tiene acceso de escritura al bucket, la subida falla — y como el script se ejecuta bajo set -euo pipefail, un fallo en cualquier lugar de esa tubería falla todo el job en el paso upload en lugar de no-op silencioso (el trap EXIT del pod registra backup FAILED during step: upload). Este también es el paso al que llegas después de corregir una expulsión por espacio de trabajo, por lo que si las copias de seguridad fueron expulsadas anteriormente en el paso de archivo, verifica que la subida ahora funcione. Filtra los logs del job fallido en busca del error de acceso a S3:
BACKUP_BUCKET con un bucket de tu propiedad y anota el ServiceAccount agenteye-backup existente con acceso de escritura (IRSA / Workload Identity / Pod Identity). Ver la sección Backups de enterprise-docs/kubernetes-deployment.md.
Evaluaciones / sesiones / consultas respaldadas por ClickHouse
La barra lateral de la página /queries está vacía después de actualizar
Se esperan tres tablas (events, evaluations, agent_sessions). Si la barra lateral del SchemaBrowser está vacía después de la actualización, el servidor no pudo aplicar el DDL de ClickHouse al arrancar. Revisa los logs del servidor en busca de failed to apply CH DDL statement:
CrashLoopBackOff en lugar de una página de consultas rota silenciosamente, pero una aplicación parcial de DDL (una instrucción OK, las siguientes con 5xx) deja el esquema a medias. Reinicia el pod del servidor después de verificar que CH es accesible:
Las nuevas evaluaciones no aparecen en /sessions o /queries
Después de la actualización, las nuevas evaluaciones se escriben en ClickHouse, no en Postgres, y aparecen en /sessions (restringido a evaluations:read) y en /queries. Si no aparecen:
- Confirma que el pipeline del evaluador está habilitado (
EVALUATOR_ENDPOINTconfigurado en el servidor) y produciendo resultados finales; busca líneas de logevaluation_finalized. - Confirma que CH es accesible desde el servidor:
kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping. - Verifica puntualmente la tabla CH:
kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'.
Las consultas fallan bajo carga con “Memory limit exceeded”, o ClickHouse recibe OOMKilled
Síntoma: bajo carga pesada del dashboard/consultas, las páginas analíticas (el stream de eventos, /sessions, la vista de modelos/latencia, el editor SQL) empiezan a fallar o a agotar el tiempo de espera; el servidor alterna brevemente entre NotReady; y el pod de ClickHouse muestra un conteo de reinicios creciente. Esto es casi siempre un problema de memoria, no de CPU ni de disco.
Confirma que es memoria (no un problema de rendimiento que la replicación resolvería):
-
Verifica el pod en busca de muertes por falta de memoria:
Reason: OOMKilled/Exit Code: 137con un conteo de reinicios creciente es la señal. -
Pregunta a ClickHouse qué está rechazando:
Un conteo grande de
MEMORY_LIMIT_EXCEEDEDes la firma. El mensaje dice “maximum: N GiB” — ese N es0.9 × el límite de memoria del pod(elmax_server_memory_usage_to_ram_ratioendeploy/base/clickhouse/configmap.yaml). Si tus lecturas pesadas necesitan más que N, son rechazadas. -
Descarta las cosas que no son el problema — si la CPU, el conteo de partes y el disco son todos bajos, añadir réplicas/sharding sería un coste desperdiciado:
payload JSON sin procesar, ejecutan JSONExtract* sobre ella y usan FINAL — cada una puede necesitar varios GiB. Si las cachés configuradas (mark_cache_size + uncompressed_cache_size) son más grandes que el pod, se agravan: las cachés se cobran contra el mismo presupuesto y eliminan la memoria de las consultas.
Solución — escala la memoria de ClickHouse:
- Aumenta el límite de memoria de ClickHouse en tu overlay parcheando los
resourcesdel contenedor del StatefulSetclickhouse(el mismo mecanismo de overlay usado para losresourcesde los demás componentes). El presupuesto del servidor utilizable es0.9 × límite, por lo que un límite de6Gida ~5.4 GiB,16Gida ~14 GiB. Configura tambiénrequests.memorycon un valor base real, para que el planificador lo reserve. Aplicar esto recrea el pod de CH (réplica única → ~30–60s de tiempo de inactividad en análisis); hazlo en una ventana de bajo tráfico. - Mantén las cachés en
deploy/base/clickhouse/configmap.yamlproporcionales al límite — las cachés pequeñas (unos pocos cientos de MiB) son seguras en un pod pequeño; solo auméntalas junto con un aumento correspondiente del límite de memoria. Elmax_memory_usagepor consulta se configura explícitamente en el perfilusers.xml(ver la sección de nodo fijo a continuación) y se mantiene por debajo del límite a nivel de servidor (0.9 × límite) para que ninguna consulta individual pueda usar más RAM que la que tiene el contenedor. - Si el nodo en sí es el techo, verifica la memoria del host que ClickHouse puede ver:
Si eso es solo un poco por encima del límite del pod, mueve ClickHouse a un nodo más grande (optimizado para memoria) — a través de un selector/afinidad de nodo en tu overlay — antes de aumentar más el límite.
500 del dashboard a mitad de ejecución mientras ClickHouse sigue procesando — mantener las consultas en RAM y rechazar la rara que supera el presupuesto rápido (MEMORY_LIMIT_EXCEEDED, en menos de un segundo) es lo que restaura la carga. Ten en cuenta un detalle importante de ClickHouse para aplicar esto:
- Estas son configuraciones de perfil, y ClickHouse solo lee
<profiles>desdeusers_config(users.xml/users.d/*.xml) — nunca desdeconfig.d. Un bloque<profiles>colocado enconfig.d/agenteye.xmles ignorado silenciosamente (max_execution_time,max_memory_usage, etc. simplemente no se aplican). La configuración incluida por tanto las envía como una claveusers.xmlen el ConfigMapclickhouse-config, montada en/etc/clickhouse-server/users.d/agenteye.xml. - Los valores por defecto incluidos:
max_memory_usage(límite por consulta — una consulta no puede consumir todo el presupuesto del servidor),max_bytes_before_external_group_by/max_bytes_before_external_sort=0(derrame deshabilitado) para que las consultas permanezcan en RAM en lugar de arrastrarse en el disco lento, ymax_execution_time(guardia contra consultas desbocadas, alineado con el timeout de lectura del cliente del servidor). - Verifica que están activas (así también detectas el error de config.d):
Espera un
max_memory_usagedistinto de cero ymax_bytes_before_external_group_by = 0. Simax_memory_usagemuestra0/predeterminado, el perfil no se está aplicando — verifica que la configuración esté en un montajeusers.d, no enconfig.d.
max_memory_usage es rechazada (MEMORY_LIMIT_EXCEEDED) en lugar de completarse lentamente — en un disco lento ese rechazo rápido es preferible, porque una consulta con derrame superaría de todas formas el timeout del cliente y fallaría. Si tu disco de datos es rápido (SSD), puedes en cambio aumentar los umbrales max_bytes_before_external_* para permitir que las consultas grandes se derramen al disco y se completen.
Multi-tenencia (organizaciones)
Errores durante la actualización que habilita organizaciones (pods de servidor mixtos viejo/nuevo)
Síntoma: durante un despliegue progresivo de la versión que habilita organizaciones, algunas solicitudes fallan: los logs del servidor muestranthere is no unique or exclusion constraint matching the ON CONFLICT specification en la ruta api_keys, y/o los canales de alertas/Slack/webhook dejan de dispararse mientras el despliegue está en curso.
Causa: la actualización reemplaza el antiguo índice único de toda la instancia en api_keys(name) con índices parciales por organización, y mueve la configuración de canales de alerta (y default_user_permissions) fuera de la tabla global settings hacia org_settings por organización. Un pod de servidor antiguo aún emite ON CONFLICT (name) (ahora sin restricción coincidente) y aún lee la configuración del canal desde las filas antiguas de settings (ahora vacías). Los pods viejos y nuevos no pueden coexistir de forma segura para estas dos rutas.
Solución: no hagas un despliegue progresivo lento de esta actualización específica entre versiones mixtas. Realiza un cambio limpio: escala el servidor antiguo a cero (o usa una breve ventana de mantenimiento) y levanta la nueva versión junto con sus migraciones, en lugar de ejecutar réplicas antiguas y nuevas en paralelo. El tráfico normal y la ingesta se reanudan inmediatamente después del cambio; esto solo afecta la ventana de transición de versión.
El provisionamiento de una organización falla en CREATE USER / CREATE ROW POLICY, o una organización puede leer los datos de otra
Síntoma: crear una organización devuelve un error que menciona CREATE USER, CREATE ROW POLICY o “access management is disabled”; o, peor, los miembros de una organización ven los eventos/evaluaciones de otra organización en el editor SQL o en el asistente.
Causa: el aislamiento por organización se aplica mediante un usuario de ClickHouse dedicado + política de filas por organización. Esto requiere que la gestión de acceso SQL esté habilitada y que users_without_row_policies_can_read_rows=false en ClickHouse. Con la gestión de acceso desactivada, el provisionamiento no puede crear el usuario/política; con el valor predeterminado de la política de filas en su valor permisivo, un usuario que tiene SELECT pero ninguna política lee todas las filas (fail-open).
Solución: usa la configuración incluida en deploy/base/clickhouse/, que configura ambos. Si ejecutas tu propia configuración de ClickHouse, habilita la gestión de acceso SQL en el usuario interno del servidor y configura users_without_row_policies_can_read_rows=false (ver deploy/base/clickhouse/configmap.yaml), luego reinicia ClickHouse y vuelve a crear la organización con la CLI agenteye-orgctl (ver enterprise-docs/tenant-management.md).
Los usuarios de la organización pierden acceso a ClickHouse después de cambiar ORG_CH_SECRET
Síntoma: el editor SQL y el asistente de IA de repente devuelven fallos de autenticación de ClickHouse para todas las organizaciones, inmediatamente después de que se cambió ORG_CH_SECRET o se configuró de forma inconsistente entre réplicas.
Causa: la contraseña de ClickHouse de cada organización se deriva como un HMAC de ORG_CH_SECRET. Rotarla (o ejecutar réplicas con valores diferentes) invalida la credencial de ClickHouse almacenada de cada organización; la contraseña derivada ya no coincide con el usuario provisionado.
Solución: configura ORG_CH_SECRET con un valor único y robusto antes de provisionar una segunda organización y mantenlo estable e idéntico en todas las réplicas del servidor. La reconciliación al arrancar el servidor vuelve a provisionar el usuario de ClickHouse de cada organización desde el secreto actual al arrancar, por lo que un reinicio del servidor en todas las réplicas (con el secreto consistente) sana los usuarios huérfanos. Trata el valor como un secreto de larga duración; no lo rotas casualmente. Como red de seguridad, si ORG_CH_SECRET se deja en el valor de desarrollo predeterminado incorporado (es decir, sin configurar), la reconciliación al arrancar omite las organizaciones no predeterminadas y registra un error en lugar de reescribir sus credenciales de ClickHouse al valor de desarrollo conocido públicamente, para que una réplica que reinicia sin el secreto no pueda romper las demás réplicas. Configura el secreto de forma consistente y reinicia para provisionar esas organizaciones.
El asistente de IA devuelve 400 / se niega a chatear después de habilitar organizaciones
Síntoma: el dock del asistente carga pero cada mensaje vuelve como un error (HTTP400), y el agente registra una solicitud /chat sin organización rechazada.
Causa: el agente es consciente de la organización y falla de forma cerrada; rechaza un /chat que no lleva contexto de organización. Esto ocurre durante un despliegue de transición donde el agente se ha actualizado pero el dashboard que envía la solicitud aún no es consciente de la organización.
Solución: completa el despliegue para que el dashboard envíe el contexto de la organización (el estado final normal, sin necesidad de ningún flag). Para salvar la brecha mientras un dashboard no consciente de la organización habla con un agente consciente de la organización, configura AGENTEYE_AGENT_ALLOW_NO_ORG=1 en el servicio agent para que recurra a la organización default en lugar de rechazar, y elimínalo una vez que la actualización del dashboard aterrice. Ver la referencia de variables de entorno en enterprise-docs/assistant.md.
Auditorías
Una auditoría nunca se ejecuta (la próxima ejecución sigue desplazándose, sin historial de ejecución)
Síntoma: la página de auditoría muestra última ejecución: nunca, opróxima ejecución sigue moviéndose al futuro sin que aparezca ninguna fila en el historial de ejecución.
Causa: la auditoría está deshabilitada (las auditorías deshabilitadas no tienen entrada en la cola), o los trabajadores de auditoría del servidor están fallando al reclamar trabajo.
Solución: confirma que la auditoría está habilitada (el botón ejecutar ahora lo requiere). Luego revisa los logs del servidor en busca de audits pipeline started al arrancar y de errores audits: — una línea claim_due failed apunta a conectividad con Postgres. AUDIT_WORKERS por defecto es 1; debe ser ≥ 1 para que se ejecute cualquier auditoría.
Las ejecuciones de auditoría tienen éxito pero no encuentran nada
Síntoma: el historial de ejecución muestrasucceeded con findings: 0 aunque /errors claramente muestra fallos.
Causa: la ventana de análisis no cubre los fallos, o los filtros de alcance los excluyen.
Solución: verifica la ventana de la ejecución (window_from → window_to) contra cuándo ocurrieron los fallos — en el modo since_last cada ejecución solo analiza desde la última ejecución exitosa, por lo que los fallos más antiguos solo los ve la primera ejecución o una auditoría con ventana fixed. Amplía scope (entornos / IDs de agente). Las estadísticas de ejecución muestran policy_hits (cuántas políticas deterministas se activaron) e improvements (cuántas registró la investigación de IA) — si ambos son 0, la ventana/alcance genuinamente no encontró nada.
La ejecución dice analysis_unavailable y solo produce hallazgos de políticas
Síntoma: las estadísticas de ejecución incluyen analysis_unavailable y los únicos hallazgos son kind: policy; no aparecen mejoras de IA.
Causa: la investigación agente no pudo ejecutarse: el servidor no puede llegar al servicio de agente (AGENTEYE_AGENT_URL / AGENTEYE_AGENT_TOKEN no configurados en el servidor — la auditoría reutiliza la conexión del asistente), el servicio de asistente no tiene LLM configurado, o la llamada tuvo error/timeout (la cadena analysis_unavailable tiene el detalle). El paso de políticas deterministas es el mínimo — siempre se ejecuta — por lo que la auditoría aún tiene éxito con sus hallazgos de seguridad.
Solución: configura AGENTEYE_AGENT_URL (p. ej. http://agent:9100) y AGENTEYE_AGENT_TOKEN en el servidor — los mismos valores que ya usa el asistente del dashboard (los manifiestos/compose incluidos ahora los conectan) — y configura un LLM en el servicio de asistente (ver assistant.md), luego vuelve a ejecutar. Una investigación grande puede necesitar un AUDIT_LLM_TIMEOUT_MS más grande (servidor) — mantenlo por encima del AGENTEYE_AUDIT_TIMEOUT_MS del agente.
El sandbox de código de auditoría está deshabilitado (sandbox_available: false)
Síntoma: el /health del agente muestra sandbox_available: false, y las ejecuciones de auditoría indican que el sandbox no está disponible; la IA investiga solo con SQL.
Causa: el sandbox bubblewrap en el pod necesita espacios de nombres de usuario sin privilegios, que el perfil seccomp del pod o el kernel del nodo está bloqueando.
Solución: configura seccompProfile: Unconfined (k8s) o security_opt: [seccomp:unconfined] (compose) en el agente, y confirma que el kernel del nodo permite espacios de nombres de usuario sin privilegios (algunas imágenes gestionadas, p. ej. GKE COS, los deshabilitan). Donde no puedas habilitarlo, esto es lo esperado y seguro — el auditor degrada automáticamente a solo SQL. Ver deployment.md.
El informe de auditoría por correo electrónico no se entrega
Síntoma: una auditoría encontró nuevos hallazgos pero no llegó ningún correo electrónico. Causa: la auditoría no tiene ningún canal de correo electrónico adjunto, el correo electrónico está deshabilitado a nivel de organización enalerts.enabled_channels, no hay destinatarios, o SMTP no está configurado.
Solución: adjunta un canal de correo electrónico a la auditoría, asegúrate de que email esté en alerts.enabled_channels, configura destinatarios (en el canal o mediante alerts.email_default_recipients), y configura SMTP (el mismo transporte que usan los correos de alertas + OTP). El correo solo se envía cuando una ejecución produce al menos un hallazgo nuevo.
Un patrón silenciado o descartado conserva su página de hallazgo antigua pero nunca se reclasifica
Síntoma: después de silenciar un hallazgo, las ejecuciones posteriores nunca vuelven a mostrar ese patrón — aunque siga ocurriendo. Causa: ese es el comportamiento diseñado: silenciar/descartar son supresiones duraderas vinculadas a la huella digital del patrón. Solución: abre el hallazgo y usa reopen para borrar la supresión; la próxima ejecución clasificará el patrón de nuevo. Usa resolve (no silenciar) para los patrones “corregidos” sobre los que querrías enterarte si regresan.Obtener ayuda
Contacta asupport@exosphere.host con:
- Tu versión de AgentEye (del tag de la versión)
- Los logs relevantes del contenedor (
docker logs <container>) - Una descripción del problema y lo que ya has intentado

