Skip to main content
The agenteye-collector daemon guarantees that your agents’ telemetry reaches AgentEye without ever blocking your application. Your code writes events to a local directory and moves on; the collector takes ownership from there, uploading each file within milliseconds and surviving restarts, network outages, and transient server errors. Failed uploads are retried with exponential backoff, and a periodic recovery sweep re-queues anything left behind by a crash or deploy. The result is durable, fire-and-forget delivery: your agents keep running at full speed while the collector ensures no events are lost in transit. Mechanically, the collector is a lightweight daemon that watches $AGENTEYE_HOME/events/ (default: ~/.agenteye/events/) for .jsonl files written by the Python SDK and uploads them to the AgentEye server.
Renamed: the collector command is now agenteye-collector (it used to be agenteye). The short agenteye name now belongs to the AgentEye CLI. If you are upgrading an existing install, see enterprise-docs/collector-migration.md.

Prerequisites


Pre-built static binaries are available for Linux, macOS, and Windows (x86_64 and arm64). Download the binary for your platform directly from the agenteye-enterprise/releases repo under the latest collector/v<version> release tag. Available artifact names:
PlatformArtifact
Linux x86_64agenteye-collector-linux-x86_64
Linux arm64agenteye-collector-linux-arm64
macOS x86_64agenteye-collector-darwin-x86_64
macOS arm64agenteye-collector-darwin-arm64
Windows x86_64agenteye-collector-windows-x86_64.exe
Windows arm64agenteye-collector-windows-arm64.exe
Download with the gh CLI (replace the version and pick your platform’s artifact):
VERSION=0.0.1-beta.13
GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \
  --repo agenteye-enterprise/releases \
  --pattern 'agenteye-collector-linux-x86_64'

chmod +x agenteye-collector-linux-x86_64
sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector
Or with curl:
VERSION=0.0.1-beta.13
ARTIFACT=agenteye-collector-linux-x86_64
curl -fsSL \
  -H "Authorization: token $AGENTEYE_TOKEN" \
  -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \
  -o agenteye-collector
chmod +x agenteye-collector
sudo mv agenteye-collector /usr/local/bin/agenteye-collector

Option B: Docker

echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin
docker pull ghcr.io/agenteye-enterprise/collector:beta-latest
Current beta builds publish the floating :beta-latest tag; :latest is assigned only to stable releases. For repeatable deployments, prefer a pinned version tag such as :v0.0.1-beta.13.
Run:
docker run -d --restart unless-stopped \
  --name agenteye-collector \
  -e AGENTEYE_URL=https://ingest.example.com/events \
  -e AGENTEYE_KEY="$AGENTEYE_KEY" \
  -e AGENTEYE_HOME=/data \
  -v "$HOME/.agenteye:/data" \
  ghcr.io/agenteye-enterprise/collector:beta-latest \
  start
The official image runs as a non-root user, so set AGENTEYE_HOME explicitly and mount the host spool to it. The volume mount shares the same ~/.agenteye/ directory that the Python SDK writes to on the host. If you already set AGENTEYE_HOME elsewhere on the host, mount that directory instead of $HOME/.agenteye.

Configuration

All options can be set three ways (highest priority first):
  1. CLI flag: agenteye-collector start --url https://...
  2. Environment variable: AGENTEYE_URL=https://...
  3. Config file: ~/.agenteye/config.json

Required options

OptionCLI flagEnv varconfig.json key
Backend URL--url <URL>AGENTEYE_URL"url"
API key--key <KEY>AGENTEYE_KEY"key"

Optional options (with defaults)

OptionCLI flagEnv varconfig.json keyDefault
Max concurrent uploads--max-concurrent-uploads <N>AGENTEYE_MAX_CONCURRENT_UPLOADS"max_concurrent_uploads"64
Sweeper interval (s)--sweep-interval <S>AGENTEYE_SWEEP_INTERVAL"sweep_interval_secs"60
Sweeper min file age (s)--sweep-min-age <S>AGENTEYE_SWEEP_MIN_AGE"sweep_min_age_secs"120
Max files per sweep--sweep-max-files <N>AGENTEYE_SWEEP_MAX_FILES"sweep_max_files"64
Max upload attempts--max-retries <N>AGENTEYE_MAX_RETRIES"max_retries"5
Retry base delay (ms)--retry-base-delay <MS>AGENTEYE_RETRY_BASE_DELAY"retry_base_delay_ms"1000

mTLS options (optional)

