KAKUNIN

Enforcement Headers

How to propagate and verify agent certificate serials across service boundaries.

Enforcement Headers

Every Kakunin-issued certificate has a serial number. When your agent sends an outbound HTTP request to another service — or when your gateway receives an inbound request from an agent — the certificate serial travels in a standard header so downstream services can verify the caller's identity without a Kakunin account.

The Header

X-Kakunin-Cert-Serial: <certificate-serial-number>

Example:

POST /v1/risk/approve HTTP/1.1
Host: risk-engine.internal
Authorization: Bearer <agent-jwt>
X-Kakunin-Cert-Serial: 3A:F2:91:CC:04:B7:DE:88:51:2E:9F:07:AC:33:61:D4
Content-Type: application/json

{"trade_id": "T-984231", "amount_usd": 50000}

AI Agent Token Spend Limits & Financial Scopes

To enforce transaction safety and prevent runaway loops, developers configure granular spend limits and action permissions in their agent registrations. These limits are cryptographically bound inside the X.509 certificate.

When downstream APIs receive requests, the enforcement middleware checks these values to ensure the agent does not exceed:

  • max_single_trade_usd: The maximum allowable value per transaction.
  • daily_limit_usd: Cumulative daily limit for the agent instance.
  • permitted_actions: Explicit scopes (e.g. read:invoices, write:drafts) verifying exactly what tools the agent is allowed to invoke.

These parameters function as hard cryptographic boundaries, preventing cost overruns and compliance failures.

Convention

RuleDetail
Header nameX-Kakunin-Cert-Serial (case-insensitive per HTTP spec)
Value formatColon-separated uppercase hex bytes — same as serial_number in GET /v1/agents/:id/certify response
Who sets itThe calling agent (your code), not Kakunin infrastructure
Who reads itReceiving service — passes to GET /v1/verify/:serial or POST /v1/verify/message
Required?Convention, not enforced by Kakunin API — your gateway decides

Verifying an Inbound Request

When a service receives a request with X-Kakunin-Cert-Serial, it can verify the caller in two ways:

1. Identity check only (no signature)

Call GET /v1/verify/:serial (no auth required) to confirm the certificate is active and get the agent's authorized scope:

const serial = req.headers['x-kakunin-cert-serial'];

const res = await fetch(`https://api.kakunin.ai/v1/verify/${serial}`);
const { data } = await res.json();

if (data.status !== 'active') {
  return reply.status(403).json({ error: 'Agent certificate not active' });
}

// data.financial_scope.max_single_trade_usd — compare against request amount
// data.permitted_actions — compare against requested action

2. Signature verification (tamper-proof)

When the calling agent signs its request payload via POST /v1/agents/:id/sign, the receiver verifies the signature using POST /v1/verify/message. The serial ties the signature to the cert:

const serial   = req.headers['x-kakunin-cert-serial'];
const signature = req.headers['x-kakunin-signature'];  // set by agent alongside serial

const res = await fetch('https://api.kakunin.ai/v1/verify/message', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    payload: req.body,
    signature,
    certificateSerial: serial,
  }),
});

const { data } = await res.json();

if (!data.valid) {
  // Signature invalid — possible spoofing attempt
  // Kakunin automatically writes a message_verification_failed event
  // and fires a risk.alert webhook on your behalf
  return reply.status(403).json({ error: 'Agent message signature invalid' });
}

Companion Header for Signed Requests

When using message signing, agents should send both headers together:

X-Kakunin-Cert-Serial: 3A:F2:91:CC:04:B7:DE:88:51:2E:9F:07:AC:33:61:D4
X-Kakunin-Signature: base64encodedSignature==

X-Kakunin-Signature carries the base64 signature returned by POST /v1/agents/:id/sign. The receiving service passes both to POST /v1/verify/message.

Gateway Middleware Pattern

In a multi-agent system, add a single middleware at the gateway layer instead of per-route verification:

// Express / Next.js middleware
async function kakuninEnforce(req, res, next) {
  const serial = req.headers['x-kakunin-cert-serial'];
  if (!serial) return res.status(401).json({ error: 'Missing X-Kakunin-Cert-Serial' });

  const verify = await fetch(`https://api.kakunin.ai/v1/verify/${serial}`);
  const { data } = await verify.json();

  if (data.status !== 'active') {
    return res.status(403).json({ error: `Certificate ${data.status}` });
  }

  req.agent = data;  // { agent_id, agent_name, financial_scope, permitted_actions }
  next();
}

This enforces that every inbound agent request has a valid, active Kakunin certificate — without any per-route logic.

Audit Test Coverage

Audit TestHow this header helps
Test #6 — Inter-Agent SpoofingReceiver calls POST /v1/verify/message with serial + signature; injected messages fail (no valid signature)
Test #8 — Kill SwitchHalted agent's cert is revoked; GET /v1/verify/:serial returns status: revoked; gateway blocks immediately
Test #1 — Trade ReconstructionSerial in each chain event maps to cert at issuance time, including model_hash

Security Notes

  • Never trust the serial alone — always verify against the Kakunin API. The header is a pointer, not proof.
  • Revocation propagates immediately — no TTL cache on the verify endpoint by design. A halted agent is blocked on the next request.
  • Verify endpoint is public — no Kakunin API key needed for GET /v1/verify/:serial or POST /v1/verify/message. Your downstream services don't need a Kakunin account.

On this page