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

# Agent architecture

> What the zero-code agent runs as, how one process observes every service on a host, and the path telemetry takes from a kernel probe to your dashboard.

One agent process per **host**, not per service. It attaches probes, aggregates
in userspace, and exports OTLP to your aiAxonIQ endpoint. There is no sidecar,
no proxy in your request path, and nothing loaded into your application
processes.

<Warning>
  **Availability.** The zero-code agent is an early-access distribution. It is
  installable, upgradable and tested, and it is **not yet an integrated part of
  the product**: there is no dashboard page for it, no in-product installer and
  no self-service download. Ask your account contact for access.

  Its telemetry, once flowing, is ordinary OTLP and needs nothing special —
  it appears in Services, Traces and Metrics exactly like SDK telemetry does.
  That is the design rather than a shortcut.
</Warning>

## The shape

<Steps>
  <Step title="One agent per host">
    A systemd service on a VM, a container with host PID access under Docker,
    or a DaemonSet pod on Kubernetes. Same binary in each case.
  </Step>

  <Step title="It discovers processes">
    It scans for processes that serve or make network calls and attaches probes
    to the ones it can instrument. New processes are picked up as they start —
    nothing needs restarting when you deploy.
  </Step>

  <Step title="Probes write to kernel maps">
    Bounded work at the event, results into shared memory. See
    [How eBPF works](/zero-code/ebpf).
  </Step>

  <Step title="Userspace aggregates and decorates">
    Requests are assembled into spans and RED metrics, URL paths reduced to
    route patterns, and Kubernetes or host metadata attached.
  </Step>

  <Step title="It exports OTLP over TLS">
    To exactly one destination: your endpoint, authenticated with your license
    key. From there it is ordinary telemetry — see
    [Platform architecture](/concepts/architecture).
  </Step>
</Steps>

## Why one process sees everything

Because it is in the kernel, the agent does not need to be inside your
application. It needs to be in the same **PID namespace** as the processes it
observes — which is what `hostPID: true` on Kubernetes and `--pid=host` under
Docker are for.

<Warning>
  **Without host PID access, the agent sees only itself.** It starts normally,
  reports healthy, discovers one process — its own — and produces essentially
  nothing.

  This is the most common installation mistake, and it looks identical to "the
  agent is broken". If your service inventory did not grow after installing,
  check this before anything else. See
  [Troubleshooting](/zero-code/troubleshooting).
</Warning>

The same principle explains something people find surprising: **the workload's
base image is irrelevant.** A container has no kernel of its own, so a
distroless image, a musl-based image and a full distribution image are all
equally observable. The requirements apply to the host.

## What it does before exporting

Three transformations happen on the host, and each exists for a reason worth
knowing:

<AccordionGroup>
  <Accordion title="URL paths become route patterns" icon="route">
    `/orders/8817` and `/orders/8818` are reduced to a single route shape.

    Two effects, and both matter. **Cardinality**: raw paths would turn one
    endpoint into a series per identifier, which is the fastest known way to
    make a metrics store unusable. **Privacy**: identifiers embedded in paths
    never leave the host.
  </Accordion>

  <Accordion title="Health and metrics endpoints are dropped" icon="filter">
    Highest frequency, lowest diagnostic value, and frequently a large share of
    total volume. Dropping them at the source costs you nothing you would have
    looked at and reduces both your ingest bill and your rate-limit pressure.
  </Accordion>

  <Accordion title="Batches are sized for a fleet" icon="boxes-stacked">
    A DaemonSet across 200 nodes is 200 exporters spending one organization's
    rate-limit budget. Batching is tuned with that in mind rather than left at
    a single-process default. See [Plan limits](/concepts/limits).
  </Accordion>
</AccordionGroup>

## Deployment shapes

| Platform                                    | Runs as                       | Needs                                                                 |
| :------------------------------------------ | :---------------------------- | :-------------------------------------------------------------------- |
| [Linux VM or bare metal](/zero-code/linux)  | A systemd service             | Profile capabilities on the unit                                      |
| [Docker](/zero-code/docker)                 | A container                   | `--pid=host` and the profile capabilities                             |
| [Docker Compose](/zero-code/docker-compose) | A service in your stack       | The same, expressed in the Compose file                               |
| [Kubernetes](/zero-code/kubernetes)         | A DaemonSet, one pod per node | `hostPID: true`, `privileged: false`, dropped-then-added capabilities |
| [OpenShift](/zero-code/openshift)           | A DaemonSet plus an SCC       | The shipped SecurityContextConstraints                                |

## What it reads from Kubernetes

On Kubernetes the agent decorates telemetry with pod, namespace, node and
workload. That needs cluster access, and the grant is deliberately small:

* **`list` and `watch`** on pods, services, nodes and replicasets.
* **Read-only**, cluster-scoped.
* Used **solely** to attach metadata to telemetry — nothing is created,
  modified or deleted.

The rendered DaemonSet also sets `privileged: false`, drops **all** capabilities
and then adds back exactly the profile's set, and mounts the root filesystem
read-only. You can inspect the whole thing before installing anything — see
[Kubernetes](/zero-code/kubernetes#inspect-before-you-install).

## Where the credential lives

Never in a configuration file. On Kubernetes it is a Secret injected as an
environment variable — never in the ConfigMap, so inspecting the ConfigMap
stays a safe debugging step. On Linux it is a root-owned environment file with
mode `0600`. It is redacted in every diagnostic the tooling prints.

<Info>
  **Issue the agent its own license key**, scoped to traces and metrics, and
  revocable independently of your primary ingest key. A DaemonSet places the
  credential on every node, which is a materially wider exposure than one
  application's configuration. See [Security model](/zero-code/security#scope-the-key).
</Info>

## Network requirements

Exactly one outbound destination — your OTLP endpoint, over TLS. The agent
opens no inbound listeners and contacts nothing else: no analytics, no update
check, no vendor telemetry. An egress-restricted network needs that one host
allowed.

The exception is **install time**, when upstream artefacts are downloaded and
checksum-verified. See [OpenTelemetry OBI](/zero-code/obi#licensing).

## Next

<CardGroup cols={3}>
  <Card title="Security model" icon="shield-halved" href="/zero-code/security">
    The full statement for a security review.
  </Card>

  <Card title="Capability profiles" icon="layer-group" href="/zero-code/profiles">
    Choosing a privilege level.
  </Card>

  <Card title="Install on Kubernetes" icon="dharmachakra" href="/zero-code/kubernetes">
    The Helm chart, values and what it renders.
  </Card>
</CardGroup>