For deployments that require mutual TLS (mTLS), the collector can present a client certificate during the TLS handshake. When these options are not set, the collector uses standard HTTPS.
OptionCLI flagEnv varconfig.json key
Client certificate (PEM)--tls-cert <PATH>AGENTEYE_TLS_CERT"tls_cert"
Client private key (PEM)--tls-key <PATH>AGENTEYE_TLS_KEY"tls_key"
Custom CA cert (PEM)--tls-ca <PATH>AGENTEYE_TLS_CA"tls_ca"
--tls-cert and --tls-key must be set together. The files must be PEM-encoded. --tls-ca is independent and only needed when the AgentEye server presents a TLS certificate that isn’t issued by a publicly-trusted CA (e.g. self-signed by an in-cluster cert-manager issuer when you don’t have a real DNS domain). The collector adds the supplied CA as an additional trust anchor; the standard public roots remain trusted, so existing deployments are unaffected. The file may contain a single PEM cert or a full chain (multiple concatenated PEM blocks). Running the collector as a sidecar in your application pod? See enterprise-docs/single-pod-deployment.md for the end-to-end EKS pattern: mTLS bundle delivered via AWS Secrets Manager + Secrets Store CSI Driver + IRSA, with automatic rotation. When running in Kubernetes with the Secret hand-off pattern, mount the certificate Secret as a volume and point these paths to the mounted files:
# Example: collector Deployment snippet
volumes:
  - name: mtls-certs
    secret:
      secretName: agenteye-collector-mtls
containers:
  - name: collector
    env:
      - name: AGENTEYE_TLS_CERT
        value: /etc/agenteye/tls/tls.crt
      - name: AGENTEYE_TLS_KEY
        value: /etc/agenteye/tls/tls.key
      # Only when the server cert isn't publicly-trusted (e.g. in-cluster
      # self-signed CA). The same Secret typically carries ca.crt alongside
      # tls.crt/tls.key.
      - name: AGENTEYE_TLS_CA
        value: /etc/agenteye/tls/ca.crt
    volumeMounts:
      - name: mtls-certs
        mountPath: /etc/agenteye/tls
        readOnly: true

Example ~/.agenteye/config.json

{
  "url": "https://ingest.example.com/events",
  "key": "sk-...",
  "max_concurrent_uploads": 16,
  "sweep_interval_secs": 30
}
With mTLS:
{
  "url": "https://ingest.example.com/events",
  "key": "sk-...",
  "tls_cert": "/etc/agenteye/tls/tls.crt",
  "tls_key": "/etc/agenteye/tls/tls.key"
}
With mTLS plus a custom CA (self-signed AgentEye server):
{
  "url": "https://ingest.example.com/events",
  "key": "sk-...",
  "tls_cert": "/etc/agenteye/tls/tls.crt",
  "tls_key": "/etc/agenteye/tls/tls.key",
  "tls_ca": "/etc/agenteye/tls/ca.crt"
}
If AGENTEYE_HOME is set, that directory is used instead of ~/.agenteye.

First-time Setup

After installing, configure the collector with your server URL and API key:
mkdir -p ~/.agenteye
cat > ~/.agenteye/config.json <<'EOF'
{
  "url": "https://ingest.example.com/events",
  "key": "YOUR_COLLECTOR_KEY"
}
EOF
Use https for any deployment that crosses an untrusted network so events are not sent in plaintext. The plaintext http://your-server-host:8080/events form is appropriate only for purely local testing against a server on the same host.
Test the connection (one-shot flush, exits after draining pending events):
agenteye-collector flush
flush reports its progress to stdout. When the spool is empty it prints No pending files. and exits 0. Otherwise it prints one line per file ([UPLOADED] <file> or [FAILED] <file> (<reason>)), followed by a Done: <uploaded>/<total> uploaded, <failed> failed. summary. This makes flush a convenient one-shot check that your URL, key, and TLS settings are correct before you start the daemon.

Running as a Daemon

Direct

agenteye-collector start

Container / Docker

When the collector and your application share a container, run them under a process supervisor. The simplest option is supervisord; it ships in every major distro, restarts crashed processes, forwards signals, and waits for graceful shutdown. Dockerfile:
FROM python:3.11-slim

