> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Collector Installation

> AgentEye Collector Installation documentation.

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](/agenteye/collector-migration).

***

## Prerequisites

* Your `AGENTEYE_TOKEN`: a GitHub PAT you generate yourself (see [enterprise-docs/github-token.md](/agenteye/github-token))
* The server URL and a collector API key (see [enterprise-docs/api-keys.md](/agenteye/api-keys))

***

## Option A: Binary (recommended)

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:

| Platform        | Artifact                                |
| --------------- | --------------------------------------- |
| Linux x86\_64   | `agenteye-collector-linux-x86_64`       |
| Linux arm64     | `agenteye-collector-linux-arm64`        |
| macOS x86\_64   | `agenteye-collector-darwin-x86_64`      |
| macOS arm64     | `agenteye-collector-darwin-arm64`       |
| Windows x86\_64 | `agenteye-collector-windows-x86_64.exe` |
| Windows arm64   | `agenteye-collector-windows-arm64.exe`  |

**Download with the `gh` CLI** (replace the version and pick your platform's artifact):

```bash theme={null}
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`:**

```bash theme={null}
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

```bash theme={null}
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:**

```bash theme={null}
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

| Option      | CLI flag      | Env var        | config.json key |
| ----------- | ------------- | -------------- | --------------- |
| Backend URL | `--url <URL>` | `AGENTEYE_URL` | `"url"`         |
| API key     | `--key <KEY>` | `AGENTEYE_KEY` | `"key"`         |

### Optional options (with defaults)

| Option                   | CLI flag                       | Env var                           | config.json key            | Default |
| ------------------------ | ------------------------------ | --------------------------------- | -------------------------- | ------- |
| 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.

| Option                   | CLI flag            | Env var             | config.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](/agenteye/single-pod-deployment) 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:

```yaml theme={null}
# 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`

```json theme={null}
{
  "url": "https://ingest.example.com/events",
  "key": "sk-...",
  "max_concurrent_uploads": 16,
  "sweep_interval_secs": 30
}
```

With mTLS:

```json theme={null}
{
  "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):

```json theme={null}
{
  "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:

```bash theme={null}
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):

```bash theme={null}
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

```bash theme={null}
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`:**

```Dockerfile theme={null}
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`:**

```ini theme={null}
[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](/agenteye/single-pod-deployment) for the EKS sidecar pattern.

**Kubernetes liveness probe** (applies whether the collector runs alone or under supervisord):

```yaml theme={null}
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.

### systemd (Linux, recommended for production)

```ini theme={null}
# /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
```

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl enable --now agenteye-collector
sudo systemctl status agenteye-collector
```

### launchd (macOS)

```xml theme={null}
<!-- ~/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>
```

```bash theme={null}
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](#option-a-binary-recommended)), 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

| Command                     | Description                                                                                                                                                                                                                                                      |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agenteye-collector start`  | Start 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 flush`  | One-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 health` | Read 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`.
