Territory Grounder is an autonomous SRE agent that commits a prediction before it acts, then lets separate code decide whether reality agreed. The model that proposes a remediation never scores its own outcome, and no mutation runs on a belief the system has not independently checked.

Territory Grounder is an open-source, self-hosted SRE platform: an LLM agent ingests alerts, chat messages, and tickets, triages incidents across Kubernetes, hypervisors, network, and storage, and (from Phase 2 on) executes remediations inside a mechanical governance envelope. It is the ground-up rewrite of Agentic ChatOps as a distributable product: Go and Temporal instead of Python, n8n, and cron. Same control logic, none of the code.

GitHub: territory-grounder/grounder · Product site: territorygrounder.com

Overview

AspectDetails
FunctionAlert/chat/ticket ingest, LLM triage, governed remediation (predict, act, verify)
Control planeGo 1.25, Temporal workflows, PostgreSQL + pgvector
Model accessBundled LiteLLM gateway: one OpenAI-compatible endpoint, multi-provider fallback ladder
IntegrationsRoughly thirty connector modules across seven adapter surfaces (ingest, tracker, notifier, CMDB, actuation, model provider, observability)
DeploymentSingle docker-compose stack; no SaaS dependency, no phone-home
StatusPhase 1 live, read-only; the mutation path built and globally disabled
LicenseApache-2.0
Repositorygithub.com/territory-grounder/grounder

Control Loop

No mutating action runs without a consequence prediction committed first, keyed to action_id = SHA-256(canonicalJSON(Action)). After execution, a pure Go function compares observed state against the committed prediction and writes the verdict: match, partial, or deviation. The model that proposed the action has no write path to the verdict columns. A deviation disables auto-resolve for that action class.

Predictions are additionally scored against a degree-preserving shuffled-graph negative control. The real prediction must be at least twice as precise as the shuffle (control_ratio <= 0.5), otherwise the gate is treated as uninformative.

alert / chat / ticket --> adapter --> Temporal workflow
                                          |
                          predict --> commit prediction  (the gate)
                                          |
                                      act  (bounded to its territory)
                                          |
                    independent verify --> verdict --> hash-chained ledger
                                          |
                          band:  AUTO / AUTO_NOTICE / POLL_PAUSE

The human is a circuit-breaker, not a per-action approver. Three autonomy bands set the interrupt level per session: AUTO (execute, log), AUTO_NOTICE (execute, notify), POLL_PAUSE (wait for a vote; never proceeds on timeout, pinned by a DB CHECK).

Enforcement by Construction

Safety properties live in the type system, the schema, and boot checks, not in review discipline:

Failure classEnforcement
Approve action X, execute action Yaction_id is asserted at classification, prediction, approval, execution, and verification. Any change to the action mints a new id and voids prior approvals
Approval poll without a predictionBuildApprovalPoll accepts only a GatedProposal, a type constructible only by the prediction-gate activity. The bypass does not compile
Error path defaults permissiveZero values are the restrictive option: unset band is POLL_PAUSE, unset reversibility is Irreversible
Shell injectionActuation is fixed argv vectors via exec.Command / x/crypto/ssh with pinned host keys. sh -c is not expressible; CI greps for it
SQL injectionpgx/sqlc generated queries only; string-built SQL fails CI
Unauthenticated routeHandlers come from a factory that requires the authenticated principal; a route declared auth=none fails to register at boot
Silently unwired controlA startup self-test fails boot if the actuation interceptor chain is not in place
Ledger tamperingAppend-only SHA-256 hash chain with UPDATE and DELETE revoked from the runtime role at the database, so the record is tamper-resistant, not merely tamper-evident. A verifier walks the chain and alerts on break or staleness

A non-configurable never-auto floor covers mkfs, dropdb, zpool destroy, tofu destroy, kubectl delete/drain, credential revocation, and reboot/halt. No flag or org policy lifts it. An unrecognized mutation classifies as never-auto.

Operator Console

Grounding scorecard: verifier match rate, falsifiability signal, blast-radius precision and recall

Fifteen-plus live-wired surfaces: sessions, approvals, ledger, estate graph, governance controls, and the Grounding scorecard (verifier match rate, blast-radius precision/recall, falsifiability signal against the shuffled control). The estate causal graph is discovered from NetBox, Proxmox, and LibreNMS with per-source confidence tiers (1.00 for declared tunnels down to a 0.75 cap on learned co-occurrence edges). Screenshots show fixture data.

Build Process

Most of the Go is written by coding agents under a spec-driven workflow: EARS-format requirements, godog acceptance oracles in CI, and a content-hash lockstep that binds each safety-critical file to its owning spec. The current gate runs over 2,600 spec checks across a hundred-plus lockstep-bound files, -race clean. The -race sweep fixed 7 latent concurrency bugs, one of them a ledger writer racing itself and corrupting its own hash chain.

Status

PhaseScopeStatus
0 · Secure foundationMandatory-auth router, argv-only actuation, DML-only runtime DB role, fail-closed mutation gateDone
1 · Typed spineIngest, risk classifier, agent loop, prediction gate, verdict engine, ledger, console, estate graphLive, read-only
2 · Governed autonomyActuation interceptor chain, vote-consuming approval loop, mutation enableBuilt, gated OFF
3 · Anti-drift and lifecycleReconciliation, drift correction, regime-aware actuation (direct on runtime, merge-request on GitOps-managed targets), safe decommissionPlanned
4 · Adversarial assuranceBoundary-coverage gate, sealed-holdout evals, published third-party benchmarksPlanned

What is live today, running read-only against my own estate: authentication on every route, the console, the estate graph, the prediction/verdict/ledger spine, and the Grounding scorecard. The governed-autonomy machinery of Phase 2, the actuation interceptor chain and the vote-consuming approval loop from console approve/deny through a Temporal signal to the Runner and the ledger, is built and wired but gated off. What stays genuinely unexercised is mutation itself, globally disabled and asserted false at boot preflight until the Phase 2 self-tests and a readiness review pass, and the published third-party benchmark. With the operator away, an escalation that reaches POLL_PAUSE times out to deny rather than proceeding, so live autonomy is a decision that gets earned, not defaulted into.


Successor to Agentic ChatOps . Product site: territorygrounder.com . Design rationale: The Map Is Not the Territory .