The pipeline, end to end.

What each stage does, what it stores, and the one place a model is allowed in.

A model between two deterministic layers.

Everything before the model is deterministic. Everything after it is too. A person decides what gets applied.

  1. Collect

    Deterministic

    • Plugins read systems and take in telemetry
    • Graph versioned in PostgreSQL, with evidence IDs
    • Change feed an ordered, transactional outbox
    • Novelty detector asks whether a change is new
  2. Investigate

    Model

    • Packet a compact summary of the change, with no telemetry in it
    • Investigator queries the graph through six read-only tools
  3. Decide

    Deterministic

    • Validation every claim must cite what the graph returned
    • Promotion a finding is kept or dropped
    • Findings persisted, served by API, shown in the explorer
  4. Act

    You approve

    • Plan the plugin resolves current state
    • Dry run every write is checked first
    • Approval a person submits the prepared plan
    • Apply and verify the plugin writes, then re-reads

The graph is the shared language.

Every plugin describes its world as resources, facets, and relationships. The detector and the first packet use neutral security semantics, not provider-native fields, so adding a plugin does not mean teaching the model a new format.

  • Identity does not drift. Names, labels, and IP addresses are attributes. Identity is an authority plus an immutable key.
  • Plugins replace, not patch. Each publishes its complete current output. Whatever it omits is retracted.
  • Every publication is a version. The canonical graph is compiled from active assertions and carries a SHA-256 digest that findings are pinned to.
  • Security facts are typed. Class, domain, state, effect, scope, direction, and coverage are explicit. A declared policy is not assumed to be enforced.

Identity

scheme
kubernetes.io/v1, Kind=Object
authority
stable cluster ID
key
lowercase(apiVersion/kind/UID)

Shown for Kubernetes. AWS resources use aws.amazon.com/v1, Kind=Resource with the owning account as the authority.

Relationships

  • contains
  • instantiates
  • member-of
  • uses-identity
  • exposes
  • governed-by
  • communicates-with
  • runs-on
  • backed-by

A closed vocabulary. A new predicate is added centrally, not per plugin.

Telemetry stays out of the graph.

The graph says what exists and what is allowed. Telemetry says what is happening. They meet at one identity.

In

Logs arrive over OTLP/HTTP from your collector, and AWS VPC Flow Logs can arrive straight from Amazon Data Firehose. Plugins map them into normalized events. Ownership comes from registration, never from the payload.

Stored

Raw events go to local JSONL or ClickHouse before anything is projected, with explicit backpressure. Nothing uncommitted reaches the graph.

Rolled up

The graph holds bounded rollups and evidence IDs, not payloads. A communicates-with edge is a lease: it refreshes while traffic continues and retracts when it stops.

How a change becomes a finding.

The model is an advisory investigator. The service stays authoritative for graph state, retrieval bounds, evidence, and promotion.

  1. A change lands

    Each publication that matters to reasoning writes one ordered event to the outbox, in the same transaction. Telemetry-only updates do not.

  2. A detector asks whether it is new

    It compares the previous graph with a coherent checkpoint. A resource becoming externally addressable, typed semantics disappearing or changing, a governed-by edge being retracted, or a new connection to a sensitive destination all raise a signal. Windows with no signal never reach a model.

  3. The model gets a small packet

    Resource IDs, kinds, typed security semantics, opaque evidence handles, and the signals. No telemetry and no provider-native configuration.

  4. It investigates with read-only tools

    Neighborhoods, paths, governance posture, telemetry chains, timelines, and baselines. Each result is bounded and pinned to the packet’s analysis token.

  5. The harness validates

    A candidate needs a selected signal, entities from the packet, returned fact IDs, and evidence IDs attached to those facts. A wrong reference gets one correction turn. Truncated retrieval blocks promotion.

  6. A finding is promoted or dropped

    Finding IDs are deterministic. A later change that touches an affected entity invalidates older findings; they stay available for audit but cannot launch a remediation.

Fixes come from the plugins that can apply them.

Reasoning attaches desired outcomes to a finding. It never picks a provider. You see every action that is live and choose one.

  • Kubernetes

    Action
    network-policy/v1
    Outcome
    network.declare-ingress-isolation
    Result
    A pod label and an ingress-isolating NetworkPolicy
  • Cilium

    Action
    cilium-network-policy/v1
    Outcome
    network.declare-ingress-isolation
    Result
    A pod label and an ingress-isolating CiliumNetworkPolicy
  • Istio

    Action
    peer-authentication/v1
    Outcome
    transport.require-mutual-tls
    Result
    A pod label and a STRICT PeerAuthentication

A third outcome, gateway.prevent-route-delivery, can be suggested, but no shipped plugin implements it yet. The AWS plugin has no actions either.

Preparation runs a dry run for every intended write. Execution re-reads the target, writes, and attempts to roll back a new pod label if the policy write fails. Read the remediation docs.

Where it stops today.

It is v0. These are the edges, stated plainly.

  • Kubernetes and AWS EC2 networking only. The graph and plugin contract are provider-neutral; other environments will arrive as plugins.
  • The AWS plugin is early and read-only. It models instances, network interfaces, and security groups, not routing, gateways, network ACLs, or IAM, so a public address or an open rule is not treated as proof of exposure.
  • The graph models network and policy. Permissions, reachability from network policy, and secret access are not edges yet.
  • Reasoning works on batches of graph changes, so detection is near real time, not instant.
  • On first start, or after a restart that lags, it rebases to the current state instead of analyzing what changed while it was down.
  • The development API has no production authentication. Approval state lives in memory, and mutations are served only on a loopback listener.
  • Verification confirms the declared policy and label are present. It does not prove the controller accepted them or that traffic is blocked.

Run it yourself.

One binary with the explorer built in. It needs PostgreSQL and something to read: a Kubernetes context, AWS credentials, or both. Reasoning is optional.

Needs Go, Node.js with pnpm, Docker, and kubectl.

export POSTGRES_PASSWORD='development-only-password'make postgres-upexport AGENTANTIBODY_DATABASE_URL="postgres://agentantibody:${POSTGRES_PASSWORD}@127.0.0.1:5432/agentantibody?sslmode=disable"make run

Open http://127.0.0.1:8088. To turn on reasoning, set a model endpoint first.

export AGENTANTIBODY_MODEL_ENDPOINT='<your OpenAI-compatible endpoint>'