Skip to content

Overview

rootpilot-edge is the open half of a runner / control-plane split. This repository holds everything that runs on your infrastructure: the runner, the connectors, PII redaction, and the communication contract. Nothing here makes a judgment: it collects, normalizes, redacts, and answers.

The dependency direction is one-way: the control-plane consumes the packages from here, never the reverse. If you’re contributing, the rule of thumb is that collection, normalization, and redaction are edge; judgment is control-plane.

The runner dials out. There is no inbound port, no exposed health endpoint, nothing you need to open in your firewall for ingress. It opens a reverse WSS tunnel with mTLS to the control-plane and serves calls from inside it.

That has an operational consequence worth knowing early: because the runner is a client and not a server, there is no HTTP liveness probe. You observe its health through boot logs and through the control-plane’s Fleet view.

  1. The control-plane requests a catalog operation (say, metrics.getServiceLatency).
  2. The runner checks it against the enforcement point: is the op in the versioned catalog? Do the arguments validate strictly against its inputSchema? Does the deadline fit?
  3. The matching connector makes the read-only call against your source, using credentials read from your secret manager.
  4. The result passes through edge redaction: declared field, structural, then content, in that order.
  5. The redacted result goes back through the tunnel.

The control-plane asks what. The runner decides whether it may. Those two questions live on different sides on purpose.

Terminology: “Agent” is the product, runner is the code

Section titled “Terminology: “Agent” is the product, runner is the code”

The component running on your infrastructure is called the RootPilot Agent in the product, the UI, and customer-facing docs, because it’s the familiar observability term, like the Datadog Agent. In code, the protocol, environment variables, and the SPIFFE id, it is runner, and it will stay that way: renaming would break the wire contract and the entire RUNNER_* surface for no gain.

If you find the word “agent” inside this repository’s code, it almost always means something else: the LLM that consumes the tools. Don’t conflate the two.

Package What it is
apps/runner The ephemeral container. Enrollment, tunnel, enforcement, redaction, drain.
packages/connectors The 15 read-only clients for external sources.
packages/core-edge Edge utilities: cache, errors, PII redactor, catalog loader.
packages/protocol The versioned runner↔control-plane contract.
packages/connector-sdk Open SDK for authoring your own connectors.
packages/otel Shared OpenTelemetry instrumentation.
packages/demo A complete fictional environment, with no credentials at all.

The runner holds no durable state. Credentials live in memory only, the local SQLite is a cache, and its default is :memory:. It is built to die: spot reclaim, OOM, docker compose down. Another one comes up and the system carries on. Don’t back it up, don’t treat it as a named server, and don’t keep anything inside it that you need back.