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 two halves
Section titled “The two halves”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.
How the runner connects
Section titled “How the runner connects”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.
What the runner does on a call
Section titled “What the runner does on a call”- The control-plane requests a catalog operation (say,
metrics.getServiceLatency). - 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? - The matching connector makes the read-only call against your source, using credentials read from your secret manager.
- The result passes through edge redaction: declared field, structural, then content, in that order.
- 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.
What’s in each package
Section titled “What’s in each package”| 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. |
Cattle, not pets
Section titled “Cattle, not pets”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.