Home / Stories / LLM egress & profiles
Story · Data boundary Live

Your hostnames stay yours. The model still does the work.

Some of your infrastructure data can go to any AI model (LLM). Some of it may leave only with its identifiers masked. Some of it must never leave your own hardware. The assistant treats "where does this prompt go" as a declared decision for each call. It is not an accident of configuration. You can also pick a different model for each class of problem.

Starts fromAny LLM call that the assistant makes: triage, drafting a change, or reviewing a merge request (MR).
Looks atThe assembled prompt, the declared class of the destination, and the strictest egress requirement (the rule for data that leaves) of your tenants.
You getCalls that go only where you allow. Identifiers are masked where required and restored on the way back. You also get a record of each decision.
01 · One door out

Every model call leaves through the same engine.

The assistant has many agents but a single path to an AI model. Each call carries a label that names the kind of work (review_mr, analyse_manifest, chart_upgrade…). The label decides which profile the call uses. The profile decides which endpoint the call goes to.

A test suite guards that door. If new code talks to a model provider directly, the build fails until someone classifies that code.

02 · Classify what is in the prompt

Redact, pseudonymise, or pass. Rules decide, not a model.

Before anything leaves, a rule pack in code sorts the prompt into data classes. No AI model classifies the prompt, because the payload would have to leave first.

  • Redact: secret material. A separate, older secret scrub handles the paths that can carry it. A fail-closed check (it blocks when unsure) backs it up on every write to your forge.
  • Pseudonymise: your company and project names, public hostnames, private IP addresses, email addresses, cluster ids, Vault mount paths.
  • Pass: Kubernetes kinds and label keys, public chart and image names, cluster.local, upstream documentation hosts.
03 · Where is it going?

Destinations are declared, never inferred.

Config declares every profile as one of three destination classes. A self-hosted box that you run is local controlled: no third party sees the data. A provider that you accept for masked payloads is approved remote. It can be a regional provider or a frontier model. Anything not declared is denied.

The assistant does not trust the endpoint URL as evidence. It refuses a profile that the declaration does not list. It does not guess.

04 · What does the tenant require? In development

Each tenant states its own floor.

A tenant's egress requirement is one of any, pseudonymised or local_only. The checks are built, but not every call reliably records its tenant yet. Until it does, a shared engine applies the strictest configured requirement to every call. So one cautious tenant raises the floor for all.

pseudonymised lets a call reach an approved remote provider only as a validated masked envelope. local_only keeps the call on your own hardware.

05 · Mask the identifiers

Same shape, obviously fake, consistent within the request.

Each identifier becomes an alias that keeps its grammar. A hostname stays a valid hostname under the reserved .invalid domain. A private address becomes a documentation-range address with the same prefix width. The same value always gets the same alias. So the model can still reason about "this host talks to that host".

The assistant stores no table of real names and aliases. It rebuilds the mapping for each request from what the request contains.

06 · Restore on the way back

The answer comes back in your terms, or not at all.

The assistant swaps the aliases in the reply back to the real values before any other code sees them. It rejects the reply if an alias cannot be restored. It also rejects the reply if an alias would end up in a file, an MR or a tool argument. So a fake name never leaks into your repository.

A model may use a masked lane only after a paired run proves that its replies restore cleanly. The evidence applies to that exact provider, endpoint and model.

07 · When the only allowed endpoint is down In development

It stops and asks. It does not quietly go elsewhere.

A profile can fall back to another tier when an endpoint fails. The assistant checks every fallback again against the policy of the tier it lands on. It never reroutes automatically to a different residency.

If a local_only tenant's box is down, the engine enters a named HALT state and waits for a person. The design accepts the cost of a lost night of work. It never sends that tenant's data to a cloud model.

08 · Mix and match

Route each class of problem to the model that suits it.

A profile maps call labels to endpoints. Bulk, high-volume work goes to a small, cheap model. Careful generation of a diff goes to a stronger model. The review of the finished MR goes to a model from a different family. So the reviewer does not mark its own homework.

Unmapped labels use the profile's default. If a mapping names a profile that does not exist, the assistant reports it at startup.

Agentsupgrades · resources · alerts · review…
LLM enginethe only path to a model
Egress gateclassify · check destination · mask
Endpointchosen by the call's label
call: label=review_mr · profile=review-tier · 1 MR diff + 3 cluster reads
classification · deterministic rule pack
  • password: s3cr… secret · REDACT
  • orders.shop.acme.example public hostname · PSEUDONYMISE
  • 10.40.12.7 private IPv4 · PSEUDONYMISE
  • acme company name · PSEUDONYMISE
  • [email protected] email · PSEUDONYMISE
  • kind: HelmRelease Kubernetes vocabulary · PASS
  • ingress-nginx public chart name · PASS
  • orders-api.shop.svc.cluster.local in-cluster name · PASS
Local controlledyour own GPU box · raw data may go here
Approved remoteregional provider · frontier model · masked where required
Deniedanything not declared · never a payload
config.yaml · egress_policy
egress_policy:
  local-gpu-box:      local_controlled
  regional-provider:  approved_remote
  frontier-model:     approved_remote
  # not listed ⇒ refused once enforcement is on
