AI Gateway Quickstart
You adopt the AI Gateway by pointing your existing AI SDK at your agent’s gateway URL and using a phantom token as the API key. No new SDK, no code rewrite.1. Create an agent
In the dashboard, go to AI Gateway → New agent. Pick your provider — Anthropic, OpenAI, Google Gemini, Cohere, Azure OpenAI or a self-hosted Ollama-compatible endpoint — paste that provider’s API key, and press Create agent. KnoxCall does the rest in one step: it encrypts the key into a normal KnoxCall secret, creates the upstream route that injects it, creates the gateway if you do not have one yet, creates the agent, and mints your first capability key. Azure OpenAI and self-hosted endpoints also ask for the base URL of your own resource, because that address is specific to you. When the agent is created you get two things:- an agent URL —
https://<your-slug>.knoxcall.com/v1/ai/<agent-slug>(sandbox:https://sandbox-<your-slug>.knoxcall.com/...) - a phantom token —
kp_live_a_…(shown once at mint time)
The provider key you paste is envelope-encrypted with your tenant key before it is stored, and no endpoint ever returns it. It is injected at the upstream hop, so clients holding the capability key never see it.
Prefer to wire it up piece by piece? New Gateway still creates an empty gateway, and the agent form still lets you point at an existing secret instead of pasting a key.
The data plane is served on your tenant’s proxy subdomain (
<slug>.knoxcall.com), not api.knoxcall.com. Always use the agent_url returned at agent creation as your base URL.2. Swap your base URL
Anthropic SDK
OpenAI SDK
Node / TypeScript
The provider’s own Node SDK works unchanged — same swap, same two lines:import OpenAI from 'openai' and pass the same baseURL / apiKey.
curl
What comes back
The provider’s own response shape, unchanged — the gateway does not wrap it:X-Request-Id is on every response and is the key into your audit trail for that
exact call. The rest appear only when there is something to say — see
the header reference below. A refusal replaces the body with
an error envelope; nothing is ever silently degraded.
That’s it. The call is now authenticated by the phantom token, screened by the prompt firewall, PII-redacted if a policy applies, counted against the agent’s budget, and recorded with per-call cost attribution.
3. Authentication schemes
The phantom token can be sent three ways — use whichever your SDK makes easiest:DPoP proof header on every request.
Everything you need is on the agent’s Connect panel
You do not have to keep the values from the create wizard. Open the agent (AI Gateway → your gateway → the agent) and the Connect panel at the top of the page has:- the agent URL, copyable — the base URL your SDK points at;
- the environment variables for that agent, already filled in
(
ANTHROPIC_BASE_URL/OPENAI_BASE_URLand the key variable your provider’s SDK reads), so a working shell is one paste away; - a curl smoke test shaped for that agent’s provider;
- the newly issued capability key, the one time it is shown, when you mint from the Capability keys list below it;
- a Playground button, which runs a prompt through this agent’s real data plane and shows what the gateway did to it.
A capability key is displayed once, at mint time. If you lose it, revoke it
and mint another; there is no endpoint that returns an existing token’s value.
4. Streaming
Streaming works unchanged — setstream: true (or Accept: text/event-stream). PII redaction runs inside the stream, so redactions appear as the tokens arrive rather than after the response completes:
Try it from the dashboard: the Playground
Every agent has a Playground (agent page → Playground). It sends the prompt you type through that agent’s own/v1/ai/<slug> data plane — the same URL your
SDK uses — with a one-shot capability key that expires the moment it is used, and
shows what the gateway did to the call beside the reply:
- the redaction diff — your prompt with every detected value highlighted, next to the exact text the provider received, with the format-preserving surrogates that replaced them;
- the firewall verdict for the prompt;
- cache outcome, model, latency and cost for the request.
ai_gateway_usage,
ai_gateway_firewall_events) and the PII token map for its conversation — not
recomputed for display. Where a row is missing the panel says so rather than
showing a reassuring default. The Playground spends the same provider tokens a
real call does, and is subject to whatever budget the agent has: a quickstart
agent starts with none, so set one on the agent before handing the Playground to
a wider team.
From the command line
The KnoxCall CLI carries anai command group over the same /v1 control plane,
so gateways, agents, minting and spend are all reachable without opening the
dashboard. It reuses the credential knoxcall login writes — no keys in scripts,
and the tenant is resolved from the token, so no tenant header:
Useful request/response headers
Response caching
Caching is off by default and is set per agent withcache_mode — in the
dashboard on the Agent’s Budgets & cache tab, or over the /v1 Management
API. An agent’s cache_mode is off unless you set it deliberately.
A cache hit costs $0, is recorded with
cost_source = 'cache_hit', does not
charge the agent’s budget, and sets X-Knox-AI-Cache: exact or semantic.
What the hit rate actually is
The Agent’s Budgets & cache tab reports, over the last 30 days: hit rate, exact hits, near (semantic) hits, misses, bypassed requests, stored entries, and — for an agent insemantic mode — how many requests approximate matching actually
ran for, its own hit rate, and how many degraded, with the reason.
Two things about that report are worth knowing before you read a number off it.
Bypassed is not a miss. A request that streamed, that hit a response-direction
guardrail hook, that ran on an agent with a customer-managed key, or that the
gateway could not attribute to a token, was never eligible for the cache. Those
are counted beside the rate and never inside it. An agent whose traffic is all
stream: true will show a large bypass count and no hit rate, which is the
truthful answer rather than 0%.
Before 2026-09-08 this number was wrong — for an agent in exact mode it read
100% from its first hit onward, because misses were never recorded. If you looked
at it before that date, look again.
The number we have, and what it is worth. On our reference fixture
(
support-assistant-v1: 7 conversations, 30 requests, a mix of verbatim repeats
and paraphrases) at the default 0.95 threshold, 13.3% of requests were served
from cache — three exact, one approximate — with no false matches and no
cross-caller hits. At 0.90 it is 30%; the exact-cache floor, which needs no
embedding model at all, is 10%.That is a fixture measurement produced with a substitute embedder, because our
test suite may never call a provider. It is not a forecast of your traffic, and we
will not dress it up as one: how much a response cache saves depends almost
entirely on how repetitive your prompts are. The number that matters is the one on
your own Agent’s cache panel.Isolation — what a hit can and cannot cross
Every cache entry is keyed on the phantom token that produced it and the conversation id, in addition to the agent and the request body. That means:- a cached response never crosses tenants;
- it never crosses tokens, even inside one tenant — two users of the same agent do not serve each other’s answers, whatever conversation ids they send;
- it never crosses conversations for one token;
- a request the gateway cannot attribute to a token neither reads nor writes the cache at all.
X-KC-Conversation-Id is a client header — still worth making
unguessable and unique per end-user conversation, since it partitions a single
token’s own cache, but it is no longer the only thing standing between two
callers.
Semantic matching — the requirements
Semantic matching runs only when all four of these hold (cache/index.ts,
semanticEnabled). Each one is a boundary, not a limitation to work around:
cache_modeissemanticandcache_embedding_modelis set.- The request carries an
X-KC-Conversation-Id. Approximate matching needs an isolation boundary to be confined to; a stateless request has none, so it is exact-only. - The agent is not using reversible PII tokenization — that is,
pii_request_modeisoffandpii_response_modeisredact. Either half on its own is enough to keep semantic matching off. Conversation scoping already makes it safe, but approximate matching against a per-conversation token map is held apart until a dedicated review clears it. Tokenizing agents still get exact caching. - The upstream exposes an OpenAI-compatible
/v1/embeddingson the same origin as the chat endpoint. Anthropic has no embeddings API, so an Anthropic-backed agent is exact-only.
Caching applies to buffered responses only. A streaming request is never served
from cache and never stored, so an agent whose traffic is all
stream: true will
see no hits.Next steps
Bring your own key
Why AI features use your own Anthropic key, and how to add it.
Tokens & DPoP
Mint scoped, sender-constrained tokens for agents and CI.
Model & output policy
Pin which models an agent may call, and the shape of what comes back.
Limits & availability
The ceilings the data plane enforces, and what we do and don’t promise.