Zerker Routing & Proxy
Gateway sits in the path of every call.
A caller invokes the agent through Gateway instead of calling the upstream directly. Gateway resolves the upstream, injects the agent's credential, forwards the body untouched, and records what happened. The upstream sees its own protocol.
Two modes
Transactional or streaming.
The same agent is reachable two ways, and the caller picks per call. Both return an inv_ ID, so every call can be looked up later.
Transactional
$ curl localhost:8080/v1/proxy/{id} \ -H "Authorization: Bearer $TOKEN" -d '{}' 202 Accepted X-Zerker-Invocation-ID: inv_019842… { "invocation_id": "inv_019842…" }
Returns immediately, runs the upstream call server-side. Poll /v1/proxy/{id}/invocations/{inv_id} for the result. Suits long-running work.
Streaming
$ curl -N localhost:8080/v1/proxy/{id}/stream \ -H "Authorization: Bearer $TOKEN" -d '{}' ← request and response stream through verbatim, with no buffering
A long-lived connection for token-by-token responses or large payloads. The invocation ID is set on the response before any upstream byte is written, so a call is traceable even when it fails mid-stream.
The mechanic
Bodies pass through untouched.
Gateway forwards the request body unmodified. No wrapper, no re-encoding, no schema of ours in the middle. An existing upstream needs no change to sit behind it, and leaving later means no format to unpick.
| Header | What it does | Set by |
|---|---|---|
X-Request-ID |
Correlates the call end to end. Yours is honoured; if absent, one is injected | Caller or gateway |
X-Zerker-Model |
Optional label recorded on the invocation, capped at 256 bytes | Caller |
Authorization |
Always stripped. The upstream never sees the caller's token | Gateway |
Headers forward through a block-list, not a pass-all. The caller's token is removed and the agent's own credential is injected in its place. The upstream sees your integration, never the individual caller.
The transactional endpoint caps request bodies at 32 MiB. The streaming endpoint has no cap, because it never buffers.
Policy
Refused calls are never charged.
Policy is evaluated on the proxy path, after the call is parsed and before the payment gate. A request your policy denies gets a 403, never a 402 first.
| Action | What happens | Recorded |
|---|---|---|
allow |
Forwarded unchanged — also the behaviour when nothing matches and the policy's default is allow | Yes |
warn |
Forwarded, plus an X-Zerker-Policy-Warning header on the transactional response |
Yes |
deny |
Rejected with 403 and a single coarse reason. Never forwarded |
Yes |
The no-match and on-error actions come from your policy, not from us. You decide whether an unevaluable call fails open or closed. A tenant with no policy sees no change.
When you get it wrong
SSRF blocked at request time.
Every check that can run before the upstream call does. Error responses say what happened without describing where anything lives.
| What you did | What you get | Why |
|---|---|---|
Invoked a pending, suspended, or soft-deleted agent |
422 |
Decided from the catalog record, before any upstream call is made |
| Pointed at an upstream that won't answer | 502 |
Transient failures are retried. A circuit breaker opens on an upstream that keeps failing |
| Pointed at an upstream that answers too slowly | 504 |
|
| Sent a call your policy denies | 403 |
One coarse reason. A precise one would let a caller map your rules by probing |
| Read any error body above | No internals | Error bodies never carry upstream addresses or internal detail |
One limit to know. If the policy store is unreachable, your on-error setting cannot be read, so Gateway fails closed and returns 500 until it recovers.
Where the line falls
Routing is open source.
Everything that carries a request from your caller to your upstream and back is Apache-2.0.
| Capability | Tier |
|---|---|
| Transactional and streaming proxy, verbatim body forwarding | OSS |
| Credential injection, SSRF guarding, retries and the circuit breaker | OSS |
| Policy evaluation on the proxy path | OSS |
| Governance and a control plane across tenants | Commercial |
Next
The proxy forwards bytes. MCP lets it read them.
Declaring an agent's protocol as MCP keeps everything on this page and adds method and tool visibility, plus a retry rule that knows which calls are safe to repeat.