tenant requirement × destination
  • any → approved remote raw payload allowed
  • pseudonymised → approved remote masked envelope only
  • pseudonymised → local controlled raw allowed, never leaves
  • local_only → local controlled raw allowed
  • local_only → approved remote refused
  • any → undeclared endpoint refused
tenants: shop=any · payments=pseudonymised ⇒ engine floor = pseudonymised
prompt as assembledstays in memory
host: orders.shop.acme.example
upstream: 10.40.12.7:5432
vault path: secret/acme/orders/db
alert contact: [email protected]
what the provider receivesmasked
host: egress-fake-3b9e1c07a4d2f6e815c0.invalid
upstream: 198.51.100.37:5432
vault path: secret/egress-fake-a71f0c92d8e4b3561f2a/orders/db
alert contact: egress-fake-5c2d…@contact.invalid
# note to the model: copy placeholders verbatim
Illustrative values. Aliases are keyed hashes: stable, announced-fake, never mistaken for real.
model reply
The ingress for egress-fake-3b9e…f6e815c0.invalid points
at a Service with no ready endpoints; the database at
198.51.100.37 is unaffected.
after restoration
The ingress for orders.shop.acme.example points
at a Service with no ready endpoints; the database at
10.40.12.7 is unaffected.
  • every alias restored reply accepted
  • an unknown alias in a proposed file reply rejected, nothing written
Calltenant: local_only
local-gpu-boxconnection refused
Fallback?frontier-model · approved remote
HALT · restricted destination unavailable
Fallback to frontier-model refused: tenant requirement local_only. Queued calls wait; an operator restarts or reconfigures to resume.
recorded: HALT · label=analyse_manifest · reason=local-only destination exhausted
config.yaml · profiles
profiles:
  acme-routed:
    # default tier: bulk triage, cheap and fast
    base_url: http://gpu-box.internal:8000/v1
    model: small-local-model
    call_profiles:
      # judgement: drafting and checking changes
      analyse_manifest: regional-provider
      chart_upgrade:    regional-provider
      diff_complex:     regional-provider
      # review: a different model family
      review_mr:        frontier-model
      review_issue:     frontier-model
Triagelocal GPU box
Generateregional provider
Reviewfrontier model

What a masked review looks like to you.

Illustrative. The assistant reviews its own draft MR before it reaches you, through a masked lane. You see real names. The provider did not.

Draft

Add readiness probe to shop/orders-api

from gitops-ai/reliability-orders-api-probe-7a2e into main · 1 file · +8
category:reliabilitysource:repo_scan:acme-deployrisk:lowxrev::LGTM
ReviewWhat the provider sawEgress record
Automated review

The probe targets port http on /healthz. The live pods at orders.shop.acme.example already answer that path with 200. The Service selector matches the Deployment's labels. The probe does not include the database dependency on 10.40.12.7. So a database blip will not take the pods out of rotation.

Verdict: LGTM.

Excerpt of the outbound prompt
Live pods behind egress-fake-3b9e1c07a4d2f6e815c0.invalid answer
GET /healthz with 200. DB upstream 198.51.100.37:5432.
… the diff, Kubernetes kinds and public chart names pass unchanged …

The assistant masked identifiers with keyed aliases for this request only. This is pseudonymisation of declared identifier classes. A provider could still infer things from structure and chart choices. This lane does not claim otherwise.

FieldValue
labelreview_mr
profilefrontier-model
destination classapproved remote
engine floorpseudonymised
aliasedfqdn 2 · rfc1918-ipv4 1 · customer-name 1
round tripall aliases restored · reply accepted
qualificationpaired-run evidence on file for this provider + model

The assistant records only the counts, never the values.

What keeps it honest.

The boundary is rule-based code with tests that fail loudly. It is not a promise in a prompt.

Sealed masking codeThe classification and masking module cannot import any network client or model SDK. It can transform a prompt. It can never send one.
Mask the copy, not the sourceThe assistant masks only the outbound envelope. Your manifests and the proposals built from them stay real. So a fake name never reaches a commit.
Aliases are a taintAn alias that survives into a file, a tool call or a forge write rejects the reply. The forge write gate also blocks alias-shaped text.
Refusal is a named stateUnknown destination: refused. Restricted tenant with its endpoint down: HALT. The assistant records both with a reason code. Nothing degrades silently.
Qualified before maskedA model joins a masked lane only with round-trip evidence for that exact provider, endpoint, model and masking version.
Honest about limitsMasking covers declared identifier classes. It does not stop a provider from inferring who you are from structure or style. We do not claim that it does.

Where this stands.

Live
  • One engine for every model call, guarded by tests
  • Declared destination classes; undeclared endpoints refused
  • Identifier masking and restoration for MR review calls, with per-model round-trip evidence
  • Profiles routing call labels to different endpoints, with startup checks
  • Secret scrub, with a fail-closed check on every forge write
In development
  • Per-tenant any / pseudonymised / local_only requirements and HALT (built, not yet in customer use)
  • Masking for issue review, then further call labels
  • Self-hosted local endpoints as a routine production tier
  • Observation of review tool servers (results not yet masked)
Roadmap
  • Masking of tool results and of manifest-editing calls
  • Per-call tenant provenance, so each call gets its own tenant's floor instead of the strictest
← Previous storyBeyond GitLab: other forges