Zum Hauptinhalt springen
Dieser Leitfaden ordnet die häufigsten Symptome in der Produktionsumgebung einer konkreten Diagnose und Lösung zu, damit Sie Vorfälle mit vorhandenen Werkzeugen beheben können – ohne zusätzliche Observability-Infrastruktur aufbauen zu müssen. Er behandelt Server, Collector, Dashboard, KI-Assistent, Python SDK, Gesundheits- und Zertifikatsüberwachung, Backups, ClickHouse-basierte Analytics und Multi-Tenancy. Dashboard-Seiten sind unter /<org-slug>/… org-scoped, und der Ereignisstrom ist die Org-Startseite (/<org-slug>/). Seitennamen in diesem Leitfaden (z. B. /sessions, /queries) beziehen sich auf diese org-scoped Routen.

Logs anzeigen

AgentEye bündelt keinen Logging- oder Monitoring-Stack. Sowohl der Server als auch das Dashboard schreiben strukturierte Logs nach stdout, sodass Sie diese direkt mit kubectl oder docker lesen können – kein Aggregator erforderlich.

Kubernetes

Live-Logs für Server und Dashboard verfolgen:
Nützliche Varianten:
ZielBefehl
Letzte 200 Zeilen (kein Follow)kubectl logs -n agenteye -l app=server --tail=200 --timestamps
Logs des vorherigen Absturzeskubectl logs -n agenteye <pod-name> --previous
Alle Replikas gleichzeitig verfolgenkubectl logs -n agenteye -l app=server --max-log-requests=10 -f
Postgres (StatefulSet)kubectl logs -n agenteye postgres-0 -f

Docker Compose

Eine einzelne Anfrage über Dashboard und Server korrelieren

Jede Dashboard-Anfrage erhält eine request_id, die über den x-request-id-Header an den Server weitergeleitet wird. Der Server gibt sie in seinen Antwort-Headern und in jeder Log-Zeile für diese Anfrage wieder aus. Um eine Anfrage von Anfang bis Ende zu verfolgen:
  1. ID aus dem Antwort-Header erfassen, z. B.:
  2. Logs beider Pods nach dieser ID durchsuchen:
Sie sehen die proxy passthrough-, withAuth: authorized- und upstream response-Zeilen des Dashboards zusammen mit dem http request received / http request completed-Paar des Servers – alle mit derselben request_id.

JSON-Logs und jq

Setzen Sie AE_LOG_JSON=1 am Dashboard (standardmäßig aktiviert, wenn NODE_ENV=production), um ein JSON-Objekt pro Zeile auszugeben. Dann strukturell filtern:
Der Rust-Server gibt key=value-Tracing-Paare aus, die sich gut mit grep ohne jq durchsuchen lassen:

Ausführlichkeit erhöhen

KomponenteEnv-VariableBeispiel
ServerRUST_LOGRUST_LOG=debug oder RUST_LOG=agenteye_server=debug,info
DashboardAE_LOG_LEVELAE_LOG_LEVEL=debug
debug am Server fügt eine api key authenticated-Zeile pro Authentifizierung hinzu. debug am Dashboard fügt upstream request-, session validated- und proxy passthrough-Zeilen hinzu.

Log-Aufbewahrung

Container-stdout ist flüchtig; kubelet rotiert Log-Dateien (Standard ca. 10 MiB pro Container) und hält eine kleine Anzahl auf der Festplatte. Sobald ein Pod gelöscht wird, sind die Logs verschwunden. Wenn Sie eine längere Aufbewahrung oder pod-übergreifende Suche benötigen, richten Sie Ihren Cluster auf einen Log-Collector (Loki, CloudWatch, Cloud Logging, Datadog usw.) ein, der /var/log/containers/ verfolgt. AgentEye schreibt keine bestimmte Lösung vor.

Authentifizierungsprobleme

docker pull schlägt fehl mit “unauthorized”

Stellen Sie sicher, dass Sie Docker mit Ihrem AGENTEYE_TOKEN gegen GHCR authentifiziert haben:
Das Token muss die Berechtigung read:packages für die agenteye-enterprise-Organisation haben. Kontaktieren Sie support@exosphere.host, wenn Ihr Token nicht funktioniert.

gh release download gibt 404 oder 401 zurück

  • Bestätigen Sie, dass AGENTEYE_TOKEN in Ihrer Shell exportiert ist: echo $AGENTEYE_TOKEN
  • Bestätigen Sie, dass Sie GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ... verwenden (die gh-CLI liest GITHUB_TOKEN)
  • Das Token benötigt contents:read auf agenteye-enterprise/releases

Server-Probleme

Server schlägt fehl mit “invalid port number”

Das POSTGRES_PASSWORD (oder eine andere Anmeldeinformation) enthält URL-Sonderzeichen (/, +, =), die das Parsen der DATABASE_URL stören. Generieren Sie das Passwort mit Hex-Kodierung neu:
Aktualisieren Sie dann das Kubernetes-Secret und das Passwort in Postgres (oder erstellen Sie die .env für Docker Compose neu) und starten Sie den Server neu. Siehe die vollständigen Schritte in enterprise-docs/kubernetes-deployment.md § “PostgreSQL credentials”.

Server beendet sich sofort beim Start

Überprüfen Sie die Container-Logs:
Häufige Ursachen:
  • DATABASE_URL nicht gesetzt oder fehlerhaft: Der Server protokolliert den Fehler und beendet sich.
  • Postgres ist nicht erreichbar: Bestätigen Sie, dass der Postgres-Container oder die verwaltete DB läuft und Host/Port korrekt sind.
  • Migrationen fehlgeschlagen: Prüfen Sie die Logs auf SQL-Fehler.

GET /health gibt non-200 zurück oder läuft ab

Der Server führt beim ersten Start möglicherweise noch Migrationen durch. Warten Sie einige Sekunden und versuchen Sie es erneut:
Wenn das Problem anhält, prüfen Sie docker logs agenteye-server auf Fehler.

GET /ready gibt 503 zurück