RUN apt-get update && apt-get install -y --no-install-recommends supervisor \
 && rm -rf /var/lib/apt/lists/*

# Pull the agenteye-collector binary from the official image.
# Pin a specific tag (:beta-latest for current betas, or a :v<version> tag);
# :latest is published only for stable releases.
COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \
     /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector

COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf
COPY my_agent.py      /app/my_agent.py

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
supervisord.conf:
[supervisord]
nodaemon=true
user=root

[program:agenteye-collector]
command=/usr/local/bin/agenteye-collector start
autorestart=true
stopwaitsecs=30
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:app]
command=python /app/my_agent.py
autorestart=unexpected
stopwaitsecs=30
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
Why these settings:
  • autorestart=true on agenteye-collector: restart on any exit (crash, panic, OOM).
  • autorestart=unexpected on the app: restart only on non-zero exit, so a one-shot agent that exits 0 doesn’t loop.
  • stopwaitsecs=30: gives the collector room to drain pending uploads on SIGTERM before supervisord escalates to SIGKILL.
  • stdout_logfile=/dev/stdout, *_maxbytes=0: stream both programs’ output to the container stdout; no log files inside the container.
Pass AGENTEYE_URL / AGENTEYE_KEY (and any TLS env vars) on docker run -e as before; supervisord inherits the environment.
Separate containers? If you run the collector as its own container (Docker Compose service, Kubernetes sidecar, etc.), don’t use supervisord; the container runtime’s restart policy already does this job. See enterprise-docs/single-pod-deployment.md for the EKS sidecar pattern.
Kubernetes liveness probe (applies whether the collector runs alone or under supervisord):
livenessProbe:
  exec:
    command: ["agenteye-collector", "health"]
  initialDelaySeconds: 10
  periodSeconds: 30
The running daemon writes a heartbeat to $AGENTEYE_HOME/health.json every 30 seconds. agenteye-collector health reads that file and exits 0 (healthy) only when the heartbeat is fresh and the upload tasks are running normally; it exits 1 (unhealthy) when the heartbeat is older than 90 seconds (for example, the daemon has stopped) or while the watcher and sweeper are restarting after an unexpected exit. The heartbeat is written only by start, so run the probe against the long-lived daemon rather than the one-shot flush command.
# /etc/systemd/system/agenteye-collector.service
[Unit]
Description=AgentEye Collector
After=network.target

[Service]
ExecStart=/usr/local/bin/agenteye-collector start
Restart=on-failure
RestartSec=5
EnvironmentFile=/etc/agenteye/env

[Install]
WantedBy=multi-user.target
Create /etc/agenteye/env:
AGENTEYE_URL=https://ingest.example.com/events
AGENTEYE_KEY=YOUR_COLLECTOR_KEY
sudo systemctl daemon-reload
sudo systemctl enable --now agenteye-collector
sudo systemctl status agenteye-collector

launchd (macOS)

<!-- ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>ai.befailproof.agenteye-collector</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/local/bin/agenteye-collector</string>
    <string>start</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>AGENTEYE_URL</key>
    <string>https://ingest.example.com/events</string>
    <key>AGENTEYE_KEY</key>
    <string>YOUR_COLLECTOR_KEY</string>
  </dict>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
</dict>
</plist>
launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist

Upgrading the Collector

The collector does not update itself. To upgrade:
  • Binary: download the new agenteye-collector-<os>-<arch> artifact from the latest collector/v<version> release (see Option A), replace /usr/local/bin/agenteye-collector, then restart the service (sudo systemctl restart agenteye-collector, re-launchctl load, or restart your supervisor).
  • Docker: docker pull ghcr.io/agenteye-enterprise/collector:beta-latest (or a pinned :v<version> tag; :latest exists only for stable releases) and recreate the container.
AGENTEYE_TOKEN is required to download new binaries/images from the private releases repo, but is not needed by the running daemon.

Subcommands

CommandDescription
agenteye-collector startStart the long-lived daemon. On startup it flushes any events left over from a previous run, then watches for new files and uploads them. The watcher and sweeper auto-restart on unexpected exit, and a heartbeat is written to health.json every 30 seconds.
agenteye-collector flushOne-shot: upload all pending files and exit. Prints No pending files. when the spool is empty, otherwise a per-file [UPLOADED]/[FAILED] log and a Done: <uploaded>/<total> uploaded, <failed> failed. summary.
agenteye-collector healthRead the daemon’s health.json heartbeat. Exit 0 when fresh and healthy; exit 1 when the heartbeat is stale (older than 90s) or the tasks are restarting.

Directory Layout

~/.agenteye/
├── config.json       <- optional config file
├── events/           <- .jsonl files written by the SDK, picked up by the collector
└── failed/           <- files that failed all upload attempts
Files in failed/ are not automatically retried. To manually re-queue them, move them back to events/ and run agenteye-collector flush.