compression with a quality contract

Deploy & Security

Three deployment topologies, one security model. The proxy is designed to be safe by default — it binds localhost, forwards only to the single configured upstream, and never touches your secrets.

Deployment topologies diagram

Deployment topologies

Topology 1

Local dev sidecar

Run distil proxy on your laptop alongside your application. Default bind is 127.0.0.1:8788 — not reachable from the network. Zero infra overhead.

Topology 2

Container sidecar

Add the proxy as a sidecar container in the same Pod or Compose stack. Your app container calls http://localhost:8788; only the sidecar egresses to the upstream API.

Topology 3

Shared gateway

Run one proxy instance accessible to multiple services on a private network. Bind to an internal interface (--host 0.0.0.0), keep it behind a firewall or service mesh, never expose it to the public internet.

Local dev sidecar

# Terminal 1
distil proxy --port 8788 --upstream https://api.anthropic.com

# Terminal 2 — your application
ANTHROPIC_BASE_URL=http://127.0.0.1:8788 python my_agent.py

Container sidecar (Docker Compose)

services:
  app:
    build: .
    environment:
      - ANTHROPIC_BASE_URL=http://distil-proxy:8788
    depends_on:
      - distil-proxy

  distil-proxy:
    image: python:3.12-slim
    command: >
      sh -c "pip install distil-llm &&
             distil proxy --host 0.0.0.0 --port 8788
               --upstream https://api.anthropic.com"
    ports: []  # not exposed externally

Shared gateway (Kubernetes)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: distil-proxy
spec:
  replicas: 2
  template:
    spec:
      containers:
      - name: distil
        image: python:3.12-slim
        command:
          - sh
          - -c
          - pip install distil-llm && distil proxy --host 0.0.0.0 --port 8788
        env:
          - name: DISTIL_UPSTREAM
            value: https://api.anthropic.com
---
apiVersion: v1
kind: Service
metadata:
  name: distil-proxy
spec:
  clusterIP: ...  # internal only — no LoadBalancer type
  ports:
  - port: 8788

Security model

Localhost-only by default

The proxy binds to 127.0.0.1 by default. It is not reachable from any other host unless you explicitly pass --host 0.0.0.0. In production topologies, always restrict network access to the proxy with a firewall rule or service mesh policy.

Single configured upstream — no SSRF

The upstream URL is set once at startup (--upstream). The proxy does not read the destination from the incoming request, so a malicious request body cannot redirect traffic to an attacker-controlled server. All outbound connections go to exactly one destination.

No SSRF surface. The upstream is a constructor argument baked into the handler class at startup, not read from request headers or the request body. There is no mechanism for an incoming request to change where the proxy connects.

No request body logging

The proxy overrides log_message to suppress all request logs. It reads the request body to compress it, then discards it — nothing is written to disk or stdout. API keys, message content, and tool results are never logged.

# In distil/proxy.py — request logs are silenced by design
def log_message(self, fmt: str, *args: object) -> None:
    pass

Auth-mode gating — lossless subscriptions stay lossless

Anthropic's cache-control and subscription/OAuth sessions require byte-for-byte stability in the system prefix. Pass --lossless-only to restrict the proxy to Tier-0 lossless transforms only (JSON minification, run-length collapse). No digests, no content changes that could break a cached prefix or OAuth flow.

distil proxy --lossless-only --upstream https://api.anthropic.com

Hop-by-hop header stripping

The proxy strips connection-specific headers (Connection, Transfer-Encoding, Keep-Alive, etc.) before forwarding. This prevents header injection attacks and ensures clean HTTP/1.1 semantics at the upstream boundary.


Data retention and zero-data retention (ZDR)

Distil itself retains no data. The proxy is stateless: it reads a request, compresses the messages array in memory, forwards it, and relays the response. Nothing is written to disk.

If your Anthropic contract includes Zero Data Retention (ZDR), the compressed payload forwarded by the proxy is covered by the same ZDR terms as a direct call — Distil does not introduce any additional retention surface.

RestoreStore is in-process only. The Tier-1 reversible digest stores original text in a Python dict for the duration of a single request. It is never persisted, never sent to the model, and is garbage-collected when the request handler exits.

Threat model summary

ThreatMitigation
Network exposure of the proxy Binds 127.0.0.1 by default; explicit --host required to listen externally.
SSRF via request body Upstream is set once at startup; cannot be overridden by request content.
Secret exfiltration via logs Request logging is disabled; no body content is written anywhere.
Cache prefix corruption --lossless-only mode restricts to byte-stable Tier-0 transforms only.
Header injection Hop-by-hop headers are stripped before forwarding in both directions.
Data retention beyond request Stateless handler; RestoreStore is in-process, not persisted.