/ready ist der Readiness-Probe: Er gibt 503 zurück, wenn der Server Postgres oder ClickHouse nicht erreichen kann. Der Body benennt die fehlschlagende Abhängigkeit:
Beheben Sie die als down gemeldete Abhängigkeit: Ist der ClickHouse-/Postgres-Pod Running? Ist CLICKHOUSE_URL / DATABASE_URL korrekt und erreichbar? In Kubernetes liest der Pod NotReady, bis /ready sich erholt; das ist erwartet und genau das Signal, auf das die Gesundheitsüberwachung alarmiert. Redis ist niemals eine Ursache: Es wird gemeldet, verursacht aber keinen Readiness-Fehler.

Collector gibt 401 Unauthorized zurück

Der API-Schlüssel des Collectors hat keine events:add-Berechtigung, oder der Schlüssel wurde deaktiviert. Erstellen Sie einen neuen Schlüssel mit der richtigen Berechtigung:

Authentifizierte Anfragen sind plötzlich langsam (~200ms statt ~5ms)

Dies ist das Symptom, wenn Redis ausgefallen ist, während REDIS_URL gesetzt ist. Jeder Cache-Aufruf läuft nach 100ms ab und fällt dann auf Postgres zurück; auf Auth- und OTP-Pfaden macht die Anfrage zwei solche Fallbacks. Bestätigen in den Server-Logs:
Lösung:
  1. redis-cli -h <your-redis> ping um zu bestätigen, dass Redis im Cluster-Netzwerk erreichbar ist.
  2. Wenn Redis kurz ausgefallen war und jetzt wieder läuft, starten Sie die Server-Pods neu. Der redis::aio::ConnectionManager stellt die Verbindung nach einem Verbindungsabbruch nicht zuverlässig wieder her; ein Pod-Neustart nimmt die neue Verbindung sauber auf. Dasselbe gilt für das Dashboard.
  3. Wenn Sie Redis derzeit nicht betreiben möchten, entfernen Sie REDIS_URL aus dem Deployment und starten Sie neu. Beide Dienste laufen ohne Cache (Korrektheit bleibt erhalten; Latenz kehrt zum Pre-Redis-Ausgangswert zurück).

Server meldet OTP request rate-limited in den Logs, aber der Benutzer sagt, er hat es nur einmal versucht

Prüfen Sie, ob Redis unerreichbar war. Der Fallback-Pfad verwendet SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes', der zuvor generierte OTP-Zeilen sieht. Wenn der Benutzer eine Stunde lang auf “Erneut senden” geklickt hat, kann das 15-Minuten-Fenster noch ≥5 Codes enthalten. Lösung: entweder warten, bis das Fenster abläuft, oder DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes' (Operator-Konsole).

Ich habe ALLOWED_EMAILS / SESSION_TTL_SECS / OTP_TTL_SECS geändert und neu gestartet; nichts hat sich geändert

Diese Env-Variablen sind nur beim ersten Start als Seeds gedacht. Sobald die settings-Tabelle eine Zeile für den entsprechenden Schlüssel hat, ist diese Zeile die Quelle der Wahrheit; die Env-Variable wird nur beim ersten Start gelesen und bei jedem nachfolgenden Neustart ignoriert. Um sie nach dem ersten Start zu ändern, melden Sie sich am Dashboard an und bearbeiten Sie sie unter /settings. Die Änderung gilt innerhalb von Sekunden für alle Replikas; kein Neustart erforderlich. Wenn Sie einen erneuten Seed aus der Env erzwingen müssen (selten, typischerweise nur in der Entwicklung nützlich), führen Sie DELETE FROM settings WHERE key = '<key>' aus und starten Sie den Server neu. Der Bootstrap nimmt den aktuellen Env-Variablenwert beim nächsten Start auf. Das Bearbeiten über /settings ist der unterstützte Weg in der Produktion.

Collector-Probleme

Collector startet, aber Ereignisse erscheinen nicht im Dashboard

  1. Bestätigen Sie, dass der Collector läuft: systemctl status agenteye-collector (Linux) oder prüfen Sie den Prozess.
  2. Bestätigen Sie, dass AGENTEYE_URL auf http(s)://your-server-host:8080/events zeigt (Hinweis: /events-Pfad).
  3. Führen Sie einen einmaligen Flush aus, um sofortige Ausgabe zu sehen:
  4. Prüfen Sie, ob das Python SDK tatsächlich Dateien schreibt: ls ${AGENTEYE_HOME:-~/.agenteye}/events/
  5. Wenn Dateien in ${AGENTEYE_HOME:-~/.agenteye}/failed/ vorhanden sind, schlagen die Uploads fehl. Prüfen Sie die Collector-Logs auf den Fehler – wahrscheinlich ein 4xx (falscher Schlüssel oder URL) oder ein Netzwerkproblem.

Dateien häufen sich in $AGENTEYE_HOME/events/ an und werden nicht hochgeladen

  • Der Collector läuft möglicherweise nicht. Starten Sie ihn: agenteye-collector start; er leert beim Start automatisch vorhandene Ereignisse.
  • Collector-Zustand prüfen: agenteye-collector health
  • Der Collector läuft möglicherweise, kann aber den Server nicht erreichen. Prüfen Sie die Firewall-Regeln zwischen Collector- und Server-Hosts.

Dateien in $AGENTEYE_HOME/failed/

Dateien werden nach Erschöpfung aller Wiederholungsversuche (Standard: 5 Versuche mit exponentiellem Backoff) nach failed/ verschoben. Das bedeutet entweder:
  • Der Server hat einen 4xx-Fehler zurückgegeben (falscher Schlüssel, falsche URL oder Payload-Problem)
  • Der Server war während des gesamten Wiederholungsfensters nicht erreichbar
Beheben Sie das zugrunde liegende Problem und stellen Sie dann manuell erneut in die Warteschlange:

Collector meldet bei jedem Upload network error (TLS-Handshake schlägt fehl)

