Keep your gateway. Interlok is where the proof lives.

Two vendor-neutral paths that work without your gateway vendor's cooperation. Use either; use both for corroborated evidence.

1 · Chained observer (G2)

Create a chained-observer source with your MCP server's URL. Interlok gives you an upstream URL; put it where your gateway's upstream setting points today:

agent → your gateway → Interlok observer → your MCP server

2 · Decision records (G3): interlok.gateway-decision/1

Send one JSON object, a JSON array, or NDJSON (one record per line) to the webhook URL, signed with the source's key; or push with an API key to POST /api/v1/evidence-sources/<id>/events; or upload a .jsonl file in the console. Unknown fields are rejected, so a typo cannot silently drop evidence.

{"schema":"interlok.gateway-decision/1",
 "event_id":"evt_01J9Z8K6Q1",            // your gateway's own id (required, unique per source)
 "occurred_at":"2026-10-09T14:03:11Z",   // when the gateway decided (required)
 "decision":"approve",                   // allow | deny | approve | hold | error | other
 "tool":"github/create_release",
 "server":"github-mcp",
 "args":{"repo":"acme/api","tag":"v2.4.0"},   // or "args_hash": sha256 of RFC 8785 JSON
 "agent":{"id":"agent-release-bot","type":"agent"},
 "on_behalf_of":{"email":"dev@acme.com","type":"human"},
 "approver":{"email":"lead@acme.com","type":"human"},
 "policy":{"id":"pol_12","name":"releases need a human"},
 "reason":"tag on main",
 "correlation_id":"4bf92f3577b34da6a3ce929d0e0e4736"}

Webhook signature

t=$(date +%s)
sig=$(printf '%s.%s' "$t" "$(cat body.json)" | openssl dgst -sha256 -hmac "$INTERLOK_KEY" -hex | cut -d' ' -f2)
curl -X POST "$INGEST_URL" -H "content-type: application/json" \
     -H "Interlok-Signature: t=$t,v1=$sig" --data-binary @body.json

Interlok-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(key, t + "." + body)>, five-minute tolerance. Up to 500 records or 2 MB per delivery.

Gateway logs vs signed evidence · PolicyLayer · Runlayer · Pricing