KRUTRIM EKAMAgent-identity control plane

Ekam blog · 30 June 2026

How offline token verification works (and why it's fast)

architectureperformanceJWKSES256gateways   7 min read · The Ekam team

Verify offline. Never call home. agentpresents JWT your gatewayverify(jwt)ES256 · iss · aud · expin-process · ~0.05 ms JWKS (cached) introspectonly if live-revoke ~18,000 verifications/sec/core · p99 < 0.1 ms · token ~640 bytes (measured)

The fastest authorization call is the one you don't make. Ekam is designed so the thing on your request hot path — checking a token — never leaves your process. This post is the architecture, the exact verification steps, and honest, reproducible numbers.

The shape of a token

Ekam issues ES256 JWTs (asymmetric P-256). The signing key lives only in Ekam; everyone else verifies with the public half, published at a JWKS endpoint. A decoded agent token carries:

{
  "iss": "https://ekam.olakrutrim.com",
  "sub": "agt_...",                  // the agent (a first-class identity)
  "type": "agent",                   // or "human"
  "aud": "https://your-gateway.example",  // RFC 8707 - valid for ONE resource
  "scope": "models:invoke",          // attenuated by the blueprint
  "act": { "sub": "own_...",         // delegation chain: agent -> owner -> human
           "act": { "sub": "hum_..." } },
  "tenant": "...", "exp": 1750000000
}

Tokens are short-lived (default 15 min, capped at 1 hour) and compact — about 640 bytes in practice — so they fit in a header without bloating every request.

What your gateway actually does

On the hot path your gateway runs five local checks, none of which call Ekam:

  1. Fetch the JWKS once from /.well-known/jwks.json (kid ekam-2026-06) and cache it. Keys rotate by kid, so the cache is safe to hold.
  2. Verify the signature (ES256) against the cached public key.
  3. Check iss equals Ekam, and aud equals your resource (RFC 8707 — a token minted for gateway A is useless at gateway B).
  4. Check exp (and reject the few sensitive scopes you don't allow).
  5. Map the principal to a budget — read sub + the act owner, attribute usage, meter, and (when you charge) bill the owner.

That's it for the common case. The SDK is one import:

import { createEkamVerifier } from "@krutrim/ekam-verify";
const verify = createEkamVerifier({
  issuer: "https://ekam.olakrutrim.com",
  jwksUri: "https://ekam.olakrutrim.com/.well-known/jwks.json",
  audience: "https://your-gateway.example",
});
const principal = await verify(token); // { agentId, ownerId, scopes, tenant, act, ... }

When you need live revocation

Offline verification has one trade-off: a token stays valid until it expires, even if you revoked it 30 seconds ago. Ekam closes that two ways, and you pick per your risk:

Short TTLs + push give you most of the safety of online checks at most of the speed of offline ones.

The numbers (measured, reproducible)

Methodology: a single Node 23 process on a dev laptop, in-process verification after the JWKS cache is warm, averaged over thousands of iterations; HTTP figures are localhost round-trips. These are not a load-tested production benchmark — they're a floor that scales linearly across cores and pods.

OperationResult
Offline verify (hot path)~18,000 / sec / core · mean ~0.055 ms · p50 ~0.05 ms · p99 < 0.1 ms
Broker a token (HTTP, off hot path)p50 ~20 ms · p99 ~23 ms
Introspection (HTTP, optional)p50 ~20 ms
Token size~640 bytes

The point isn't the absolute figures — it's the shape: brokering happens once per task; verifying happens on every request and is effectively free. Security is added off the latency budget that matters.

Verifier docs Cookbook verify-gateway.ts

Was this helpful?

More reading: The shared API key is over: agent identity for developer platforms Identity and billing in one plane: metering agents by the owner Why India needs its own agent-identity control plane 10 things to build on Ekam this week How BharatRouter runs on Ekam: agent identity for an AI gateway

Krutrim Cloud · DR enabled · Open beta  ·  Home · Blog · Docs · Cookbook · Privacy · Terms · Report a bug