Wenn curl -k gegen AGENTEYE_URL erfolgreich ist, aber das Collector-Binary jeden Upload mit error sending request for url (...) fehlschlagen lässt, präsentiert der AgentEye-Server ein TLS-Zertifikat, das nicht von einer öffentlich vertrauenswürdigen CA signiert ist. Der Produktionspfad ist der ACME-Ingest-Hostname, der in deploy/base/certificates/domain.env konfiguriert ist (siehe kubernetes-deployment.md Phase 3.1 / 4.2). Sobald INGEST_DOMAIN auf den öffentlichen Traefik-LB auflöst und cert-manager das Let’s Encrypt-Zertifikat ausgestellt hat, verifizieren Collectors das Server-Zertifikat gegen den System-Vertrauensspeicher ohne AGENTEYE_TLS_CA; entfernen Sie es aus Ihrer Collector-Konfiguration, falls es gegen ein älteres selbstsigniertes Deployment gesetzt war. Symptom: Collector funktionierte gestern, schlägt heute nach ~90 Tagen fehl. Das bedeutet, dass das Deployment noch den Legacy-selfsigned-Aussteller für ingest-tls verwendet. Das 90-Tage-Zertifikat wurde rotiert und die gepinnte CA-Datei ist veraltet. Dauerhaft beheben, indem Sie den Cluster auf den ACME-Aussteller umstellen (Phase 3.1 des Deployment-Leitfadens). Kurzfristige Lösung: das aktuelle Server-Zertifikat neu extrahieren und AGENTEYE_TLS_CA aktualisieren:
AGENTEYE_TLS_CA fügt einen zusätzlichen Vertrauensanker hinzu; die standardmäßigen öffentlichen Roots werden weiterhin vertraut.

ingest-tls-Zertifikat bleibt nach dem Deploy Ready: False

Schauen Sie sich Events und den referenzierten Order / Challenge an. Häufige Ursachen:
  • DNS löst nicht auf den öffentlichen LB auf. Der HTTP-01-Validator kann INGEST_DOMAIN nicht erreichen. Mit dig +short INGEST_DOMAIN prüfen; es sollte auf dieselbe Adresse wie die EXTERNAL-IP des traefik-public-LoadBalancers auflösen. cert-manager wiederholt automatisch, sobald DNS propagiert; das Zertifikat muss nicht gelöscht werden.
  • Port 80 am Load Balancer / Security Group blockiert. HTTP-01 erfordert, dass Port 80 von Let’s Encrypts öffentlichen Validatoren erreichbar ist. Wenn ein vorgeschaltetes WAF oder eine SG :80 einschränkt, öffnen Sie es (die Traefik-Konfiguration leitet zu HTTPS weiter, aber Boulder folgt der Umleitung und akzeptiert die Antwort).
  • dnsNames nicht ersetzt. Wenn kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}' INGEST_DOMAIN_PLACEHOLDER anzeigt, haben Sie den domain.env-Schritt übersprungen; erstellen Sie es aus domain.env.example und wenden Sie es erneut an.
  • Rate-Limit von Let’s Encrypt. Wiederholte fehlgeschlagene Orders für denselben Hostnamen lösen die Limits für doppelte Zertifikate oder fehlgeschlagene Validierungen aus. Warten Sie mindestens eine Stunde vor dem erneuten Versuch; prüfen Sie den Order-Status auf die genaue Rate-Limit-Meldung.

dashboard-tls-Zertifikat bleibt Ready: False / Browser zeigt noch eine Warnung

Gleicher Diagnoseablauf wie bei ingest-tls oben (kubectl describe certificate dashboard-tls -n agenteye); DNS-, Port-80-, Platzhalter- und Rate-Limit-Ursachen gelten alle, plus zwei Dashboard-spezifische:
  • DASHBOARD_DOMAIN löst auf den falschen LoadBalancer auf. Es muss auf den Dashboard-Traefik-LB zeigen, nicht auf den öffentlichen Ingest-LB. Mit dig +short den Hostnamen prüfen und mit der Dashboard-LB-Adresse vergleichen.
  • Die Dashboard-Traefik-Instanz kann die Challenge nicht bereitstellen. Sie muss mit der gebündelten Dashboard-Values-Datei installiert sein, die einen bereichsbeschränkten Ingress-Provider für den HTTP-01-Solver von cert-manager aktiviert. Ohne ihn ist der Solver nicht erreichbar und der Order bleibt für immer pending. Aktualisieren Sie die Instanz mit den bereitgestellten Values; die ausstehende Challenge wird dann von selbst abgeschlossen.
  • Der LoadBalancer war IP-beschränkt. Source-Ranges gelten auch für Port 80, was Let’s Encrypts Validatoren blockiert – sowohl bei der ersten Ausstellung als auch bei jeder ~75-tägigen Erneuerung. Öffnen Sie den LB erneut oder koordinieren Sie einen DNS-01-Solver mit dem Support, bevor Sie ihn sperren.
Während die Ausstellung fehlschlägt, stellt das Dashboard weiterhin sein vorheriges Zertifikat bereit (oder das Ingress-Standard-Zertifikat bei einer Neuinstallation) – der Zugang ist durch eine Browser-Warnung beeinträchtigt, aber nie unterbrochen.

CLI überspringt TLS-Verifizierung noch, nachdem das Dashboard ein vertrauenswürdiges Zertifikat erhalten hat

--insecure wird bei der Anmeldung in cli.json gespeichert. Sobald das Dashboard ein öffentlich vertrauenswürdiges Zertifikat bereitstellt, melden Sie sich erneut mit agenteye --base-url https://<your-dashboard-domain> --secure login an; die Verifizierung wird wieder aktiviert gespeichert und die Startup-Warnung verschwindet.

Dashboard-Probleme

ADMIN_EMAIL-Benutzer kann nicht deaktiviert oder bearbeitet werden

Dies ist by Design. Der Benutzer, der ADMIN_EMAIL entspricht, wird bei jedem Server-Start als geschützt markiert: Das Dashboard blendet die Deaktivieren-Schaltfläche für diese Zeile aus, und die API lehnt DELETE /users/:id und PUT /users/:id dagegen mit 403 Forbidden ab. Ein Datenbank-Trigger lehnt auch direkte UPDATE-Anweisungen ab, die die geschützte Zeile deaktivieren würden. Um den Bootstrap-Admin zu rotieren, ändern Sie ADMIN_EMAIL in Ihrer Umgebung und starten Sie den Server neu. Die neue E-Mail wird als geschützt upserted. Der vorherige Admin behält das geschützte Flag, bis es in der Datenbank gelöscht wird (in der Regel in Ordnung, da die vorherige E-Mail ein gültiger Admin bleibt, bis Sie sie explizit entfernen).

