Docs
Agents

Concepts

Installing an agent

Run the agent in your own network, enroll it with a one-time token, and run checks on what our cloud cannot reach.

Pre-release

Agents are in development (RFC 0029). The routes below are stable; the agent's own releases are announced in the changelog.

What it is

The agent, iohr-agent, is a program you run inside your network: a container in your cluster, a service on a machine, or iohr agent on a laptop. It opens one connection out to the API host and keeps it open. The platform sends work down that connection and the agent sends results back. Nothing on your side listens for the internet, so there is no inbound firewall rule to ask for.

Three rules hold for every agent:

  • Your local policy wins. The agent reads a policy file on its own machine that names the networks and hosts it may reach and the work it may do. Anything outside it is refused by the agent, and the refusal is what you see.
  • Bound to verified domains. An agent is enrolled for domains your account has verified. The platform sends a check on a named host only when the host is inside one of them and the domain is still verified. A private address or an internal name such as db.internal cannot be proved by DNS; it goes to the agent, and its policy decides.
  • Results, never content. The agent reports a check's outcome: passed or failed, the latency, the HTTP status and an error class. Never a request or response body. Credentials stay in your own secret store: a check names a reference (vault:<path>#<key>, k8s:<namespace>/<name>#<key>, env:<NAME>, file:<path>) that the agent resolves at the moment of the call.

Enroll

Make an enrollment token

In the console, open Agents and choose Enroll an agent, or call the API with a key that holds agents:write:

curl -X POST https://api.inorbit.hr/v1/accounts/orgs/$ORG_ID/agents/enrollments \
  -H "Authorization: Bearer $INORBIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"environment":"staging","domains":["example.com"],"name":"edge-1"}'

The answer carries token (ioe_…). It enrolls one agent, once, within the hour, and is shown only in this answer: the platform keeps its hash. Every domain must be verified for the account.

Install and enroll the agent

The console offers the token as a file to download (and as an .env file and Helm values). Keep it out of the command line, where shell history and the process list would keep it.

On a machine with the command line, with the token file next to you:

iohr ext install agent
iohr agent enroll --token-file ./inorbit-agent-staging.token

The agent deletes the file once it has enrolled.

In a Kubernetes cluster, the token becomes a Secret and the values only name it:

kubectl create namespace inorbit-agent
kubectl -n inorbit-agent create secret generic iohr-agent-enrollment \
  --from-file=token=./inorbit-agent-staging.token
helm install iohr-agent oci://ghcr.io/inorbithr/charts/iohr-agent \
  --namespace inorbit-agent \
  -f ./inorbit-agent-staging-values.yaml
image:
  repository: ghcr.io/inorbithr/iohr-agent
environment: staging
enrollment:
  existingSecret: iohr-agent-enrollment
  key: token

The Secret is read on the first start only and may be deleted once the agent shows as online.

What enrolling does

The agent makes an EC P-256 key pair on its machine; the private key stays in a file only it reads. It presents the token and the public key once at POST /v1/agents/enroll, the one route that takes no bearer token: the enrollment token is the credential, and the route is rate limited per address. The answer names the agent's agent_id and client_id, the token endpoint, the audience iohr-api and the scope agents:session.

From then on the agent signs a short assertion with its key (ES256, RFC 7523) and trades it at the token endpoint for a 15-minute access token. No long-lived secret sits on disk.

The session

The agent connects to wss://api.inorbit.hr/v1/agents/session with its own access token; no other token opens it, and its token opens nothing else. Frames are JSON text:

FromFrameWhen
agenthellofirst: its version, the hash of its policy, its capabilities
platformwelcomethe agent's id and heartbeat_secs (15)
agentheartbeatevery 15 seconds; three missed and the session closes
platformjoba check: surface (http, tcp, tls, grpc_health), target, expect, a deadline
agentresultok, failed or refused, with the detail or the policy's reason
platformcancel, revokeda job no longer awaited; the agent was revoked and the session ends

The agent shows as online in the console while its session is open.

Run a check

With agents:write, POST /v1/accounts/orgs/{org_id}/agents/{agent_id}/checks sends one check to an online agent and waits up to 30 seconds for its result:

{ "target": { "url": "https://api.example.com/healthz" }, "surface": "http", "expect": { "status": 200 } }

A target outside the agent's domains, or a public address with no name, is refused with 403 before anything is sent. An offline agent answers 400 failed_precondition at once.

Revoke

POST …/agents/{agent_id}/revoke, or Revoke in the console, closes the session within seconds and deletes the agent's identity, so it cannot get another token. To run an agent there again, enroll a new one.

Scopes

ScopeAllows
agents:readlist the account's agents and read one
agents:writemake enrollment tokens, revoke and delete agents, run a check