How the agent communicates

The direct HTTP/JSON protocol under /api/machine/agents/*, why it is not OpenTelemetry, the heartbeat as a control channel, the two authentication models, the separate inventory channel, and the X-Agent-Kind header that tells Scout and the Machine Agent apart.

machine-agentprotocolhttpjsonopentelemetryotlpheartbeatcommandsinventoryauthx-agent-kindapi-keyconnection-key

Direct protocol, not OpenTelemetry

A question worth answering plainly: does the Machine Agent use OpenTelemetry? No. The agent talks to the VerOps backend over a direct, purpose-built HTTP/JSON protocol rooted at /api/machine/agents/*. There is no OTLP exporter, no gRPC, and no OpenTelemetry SDK in the agent. Telemetry is modelled by VerOps's own endpoints, and control flows back to the agent through the heartbeat response — a design OTLP does not offer.

Why not OTLP: OTLP is a one-way push of spans, metrics, and logs. The Machine Agent needs a two-way relationship: the platform hands work back (log reads, process watches, config) on each check-in. That control channel is the whole point of the custom protocol, so the agent uses it instead of OTLP.

The core endpoints

Every call in this channel authenticates with the connection key in X-Machine-Key; after the agent registers, it also sends the assigned X-Agent-ID.

Method & path Purpose Auth headers
POST /api/machine/agents/authenticate Validate the connection key, obtain the agent identity. X-Machine-Key
POST /api/machine/agents/register Register the host (name, OS, version, capabilities) and receive an agent ID. X-Machine-Key
POST /api/machine/agents/{id}/heartbeat Check in, report host metrics, and receive pending commands + config. X-Machine-Key + X-Agent-ID
POST /api/machine/agents/{id}/scrape-result Return the result of a metric scrape. X-Machine-Key + X-Agent-ID
POST /api/machine/agents/{id}/process-snapshot Return a process-watch snapshot (top processes by CPU/memory). X-Machine-Key + X-Agent-ID
POST /api/machine/agents/{id}/command-result Return the result of an ad-hoc command (e.g. a READ_LOG). X-Machine-Key + X-Agent-ID

The heartbeat is a control channel, not just a ping

The agent never listens for the platform. Instead it pulls: each heartbeat is a question — "any commands for me?" — and the backend's response is the answer. The response carries a list of pending_commands and any updated process-watch configuration. The agent dispatches each command, executes it locally, and posts the outcome back to command-result (or process-snapshot). This is why lowering heartbeat_interval_secs makes commands arrive sooner — there is no separate push path.

Agent ──POST /heartbeat──────►  Backend     "here are my metrics; any commands?"
Agent ◄──200 {pending_commands}─  Backend     READ_LOG /var/log/app.log  patterns=[ERROR]
Agent   (reads file, applies filters locally)
Agent ──POST /command-result───►  Backend     matching_lines + match_count

Two authentication models

The agent uses different credentials for different channels — an important security boundary:

Channel Endpoints Authenticates with
Core telemetry & control /api/machine/agents/* The machine connection key (X-Machine-Key) + X-Agent-ID.
Inventory module (optional) /api/v1.0/inventory/* A per-device device key (X-Device-Key, obtained by exchanging a limited-use enrollment token at /api/v1.0/inventory/enroll), or an ingest key (X-Api-Key, ta_live_…), which the Machine Agent still supports. The machine connection key cannot authenticate inventory.

The inventory channel (when the module is enabled)

The optional inventory module reports on its own paths, still direct HTTP/JSON — not OTLP:

Method & path Purpose
POST /api/v1.0/inventory/enroll One-time exchange of an enrollment token (sce_…) for a revocable per-device key (scd_…), sent with agentKind=server.
POST /api/v1.0/inventory/report The primary reporting path — the host's inventory (report schema v2) and per-app activity.
POST /api/v1.0/inventory/agent-config Pull the effective tracking config and collection policy (what to collect, in which mode, how often).
In short: One agent, two doors. Logs, host metrics, and commands go through the direct /api/machine/agents/* protocol keyed by the connection key. Inventory goes through /api/v1.0/inventory/* keyed by its own enrolled device credential, or by an ingest key. Neither door is OpenTelemetry.

Which agent is calling: X-Agent-Kind

Every inventory request carries an X-Agent-Kind header naming the product that sent it — machine-agent from this agent, scout from VerOps Scout. It is how the platform applies rules that differ between the two: inventory ingest refuses org-wide API-key authentication from a Scout (enrollment-only since Scout v0.6.0) while continuing to accept it from the Machine Agent.

Note this is not the same thing as the agentKind field inside an inventory report, which describes the device's roleserver or workstation. One says which software is talking; the other says what kind of machine it is talking about.