Dashboard zeigt keine Ereignisse

  1. Bestätigen Sie, dass die Server-URL und der API-Schlüssel in den Umgebungsvariablen des Dashboards korrekt sind (AGENTEYE_SERVER_URL, AGENTEYE_API_KEY).
  2. Der Dashboard-API-Schlüssel benötigt die Berechtigung events:read.
  3. Bestätigen Sie, dass tatsächlich Ereignisse aufgenommen wurden: curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"

/errors ist leer, aber /events zeigt rote Zeilen

Neuere SDK-Versionen senden Fehler als agent_end- / tool_result- / hook_completed-Ereignisse mit outcome: "error" im Payload statt als dedizierte event_type: "error"-Zeile. Die /errors-Seite erkennt jetzt beides: Jede Zeile, die der /events-Stream rot färbt (explizites event_type='error', Payload outcome/status in der Fehler-Menge, is_error: true oder ein wahrer error-Feld), erscheint in /errors. Wenn Sie zuvor “keine Fehler in diesem Zeitfenster” sahen, während rote Zeilen in /events sichtbar waren, aktualisieren Sie Dashboard und Server zusammen (der erweiterte Filter ist errored=true auf GET /events) und die beiden Ansichten stimmen überein.

/models, /tools oder /hooks ist langsam oder schlägt bei breiten Zeitbereichen fehl

Symptom: Bei einer großen Ereignistabelle (Millionen von Zeilen) drehen sich beim Öffnen von /models, /tools oder /hooks – oder beim Erweitern des Zeitbereichs auf 7d, 30d oder all – die Charts und zeigen dann einen Ladefehler. Der Server protokolliert ein ClickHouse-MEMORY_LIMIT_EXCEEDED (Code 241) oder einen Query-Timeout für die latency_aggregate-Anfrage. Ursache: Ältere Builds berechneten die Latenz- und Verteilungs-Rollups dieser Seiten mit einer Abfrage, die den vollständigen rohen Ereignis-payload las und Anfrage-/Antwort-Ereignisse mit einem In-Memory-Sortier-und-Join paarte. Der Query-Spitzenspeicher wuchs daher mit der Fenstergröße, sodass bei einem stark ausgelasteten Tenant ein breiter Bereich die Pro-Query-Speichergrenze von ClickHouse überschreiten konnte. Lösung: Auf einen Build aktualisieren, der diesen Fix enthält. Der Rollup liest jetzt nur die kompakten promoted Columns und paart Ereignisse mit einer Streaming-Aggregation, sodass der Spitzenspeicher nicht mehr mit dem rohen Payload skaliert – breite Fenster bleiben deutlich innerhalb der Speichergrenze und werden in einem Bruchteil der Zeit zurückgegeben. Die Verbesserung ist rein query-seitig: Sie gilt für alle vorhandenen Daten beim nächsten Seitenaufruf, ohne Re-Ingest oder Backfill.

Dashboard schlägt beim Laden fehl / leere Seite

Prüfen Sie die Dashboard-Container-Logs:
Die häufigste Ursache ist, dass AGENTEYE_SERVER_URL oder AGENTEYE_API_KEY fehlt oder auf einen nicht erreichbaren Server zeigt.

Dashboard-Analytics / Telemetrie

