Deploy AI agent governance in 4 steps. One container, no code changes, no engineering sprint.
The d3cipher Gateway is a Docker container you deploy in your own infrastructure. Your AI agents talk to it instead of directly to OpenAI, Anthropic, or any other provider. The gateway enforces governance policies — audit trail, kill switch, token budgets, encrypted transcripts — without touching a single line of agent code.
Your prompts and responses never leave your network in plaintext. Only cryptographic stamps and encrypted blobs reach the d3cipher cloud. The server cannot read your content. Only your Account Key can decrypt it.
Your Agent d3cipher Gateway AI Provider
(no changes) (your network) (OpenAI, etc.)
| | |
|--- API request ---->| |
| |-- stamp (metadata) ----->| d3cipher Cloud
| |-- encrypt body --------->| (can't read it)
| | |
| |--- forward request ----->|
| |<-- provider response ----|
| | |
| |-- stamp response ------->| d3cipher Cloud
| |-- encrypt response ----->| (can't read it)
|<-- response --------| |
| | |
LockStock images are hosted on a private GitLab Container Registry. You'll receive registry credentials (username + token) when you sign up. Use them to authenticate Docker:
docker login registry.gitlab.com -u deploy-yourcompany -p your-registry-token
After authenticating, you can pull both the gateway and admin-tools images:
# Gateway (production middleware — runs as a service) docker pull registry.gitlab.com/d3cipher/lockstock-images/gateway:v3.1.0 # Admin-Tools (compliance CLI — run on-demand) docker pull registry.gitlab.com/d3cipher/lockstock-images/admin-tools:v3.1.0
Why a private registry? Per-customer access tokens let us revoke access individually, track image pulls, and keep the distribution surface controlled. Your token is unique to your account — don't share it.
Sign up to create your account. You'll receive two API keys immediately:
| Credential | What It Is | Who Holds It |
|---|---|---|
Admin Keylsk_admin_... |
API key for the dashboard — provisioning, fleet management, auditing | You (compliance / admin) |
Gateway Keylsk_gateway_... |
API key for the Docker container — stamp-only, least privilege. Even if compromised, it cannot access your data or settings. | IT / DevOps |
Then open the dashboard and click Generate Account Key. This creates your encryption key:
Account Key64-char hex |
Encryption key for transcripts. Generated entirely in your browser — the server never sees it, only a verification hash. This is what lets you read the exact prompts and responses your agents processed, decrypted in your browser. The server stores only ciphertext it cannot read. | You + IT (for the gateway container) |
Save your Account Key immediately. It is shown once and cannot be recovered. If you lose it, encrypted transcripts are permanently unreadable — that's the proof that we can't read them either.
Send IT the Gateway Key and Account Key via a secure channel, along with this page.
Liberty is our free, open-source secrets manager.
It encrypts your keys to your hardware fingerprint — no .env files, no plaintext, no leaks.
The gateway CLI reads from Liberty automatically.
# Install Liberty pip install liberty-secrets # Store your LockStock keys (one time) liberty add LOCKSTOCK_GATEWAY_KEY "lsk_gateway_..." liberty add LOCKSTOCK_ACCOUNT_KEY "85d7a50b..." liberty add LOCKSTOCK_UPSTREAM_URL "https://api.openai.com" liberty add OPENAI_API_KEY "sk-..."
That's it. From now on, every lockstock-gateway command reads from the vault automatically.
Agent IDs are written back to Liberty when you provision, so everything stays encrypted and hardware-bound.
Why Liberty? Your Account Key decrypts agent transcripts. Storing it in a
plaintext .env file defeats the purpose of envelope encryption. Liberty keeps
it encrypted at rest, bound to your hardware, and decrypted only when you need it
(or injected at runtime with liberty exec -- cmd).
Learn more →
If you stored your keys in Liberty (Step 2), one command does everything:
# Provision an agent and start the gateway (reads keys from Liberty)
lockstock-gateway provision --name MY_AGENT
lockstock-gateway start
Or run the container directly with explicit env vars:
docker run -d --name d3cipher-gateway \ -e D3CIPHER_API_KEY=lsk_gateway_your_key_here \ -e UPSTREAM_URL=https://api.openai.com \ -e ACCOUNT_KEY=your_64char_hex_account_key \ -p 4000:4000 \ registry.gitlab.com/d3cipher/lockstock-images/gateway:v3.1.0
| Variable | Description |
|---|---|
D3CIPHER_API_KEY required |
Gateway Key (lsk_gateway_*) from your d3cipher dashboard. Stamp-only, least-privilege — the container cannot access admin endpoints. |
UPSTREAM_URL required |
The AI provider your agents call. Examples: https://api.openai.com, https://api.anthropic.com, https://bedrock-runtime.us-east-1.amazonaws.com |
ACCOUNT_KEY optional |
64-character hex key for encrypted transcript storage. Enables the Auditor tab in your dashboard. Without it, you still get audit trail + kill switch. |
AGENT_ID optional |
Default agent name when agents don't identify themselves via header. If not set, each agent must send the X-D3cipher-Agent header. |
LOCKSTOCK_URL optional |
Override the d3cipher cloud URL. Only needed for on-premise deployments. Defaults to production. |
Verify it's running:
curl http://localhost:4000/healthz
# {"status": "ok", "agents_active": 0, "inflight": 0}
Kubernetes? The gateway exposes /healthz for liveness probes
and /metrics for Prometheus scraping. Single replica recommended (agent state is in-memory).
Change one environment variable wherever your agents run:
# Before (direct to OpenAI) OPENAI_BASE_URL=https://api.openai.com # After (through d3cipher Gateway) OPENAI_BASE_URL=http://gateway-host:4000
To identify which agent is which in the dashboard, add one HTTP header to each agent's configuration:
X-D3cipher-Agent: customer-support-bot
If all your agents share a single identity (or you only have one agent), set AGENT_ID
on the container instead and skip the header.
That's it. No SDK to install. No middleware to inject. No code changes. The agents think they're talking to OpenAI. They're actually talking to a gateway in your own network that enforces your governance policies.
Refresh your dashboard. Agents appear as they make their first call.
Lock any agent instantly from the dashboard. The gateway returns a 429 error to the agent. The request never reaches the AI provider. Unlock when ready.
Set per-agent spending limits. When an agent exhausts its token budget, the circuit breaker
trips automatically. The gateway also clamps max_tokens on each request to prevent
a single call from blowing the remaining budget.
If you provided an Account Key, open the Auditor tab in the dashboard. Enter your key. Read the full content of every prompt and response, decrypted entirely in your browser. The d3cipher server stores only ciphertext it cannot read.
Sentinel ML monitors agent request velocity using incremental statistical analysis. Unusual spikes trigger alerts. The circuit breaker can automatically halt agents that exceed defined thresholds.
Prompts and completions. API keys. Customer data. Request and response bodies. The Account Key. Everything that matters stays behind your firewall.
Agent ID. Task type. Timestamp. Token count. Sequence number. Cryptographic hashes. Encrypted blobs (that only your Account Key can decrypt). Governance metadata — not your data.
LockStock ships two Docker images built from the same codebase. They share the same cryptographic libraries but have a hard trust boundary between them:
| Gateway | Admin-Tools | |
|---|---|---|
| Image | d3cipher/lockstock-images/gateway |
d3cipher/lockstock-images/admin-tools |
| Purpose | Reverse proxy — stamp, encrypt, forward | Compliance tooling — decrypt transcripts, rotate keys |
| Runs as | Service (port 4000, always on) | CLI (on-demand, not a service) |
| Can encrypt | Yes | Yes |
| Can decrypt | No — decrypt function stripped at build time | Yes — full decrypt capability |
| Lives on | Your infrastructure (next to agents) | Operator's machine (compliance officer) |
| CLI commands | lockstock-gateway start|stop|provision|agents |
lockstock-audit, lockstock-rotate |
Why strip decrypt from the gateway? The gateway sits in your production network, handling live traffic. If it were compromised, an attacker with decrypt capability could read every transcript. By removing the decrypt function at build time (and verifying its absence), a compromised gateway can only see ciphertext — exactly what the d3cipher cloud sees. Decryption happens offline, on the operator's machine, with the Admin-Tools container.
The admin-tools container provides two CLI commands for compliance officers:
# Decrypt and read agent transcripts docker run --rm registry.gitlab.com/d3cipher/lockstock-images/admin-tools:v3.1.0 \ lockstock-audit \ --account-key "your-64-char-hex-key" \ --agent-id "agent_0d20202e_claude_d3cipher" \ --api-key "lsk_admin_..." \ --format json # Rotate your Account Key (re-wrap all agent encryption keys) docker run --rm registry.gitlab.com/d3cipher/lockstock-images/admin-tools:v3.1.0 \ lockstock-rotate \ --old-key "current-64-char-hex-key" \ --new-key "new-64-char-hex-key" \ --api-key "lsk_admin_..." \ --dry-run
lockstock-audit fetches encrypted blobs from the d3cipher cloud, unwraps the encryption keys
using your Account Key, and outputs the plaintext transcripts locally. Nothing is sent back to the server.
lockstock-rotate re-wraps all encryption keys under a new Account Key — use it if your
Account Key is compromised or as part of a regular key rotation policy.
version: "3.8"
services:
d3cipher-gateway:
image: registry.gitlab.com/d3cipher/lockstock-images/gateway:v3.1.0
ports:
- "4000:4000"
environment:
D3CIPHER_API_KEY: "${D3CIPHER_GATEWAY_KEY}" # lsk_gateway_* (stamp-only)
UPSTREAM_URL: "https://api.openai.com"
ACCOUNT_KEY: "${ACCOUNT_KEY}"
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4000/healthz"]
interval: 30s
timeout: 5s
retries: 3
apiVersion: apps/v1
kind: Deployment
metadata:
name: d3cipher-gateway
spec:
replicas: 1
selector:
matchLabels:
app: d3cipher-gateway
template:
metadata:
labels:
app: d3cipher-gateway
spec:
containers:
- name: gateway
image: registry.gitlab.com/d3cipher/lockstock-images/gateway:v3.1.0
ports:
- containerPort: 4000
env:
- name: D3CIPHER_API_KEY
valueFrom:
secretKeyRef:
name: d3cipher-secrets
key: api-key
- name: UPSTREAM_URL
value: "https://api.openai.com"
- name: ACCOUNT_KEY
valueFrom:
secretKeyRef:
name: d3cipher-secrets
key: account-key
livenessProbe:
httpGet:
path: /healthz
port: 4000
initialDelaySeconds: 5
periodSeconds: 30
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: d3cipher-gateway
spec:
selector:
app: d3cipher-gateway
ports:
- port: 4000
targetPort: 4000
type: ClusterIP
Single replica recommended. The gateway maintains per-agent state in memory (DEK cache, budget tracking, connection pools). Multiple replicas would create independent state per pod. Horizontal scaling is on the roadmap.
| Path | Purpose |
|---|---|
/healthz |
Liveness probe. Returns 200 if gateway is up and d3cipher cloud is reachable, 503 if degraded. |
/metrics |
Prometheus-compatible metrics: request count, rejection count, and latency per agent. |
/* |
Everything else is proxied to UPSTREAM_URL through LockStock governance middleware. |
Gateway returns 400 "Missing X-D3cipher-Agent header": Either set AGENT_ID on the container for a default, or add the X-D3cipher-Agent header to each agent's HTTP requests.
Gateway returns 429 "Token budget exhausted": The agent's token budget is depleted. Go to the dashboard, increase the budget or click Unlock to reset the counter.
Gateway returns 409 "Chain hash mismatch": The agent's chain has forked — a duplicate agent, a replay attempt, or a cloned credential. This is a hard stop. Investigate immediately.
Gateway returns 503 "LockStock stamp rejected": The circuit breaker has tripped (velocity anomaly or manual lock). Check the dashboard for the reason. Click Unlock to restore access.
/healthz returns 503: The gateway can't reach the d3cipher cloud. Check network connectivity and LOCKSTOCK_URL if set.
Agents not appearing in dashboard: Make sure the agents are actually sending requests through the gateway (check OPENAI_BASE_URL points to the gateway, not directly to OpenAI).
Transcripts show "Blob not available": The ACCOUNT_KEY environment variable wasn't set when those requests were processed. Set it and future transcripts will be encrypted and stored.