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

# Agents

> The lightweight in-cluster daemon that connects your k3s cluster to Niro.

## What is the Niro agent?

The **Niro agent** is a lightweight daemon that runs as a Kubernetes Deployment inside your cluster, in the `niro-system` namespace. It's the only component you install — everything else is managed by Niro.

The agent is:

* **Stateless** — cluster state is reconstructed from the Kubernetes API on every heartbeat
* **NAT-friendly** — all traffic is outbound HTTPS; no inbound ports or VPN required
* **Non-invasive** — read-only by default; write access requires explicit opt-in
* **Self-updating** — can roll itself to the latest version if you enable the `self-update` capability

## How the agent works

### Enrollment

The agent runs the enrollment flow exactly once when first installed:

1. Reads the enrollment token from the `NIRO_TOKEN` environment variable
2. Contacts Niro to exchange the token for a long-lived key
3. Stores the key in a Kubernetes Secret in `niro-system`
4. The enrollment token is invalid after this point — the agent uses its key for all future requests

### Heartbeat

Every \~15 seconds the agent collects a snapshot and sends it to Niro:

```
Nodes
  ├── name, status, roles, Kubernetes version
  └── CPU/memory: capacity, allocatable, usage (from metrics-server if present)

Pods
  ├── name, namespace, phase, restarts, owner (Deployment/StatefulSet/DaemonSet)
  ├── containers: image, resource requests/limits, liveness/readiness probes
  ├── privileged flag, imagePullSecrets
  └── CPU/memory usage (from metrics-server if present)

Kubernetes Events
  └── Warning-type only, recent window

Capabilities
  └── logs_enabled, apply_enabled, self_update_enabled
```

Niro processes the heartbeat to update fleet state, evaluate policies, detect incidents, and determine if an agent update should be delivered.

### Command channel

The agent maintains a persistent connection to Niro. When Niro has a command ready (apply, delete, stream logs, ping), it delivers it over this connection. The agent processes the command, reports the result, and immediately re-establishes the connection.

This creates a persistent, low-latency channel with no inbound connectivity requirements.

## Default RBAC

The agent's default role is **read-only**:

```yaml theme={"theme":{"light":"github-light","dark":"vesper"}}
# What the agent can do by default
- apiGroups: [""]
  resources: ["nodes", "pods", "namespaces", "events"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets", "daemonsets", "replicasets"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
  resources: ["nodes", "pods"]
  verbs: ["get", "list"]
```

Write access and log access are granted separately per cluster by re-running the installer with capability flags.

## Capabilities

Capabilities are opt-in, additive, and reversible. Each capability grants additional RBAC permissions and unlocks corresponding features in the Niro dashboard.

| Flag                        | RBAC granted                                    | Dashboard feature                       |
| --------------------------- | ----------------------------------------------- | --------------------------------------- |
| `NIRO_ENABLE_PODS=1`        | list pods (default on)                          | Pod inventory                           |
| `NIRO_ENABLE_LOGS=1`        | `pods/log`                                      | **View logs** button on pods            |
| `NIRO_ENABLE_APPLY=1`       | create/update/patch/delete on managed resources | **Apply to cluster**, config management |
| `NIRO_ENABLE_SELF_UPDATE=1` | patch own Deployment                            | Agent auto-update                       |

To enable a capability, re-run the installer (no new token needed — the agent reuses its existing key):

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -fsSL https://get.niro.cx/install.sh | NIRO_ENABLE_LOGS=1 NIRO_ENABLE_APPLY=1 sh
```

To revoke a capability, set the flag to `0`:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -fsSL https://get.niro.cx/install.sh | NIRO_ENABLE_LOGS=0 sh
```

The capability appears in the dashboard within \~15 seconds (the next heartbeat reports the updated capability state).

<Note>
  Setting `NIRO_ENABLE_APPLY=1` grants delete only for managed namespaced resources. Niro never deletes namespaces.
</Note>

## Log streaming

When you click **View logs** in the dashboard, Niro:

1. Sends a log stream command to the agent with the target pod/container
2. The agent streams the container logs and forwards them to Niro in batches
3. The dashboard subscribes to the stream and renders lines in real time

Log streams are coordinated through Niro so they work reliably regardless of which backend instance you're connected to.

## Self-update

If `NIRO_ENABLE_SELF_UPDATE=1`, the agent can roll itself to a new version when Niro signals an update is available. The agent patches its own Deployment's image tag, the new pod starts up, and Niro reflects the updated version within one status cycle.

## Related

* [Connect a Cluster](/guides/connect-cluster) — install the agent and enroll a cluster
* [Agent Capabilities](/reference/agent-capabilities) — full capability reference
* [Manage Secrets and ConfigMaps](/guides/secrets-configmaps) — create configuration resources for apps
* [Stream Pod Logs](/guides/pod-logs) — enable and use live log streaming