Das Dashboard sendet standardmäßig anonyme Produktnutzungs-Analytics an PostHog, geleitet über den eigenen /ingest-Pfad des Dashboards (ein Reverse Proxy zu https://us.i.posthog.com). Die First-Party-Weiterleitung verhindert, dass Browser-Werbeblocker sie abfangen. Dies ist unabhängig von der Kernfunktionalität des Dashboards:
  • Der Dashboard-Container (nicht der Browser) ist derjenige, der PostHog erreicht. Wenn sein ausgehender Zugriff auf https://us.i.posthog.com blockiert ist, schlägt die Telemetrie lautlos fehl; das Dashboard funktioniert normal und es werden keine Fehler an Benutzer weitergegeben.
  • Es werden niemals Agent-, Sitzungs- oder Ereignisdaten übermittelt, nur Dashboard-UI-Nutzung.
  • Um die Telemetrie vollständig zu deaktivieren, setzen Sie AE_ANALYTICS_DISABLED=1 am Dashboard-Container und starten Sie neu. Siehe Telemetry & privacy im Deployment-Leitfaden.

CLI-Analytics / Telemetrie

Die agenteye-CLI sendet standardmäßig anonyme Nutzungs-Analytics an PostHog: welche Befehle ausgeführt werden, Erfolgs-/Exit-Status und Dauer. Dies ist unabhängig von der CLI-Funktionalität:
  • Der Rechner, auf dem die CLI läuft, erreicht https://us.i.posthog.com direkt. Wenn sein ausgehender Zugriff blockiert ist, schlägt die Telemetrie lautlos fehl (das Senden ist zeitlich begrenzt, verzögert also keinen Befehl) und die CLI funktioniert normal.
  • Es werden niemals Agent-, Sitzungs- oder Ereignisdaten übermittelt: Befehls-Argumente und Flag-Werte (Dashboard-URL, Token, E-Mail, Sitzungs-IDs, Query-Filter) werden niemals gesendet.
  • Um es zu deaktivieren, setzen Sie AGENTEYE_ANALYTICS_DISABLED=1 (oder das tool-übergreifende DO_NOT_TRACK=1) in der CLI-Umgebung. Siehe Telemetry & privacy im CLI-Leitfaden.

KI-Assistent-Probleme

Siehe enterprise-docs/assistant.md für die vollständige Einrichtung.

Die Assistent-Blase erscheint nicht

Die Blase ist ausgeblendet, es sei denn, alle folgenden Bedingungen sind erfüllt:
  • Der angemeldete Benutzer hat die Berechtigung agent:use.
  • AGENTEYE_AGENT_URL ist am Dashboard gesetzt und der agent-Dienst ist erreichbar.
  • Ein LLM-Endpunkt ist am agent-Dienst konfiguriert (ANTHROPIC_API_KEY, ein Gateway über ANTHROPIC_BASE_URL oder Bedrock/Vertex). Ohne Konfiguration meldet der Agent “not configured” und die Blase bleibt ausgeblendet.
Prüfen Sie den Zustand des Agents vom Dashboard-Host aus: curl http://agent:9100/health sollte {"status":"ok","llm_configured":true,...} zurückgeben.

Der Assistent sagt, er kann etwas nicht lesen

Tools sind pro Benutzer freigegeben. Wenn einem Benutzer evaluations:read (oder events:read, dashboards:read) fehlt, werden die entsprechenden Tools nicht angeboten und der Assistent sagt, er kann diese Daten nicht lesen. Gewähren Sie die entsprechende Leseberechtigung.

”assistant not configured” (HTTP 503) beim Senden

Der agent-Container hat keinen LLM-Endpunkt konfiguriert, oder das AGENTEYE_AGENT_TOKEN des Dashboards stimmt nicht mit dem des Agents überein. Setzen Sie beides und starten Sie neu.

Der agent-Container startet neu / OOMs unter Last

Jedes Gespräch spawnt einen kurzlebigen Kindprozess. Stellen Sie sicher, dass der Container mit einem Init-Prozess läuft (das Image verwendet tini; in Compose setzen Sie init: true) und geben Sie ihm ausreichende Speicherlimits. Reduzieren Sie AGENTEYE_AGENT_MAX_STEPS bei Bedarf.

CLI-Probleme

agenteye startet nicht mit ModuleNotFoundError: No module named 'click'

Eine frische Installation der agenteye-CLI in Version 0.1.6 kann beim Start abstürzen mit:
0.1.6 verlässt sich darauf, dass click indirekt von typer installiert wird; aktuelle typer-Releases ziehen es nicht mehr rein, sodass einer sauberen Umgebung das Paket fehlt. Aktualisieren Sie auf 0.1.7 oder neuer, was direkt von click abhängt:
Siehe enterprise-docs/cli.md für Installationshinweise.

Python SDK-Probleme

Keine Dateien erscheinen in $AGENTEYE_HOME/events/

Das SDK puffert Ereignisse und leert standardmäßig alle 500 ms. Wenn Ihr Prozess vor dem Leeren beendet wird, können Ereignisse verloren gehen. Rufen Sie agenteye.configure(flush_interval=0.1) für schnelleres Leeren in kurzlebigen Skripten auf, oder stellen Sie sicher, dass Ihr Prozess lange genug für einen Flush-Zyklus läuft. Wenn AGENTEYE_HOME gesetzt ist, prüfen Sie, ob das SDK nach $AGENTEYE_HOME/events/ und nicht nach ~/.agenteye/events/ schreibt (erfordert SDK ≥ 0.0.1b5).

ValueError: Reserved field names cannot be used as custom fields

Die Namen timestamp, type und environment sind reserviert und können nicht als benutzerdefinierte Felder verwendet werden. Das Übergeben eines davon löst aus:
Benennen Sie das betreffende benutzerdefinierte Feld um. Beachten Sie, dass session_id und agent_id explizite Parameter des Ereignisaufrufs sind, keine benutzerdefinierten Felder; das erneute Übergeben eines davon als benutzerdefiniertes Feld löst TypeError aus.

Gesundheitsüberwachungs-Probleme

Keine Alerts in Slack ankommen (Robusta)

Robusta-Gesundheitsalarme sind opt-in; es wird nichts gesendet, bis es installiert und auf einen Slack-Kanal ausgerichtet ist. Release und Sink prüfen:
Häufige Ursachen: der Slack-api_key / slack_channel wurde nicht gesetzt (oder das Token wurde widerrufen); der api_key ist ein Robusta Cloud-Relay-Token (robusta integrations slack), aber das gebündelte disableCloudRouting: true benötigt ein selbst gehostetes Slack-Bot-Token (xoxb-…), oder setzen Sie disableCloudRouting: false; der Sink-scope schließt den Namespace aus, in dem Ihre Pods laufen (die gebündelten Values begrenzen auf agenteye); oder es ist noch kein Fehler aufgetreten. Erzwingen Sie einen Test-Alert, indem Sie einen Pod herunterfahren:
Siehe enterprise-docs/health-monitoring.md für Installation und Konfiguration.

Server flattert dauerhaft NotReady

Der Readiness-Probe trifft /ready, der fehlschlägt, wenn Postgres oder ClickHouse nicht erreichbar ist. Wenn der Server in und aus NotReady wechselt, ist eine Abhängigkeit zeitweise nicht verfügbar; prüfen Sie die ClickHouse- und Postgres-Pods sowie die CLICKHOUSE_URL / DATABASE_URL des Servers. Prüfen Sie, was /ready meldet:
Dieser Probe ist bewusst tolerant (ein großzügiger Fehlerschwellenwert), daher deutet anhaltendes Flattern auf ein echtes Abhängigkeitsproblem hin und nicht auf einen zu aggressiven Probe. Liveness bleibt auf /health, daher führt flatternde Readiness nicht zum Neustart des Pods.

Zertifikatsüberwachungs-Probleme

CronJob sendet keine Slack-Benachrichtigungen

Der cert-renewal-check-CronJob benötigt eine Slack-Webhook-URL, die in einem Secret gespeichert ist. Prüfen Sie, ob es vorhanden ist:
Falls fehlend, erstellen Sie es:
Ohne das Secret läuft der CronJob noch und protokolliert Ergebnisse nach stdout. Logs prüfen mit:

Client-Zertifikat ist abgelaufen, bevor eine Benachrichtigung empfangen wurde

Der CronJob läuft alle 12 Stunden. Wenn er nicht gelaufen ist, prüfen Sie seinen Status:
Eine manuelle Prüfung auslösen:
Um das abgelaufene Zertifikat sofort neu auszustellen:
Dann das neu generierte collector-mtls-secret.yaml im/in den Cluster(s) anwenden, auf dem/denen Ihre Collectors laufen, und sie neu starten:

Backup-Probleme

agenteye-backup schlägt fehl mit “No space left on device”

Der agenteye-backup-CronJob dumpt Postgres + ClickHouse in ein backup-tmp-emptyDir-Scratch-Volume (Standard 30Gi) und streamt dann das tar-Archiv direkt zu S3 – das komprimierte Archiv wird niemals zurück auf Scratch geschrieben, sodass Scratch nur die rohen Dumps halten muss, nicht Dumps plus eine zweite On-Disk-Archivkopie. Ein evictierter Pod / No space left on device bedeutet daher, dass die rohen Dumps die Scratch-Größe überschreiten (der ClickHouse-events-Dump dominiert und wächst im Laufe der Zeit). Prüfen Sie die Logs des fehlgeschlagenen Jobs:
Lösung: Erhöhen Sie in Ihrem Overlay das backup-tmp-emptyDir-sizeLimit des CronJobs über Ihre gesamte rohe Dump-Größe und stellen Sie sicher, dass der Knoten den ephemeren Speicher tatsächlich halten kann (sizeLimit ist eine Obergrenze, keine Reservierung). Wenn die Dumps die Festplatte eines einzelnen Knotens überschreiten, ersetzen Sie emptyDir durch ein PVC (EBS/PD) für backup-tmp oder komprimieren Sie die Dumps an der Quelle.
Ältere Releases schrieben das .tar.gz in denselben 20Gi-Scratch wie die Dumps, sodass Dumps + Archiv ihn überflutete und der Pod vor dem Upload evictiert wurde – was wie ein S3-Fehler aussieht, aber eigentlich Festplatte ist. Das Streaming des Uploads beseitigt diese Verdopplung.

agenteye-backup schlägt beim Installieren von curl fehl

Der Job läuft auf dem postgres:16-Image und installiert curl beim Start für den ClickHouse-HTTP-Dump. Auf einem Cluster ohne Egress zu den Debian-Paketspiegeln schlägt der apt-get-Schritt fehl. Erlauben Sie entweder diesen Egress vom Backup-Pod oder baken Sie curl in ein gespiegeltes/benutzerdefiniertes Backup-Image und referenzieren Sie es in Ihrem Overlay.

agenteye-backup läuft, aber nichts landet im Objektspeicher

Das Base liefert einen echten BACKUP_BUCKET (ts-prod-agenteye/backups) und das agenteye-backup-ServiceAccount. Der Job streamt das Archiv zu S3 (tar cz … | aws s3 cp - s3://…). Wenn der Backup-Pod keinen Schreibzugriff auf den Bucket hat, gibt der Upload einen Fehler aus – und da das Skript unter set -euo pipefail läuft, schlägt ein Fehler irgendwo in dieser Pipe den gesamten Job beim upload-Schritt fehl statt lautlos nicht zu funktionieren (der EXIT-Trap des Pods protokolliert backup FAILED during step: upload). Dies ist auch der Schritt, den Sie nach der Behebung einer Scratch-Space-Eviction erreichen, daher prüfen Sie, ob der Upload jetzt landet. Suchen Sie in den Logs des fehlgeschlagenen Jobs nach dem S3-Zugriffsfehler:
Lösung: Setzen Sie in Ihrem Overlay BACKUP_BUCKET auf einen Bucket, den Sie besitzen, und versehen Sie das vorhandene agenteye-backup-ServiceAccount mit Schreibzugriff (IRSA / Workload Identity / Pod Identity). Siehe den Backups-Abschnitt von enterprise-docs/kubernetes-deployment.md.

ClickHouse-basierte Evaluierungen / Sitzungen / Abfragen

Die /queries-Seiten-Seitenleiste ist nach dem Upgrade leer

Drei Tabellen (events, evaluations, agent_sessions) werden erwartet. Wenn die SchemaBrowser-Seitenleiste nach dem Upgrade leer ist, hat der Server die ClickHouse-DDL beim Start nicht angewendet. Prüfen Sie die Server-Logs auf failed to apply CH DDL statement:
Die häufigste Ursache ist, dass ClickHouse während der Migrationen nicht erreichbar ist. Der Server verweigert den Start, wenn er CH nicht erreichen kann, daher hat ein hängender Pod in der Regel einen CrashLoopBackOff statt einer lautlos defekten Abfrageseite, aber eine teilweise DDL-Anwendung (eine Anweisung OK, die nächste 5xx) lässt das Schema halb fertig. Starten Sie den Server-Pod neu, nachdem CH als erreichbar bestätigt wurde:

Neue Evaluierungen erscheinen nicht in /sessions oder /queries

Nach dem Upgrade werden neue Evaluierungen in ClickHouse geschrieben, nicht in Postgres, und erscheinen unter /sessions (durch evaluations:read abgesichert) und in /queries. Wenn sie nicht erscheinen:
  1. Bestätigen Sie, dass die Evaluierungs-Pipeline aktiviert ist (EVALUATOR_ENDPOINT am Server gesetzt) und terminale Ergebnisse produziert; prüfen Sie auf evaluation_finalized-Log-Zeilen.
  2. Bestätigen Sie, dass CH vom Server aus erreichbar ist: kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping.
  3. Die CH-Tabelle stichprobenartig prüfen: kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'.

Abfragen schlagen unter Last fehl mit “Memory limit exceeded” oder ClickHouse ist OOMKilled

Symptom: Bei starker Dashboard-/Query-Last schlagen analytische Seiten (Ereignisstrom, /sessions, Models-/Latenz-Ansicht, SQL-Editor) fehl oder laufen ab; der Server flattert kurz NotReady; und der ClickHouse-Pod zeigt eine steigende Neustart-Anzahl. Dies ist fast immer ein Speicher-Problem, kein CPU- oder Festplattenproblem. Bestätigen Sie, dass es Speicher ist (kein Durchsatzproblem, das Replikation lösen würde):
  1. Prüfen Sie den Pod auf Out-of-Memory-Kills:
    Reason: OOMKilled / Exit Code: 137 mit steigender Neustart-Anzahl ist das Indiz.
  2. ClickHouse fragen, was es ablehnt:
    Eine große MEMORY_LIMIT_EXCEEDED-Anzahl ist die Signatur. Die Meldung lautet “maximum: N GiB” – dieses N ist 0,9 × das Speicherlimit des Pods (das max_server_memory_usage_to_ram_ratio in deploy/base/clickhouse/configmap.yaml). Wenn Ihre schweren Lesevorgänge mehr als N benötigen, werden sie abgelehnt.
  3. Schließen Sie aus, was kein Problem ist – wenn CPU, Part-Anzahl und Festplatte alle niedrig sind, wäre das Hinzufügen von Replikas/Sharding verschwendete Kosten:
Ursache: Das Speicherlimit des ClickHouse-Pods ist zu klein für das analytische Working Set. Die schwersten Lesevorgänge ziehen die rohe JSON-payload-Spalte, führen JSONExtract* darüber aus und verwenden FINAL – jedes kann mehrere GiB benötigen. Wenn die konfigurierten Caches (mark_cache_size + uncompressed_cache_size) größer als der Pod sind, verschlimmern sie es: Caches werden gegen dasselbe Budget berechnet und verdrängen den Query-Speicher. Lösung – ClickHouse-Speicher skalieren:
  1. Erhöhen Sie das ClickHouse-Speicherlimit in Ihrem Overlay, indem Sie die Container-resources des clickhouse-StatefulSets patchen (derselbe Overlay-Mechanismus wie für die anderen Komponenten). Das nutzbare Server-Budget beträgt 0,9 × Limit, daher gibt ein 6Gi-Limit ~5,4 GiB, 16Gi ~14 GiB. Setzen Sie requests.memory auch auf einen echten Boden, damit der Scheduler es reserviert. Das Anwenden erstellt den CH-Pod neu (einzelnes Replikat → ~30–60s Analytics-Ausfallzeit); tun Sie es in einem Zeitfenster mit geringem Traffic.
  2. Halten Sie die Caches in deploy/base/clickhouse/configmap.yaml proportional zum Limit – kleine Caches (ein paar hundert MiB) sind auf einem kleinen Pod sicher; erhöhen Sie sie nur zusammen mit einer entsprechenden Speicherlimit-Erhöhung. Pro-Query-max_memory_usage ist explizit im users.xml-Profil gesetzt (siehe den Fixed-Node-Abschnitt unten) und wird unter der server-level-Obergrenze (0,9 × Limit) gehalten, sodass keine einzelne Query mehr RAM haben kann als der Container.
  3. Wenn der Knoten selbst die Obergrenze ist, prüfen Sie den Host-Speicher, den ClickHouse sehen kann:
    Wenn das nur etwas über dem Pod-Limit liegt, verschieben Sie ClickHouse auf einen größeren (speicheroptimierten) Knoten – über einen Node-Selector/Affinity in Ihrem Overlay – bevor Sie das Limit weiter erhöhen.
Wenn Sie keinen Speicher hinzufügen können: Queries im RAM halten und schnell abbrechen – nicht auf langsamer Festplatte spilten. Wenn der Knoten fest und der Pod nicht wachsen kann, begrenzen Sie, was eine einzelne Query verwenden darf (damit eine Query nicht den gesamten Knoten übernehmen kann) und lassen Sie auf einer langsamen (Nicht-SSD) Datenfestplatte große Aggregationen/Sortierungen nicht auf die Festplatte spillen. Das Spillen auf eine langsame Festplatte ist langsamer als der Client-Read-Timeout des Servers, sodass eine spillende Query ein Dashboard-500 mitten im Flug zurückgibt, während ClickHouse weiter arbeitet – Queries im RAM zu halten und das seltene über-Budget-Query schnell abzulehnen (MEMORY_LIMIT_EXCEEDED, unter einer Sekunde) stellt das Laden wieder her. Hinweis auf eine ClickHouse-Tücke beim Anwenden:
  • Dies sind Profil-Einstellungen, und ClickHouse liest <profiles> nur aus users_config (users.xml / users.d/*.xml) – niemals aus config.d. Ein <profiles>-Block in config.d/agenteye.xml wird lautlos ignoriert (max_execution_time, max_memory_usage usw. werden einfach nicht angewendet). Die gebündelte Konfiguration liefert sie daher als users.xml-Schlüssel auf der clickhouse-config-ConfigMap, eingebunden unter /etc/clickhouse-server/users.d/agenteye.xml.
  • Die mitgelieferten Standardwerte: max_memory_usage (Pro-Query-Obergrenze – eine Query kann nicht das gesamte Server-Budget verbrauchen), max_bytes_before_external_group_by / max_bytes_before_external_sort = 0 (Spill deaktiviert), damit Queries im RAM bleiben statt auf der langsamen Festplatte zu kriechen, und max_execution_time (Ausreißer-Wächter, abgestimmt auf den Client-Read-Timeout des Servers).
  • Prüfen Sie, ob sie aktiv sind (so erkennen Sie auch die config.d-Tücke):
    Erwarten Sie einen von Null verschiedenen max_memory_usage und max_bytes_before_external_group_by = 0. Wenn max_memory_usage 0/Standard liest, wird das Profil nicht angewendet – prüfen Sie, ob die Einstellungen in einem users.d-Mount leben, nicht in config.d.
Trade-off: Mit deaktiviertem Spill wird eine Query, deren Working Set max_memory_usage überschreitet, abgelehnt (MEMORY_LIMIT_EXCEEDED) statt langsam abzuschließen – auf einer langsamen Festplatte ist diese schnelle Ablehnung vorzuziehen, da eine spillende Query den Client-Timeout überschreiten und trotzdem scheitern würde. Wenn Ihre Datenfestplatte schnell (SSD) ist, können Sie stattdessen die max_bytes_before_external_*-Schwellenwerte erhöhen, um großen Queries das Spillen auf die Festplatte und das Abschließen zu ermöglichen.

Multi-Tenancy (Organisationen)

Fehler beim Upgrade, das Organisationen aktiviert (gemischte alte/neue Server-Pods)

Symptom: Während eines Rolling-Deploys des org-aktivierenden Release schlagen einige Anfragen fehl: Server-Logs zeigen there is no unique or exclusion constraint matching the ON CONFLICT specification auf dem api_keys-Pfad, und/oder Alert-/Slack-/Webhook-Kanäle hören während des Rollouts auf zu feuern. Ursache: Das Upgrade ersetzt den alten instanzweiten eindeutigen Index auf api_keys(name) durch organisationsspezifische Partial-Indexes und verschiebt die Alert-Kanal-Einstellungen (und default_user_permissions) aus der globalen settings-Tabelle in pro-org org_settings. Ein alter Server-Pod gibt noch ON CONFLICT (name) aus (jetzt keine passende Einschränkung) und liest noch Kanal-Konfiguration aus den alten settings-Zeilen (jetzt leer). Alte und neue Pods können für diese beiden Pfade nicht sicher koexistieren. Lösung: Rollen Sie dieses bestimmte Upgrade nicht langsam über gemischte Versionen. Führen Sie einen sauberen Cutover durch: Skalieren Sie den alten Server auf null (oder nutzen Sie ein kurzes Wartungsfenster) und bringen Sie die neue Version zusammen mit ihren Migrationen hoch, anstatt alte und neue Replikas nebeneinander zu betreiben. Normaler Traffic und Ingest werden unmittelbar nach dem Cutover wieder aufgenommen; dies betrifft nur das Versions-Übergangsfenster.

Bereitstellung einer Organisation schlägt auf CREATE USER / CREATE ROW POLICY fehl, oder eine Org kann Daten einer anderen Org lesen

Symptom: Das Erstellen einer Org gibt einen Fehler zurück, der CREATE USER, CREATE ROW POLICY oder “access management is disabled” erwähnt; oder, schlimmer, Mitglieder einer Org sehen Ereignisse/Evaluierungen einer anderen Org im SQL-Editor oder Assistenten. Ursache: Die pro-org-Isolation wird durch einen dedizierten ClickHouse-Benutzer + Row Policy pro Org durchgesetzt. Dies erfordert, dass SQL Access Management aktiviert und users_without_row_policies_can_read_rows=false auf ClickHouse gesetzt ist. Mit deaktiviertem Access Management kann die Bereitstellung den Benutzer/die Policy nicht erstellen; mit dem Row-Policy-Standard bei seinem permissiven Wert liest ein Benutzer, der SELECT aber keine Policy hat, alle Zeilen (fail-open). Lösung: Verwenden Sie die gebündelte deploy/base/clickhouse/-Konfiguration, die beides setzt. Wenn Sie Ihre eigene ClickHouse-Konfiguration betreiben, aktivieren Sie SQL Access Management für den server-internen Benutzer und setzen Sie users_without_row_policies_can_read_rows=false (siehe deploy/base/clickhouse/configmap.yaml), starten Sie dann ClickHouse neu und erstellen Sie die Org mit der agenteye-orgctl-CLI neu (siehe enterprise-docs/tenant-management.md).

Org-Benutzer verlieren ClickHouse-Zugriff nach Änderung von ORG_CH_SECRET

Symptom: Der SQL-Editor und der KI-Assistent geben plötzlich ClickHouse-Authentifizierungsfehler für jede Organisation zurück, unmittelbar nachdem ORG_CH_SECRET geändert wurde oder inkonsistent über Replikas gesetzt war. Ursache: Das ClickHouse-Passwort jeder Org wird als HMAC von ORG_CH_SECRET abgeleitet. Das Rotieren (oder das Ausführen von Replikas mit unterschiedlichen Werten) macht die gespeicherten ClickHouse-Anmeldeinformationen jeder Org ungültig; das abgeleitete Passwort stimmt nicht mehr mit dem bereitgestellten Benutzer überein. Lösung: Setzen Sie ORG_CH_SECRET auf einen einzigen starken Wert vor der Bereitstellung einer zweiten Org und halten Sie ihn stabil und identisch auf jedem Server-Replikat. Die Server-Boot-Zeit-Abstimmung stellt beim Start den ClickHouse-Benutzer jeder Org aus dem aktuellen Secret wieder her, sodass ein Server-Neustart über alle Replikas (mit konsistentem Secret) die verwaisten Benutzer heilt. Behandeln Sie den Wert als ein langlebiges Secret; rotieren Sie ihn nicht leichtfertig. Als Sicherheitsnetz gilt: Wenn ORG_CH_SECRET beim eingebauten Dev-Standard bleibt (d. h. nicht gesetzt ist), überspringt die Boot-Zeit-Abstimmung Nicht-Standard-Organisationen und protokolliert einen Fehler statt ihre ClickHouse-Anmeldeinformationen auf den öffentlich bekannten Dev-Wert umzuschreiben, sodass ein einzelnes Replikat, das ohne das Secret neu startet, die anderen Replikas nicht brechen kann. Setzen Sie das Secret konsistent und starten Sie neu, um diese Orgs bereitzustellen.

Der KI-Assistent gibt 400 zurück / weigert sich zu chatten nach Aktivierung von Organisationen

Symptom: Das Assistent-Dock lädt, aber jede Nachricht kommt als Fehler zurück (HTTP 400), und der Agent protokolliert eine abgelehnte org-lose /chat-Anfrage. Ursache: Der Agent ist org-bewusst und schlägt geschlossen fehl; er lehnt ein /chat ab, das keinen Organisationskontext enthält. Dies geschieht während eines Übergangs-Rollouts, bei dem der Agent aktualisiert wurde, aber das Dashboard, das die Anfrage sendet, noch nicht org-bewusst ist. Lösung: Schließen Sie das Rollout ab, sodass das Dashboard Org-Kontext sendet (der normale Endzustand, kein Flag erforderlich). Um die Lücke zu überbrücken, während ein noch-nicht-org-bewusstes Dashboard mit einem org-bewussten Agent spricht, setzen Sie AGENTEYE_AGENT_ALLOW_NO_ORG=1 am agent-Dienst, sodass er auf die default-Org zurückfällt statt abzulehnen, und entfernen Sie es, sobald das Dashboard-Upgrade landet. Siehe die Env-Referenz in enterprise-docs/assistant.md.

Audits

Ein Audit läuft nie (nächster Lauf verschiebt sich ständig, keine Laufhistorie)

Symptom: Die Audit-Seite zeigt last run: never an, oder next run bewegt sich immer weiter in die Zukunft, ohne dass eine Zeile in der Laufhistorie erscheint. Ursache: Das Audit ist deaktiviert (deaktivierte Audits haben keinen Warteschlangeneintrag), oder die Audit-Worker des Servers schlagen beim Beanspruchen von Arbeit fehl. Lösung: Bestätigen Sie, dass das Audit aktiviert ist (die Run-Now-Schaltfläche erfordert es). Prüfen Sie dann die Server-Logs auf audits pipeline started beim Start und auf audits:-Fehler – eine claim_due failed-Zeile verweist auf Postgres-Konnektivität. AUDIT_WORKERS ist standardmäßig 1; es muss ≥ 1 sein, damit ein Audit läuft.

Audit-Läufe erfolgreich, finden aber nichts

Symptom: Die Laufhistorie zeigt succeeded mit findings: 0, obwohl /errors deutlich Fehler zeigt. Ursache: Das Scan-Fenster deckt die Fehler nicht ab, oder die Scope-Filter schließen sie aus. Lösung: Prüfen Sie das Lauf-Zeilenfeld (`