KKRNLA
API reference · v1

KRNLA API contract

Four separate surfaces, versioned independently: the control plane configures, the gateway enforces, agents communicate, telemetry is read back. Control-plane routes authenticate with the dashboard session; gateway routes authenticate with an agent credential.

Authentication

Gateway calls carry the agent credential issued in the dashboard. The organization is derived from the credential — there is no organization parameter on any gateway endpoint.

Authorization: Bearer krn_live_xxxxxxxx_...
# or
X-KRNLA-Agent-Key: krn_live_xxxxxxxx_...

Response envelope

Every response is { ok, data } on success and { ok: false, error } on failure. Gateway responses always include the decision envelope in data, so an SDK can read data.allowed whether the request was allowed or blocked.

{
  "ok": false,
  "error": { "code": "POLICY_BLOCKED", "message": "Request blocked by an organization policy." },
  "data": {
    "allowed": false,
    "code": "POLICY_BLOCKED",
    "reason_code": "PII_DETECTED",
    "policy_id": "6a91...",
    "decision": "block",
    "trace_id": "tr_a1b2c3"
  }
}

The response never contains the detected value, the payload that triggered it, or internal error details.

Gateway · POST /api/gateway/v1/evaluate

Governance only: KRNLA decides, the caller keeps its own transport.

curl -X POST https://krnla.com/api/gateway/v1/evaluate \
  -H "Authorization: Bearer $KRNLA_AGENT_KEY" \
  -H "content-type: application/json" \
  -d '{
        "destination": "https://api.openai.com/v1/chat/completions",
        "model": "gpt-4o-mini",
        "payload": { "prompt": "customer SSN is 123-45-6789" }
      }'

Gateway · POST /api/gateway/v1/messages

KRNLA-mediated agent-to-agent delivery. Agent A names Agent B; KRNLA authenticates, governs and delivers to Agent B's inbound URL. No retry is performed — an agent message may be non-idempotent, so the delivery status is reported instead.

curl -X POST https://krnla.com/api/gateway/v1/messages \
  -H "Authorization: Bearer $KRNLA_AGENT_KEY" \
  -H "content-type: application/json" \
  -d '{ "to": "billing-agent", "payload": { "task": "reconcile invoice 88213" } }'

KRNLA delivers to the destination agent as:

POST <inbound_url>
X-KRNLA-Trace-Id: tr_a1b2c3
X-KRNLA-Source-Agent: support-agent

{ "from": "support-agent", "trace_id": "tr_a1b2c3", "payload": { ... } }

Gateway · POST /api/gateway/v1/llm

Governed agent-to-LLM proxying. The provider credential stays yours: pass it in X-KRNLA-Upstream-Authorization and KRNLA forwards it upstream without logging or storing it. With stream: true the response is governed chunk by chunk and never fully buffered.

curl -N -X POST https://krnla.com/api/gateway/v1/llm \
  -H "Authorization: Bearer $KRNLA_AGENT_KEY" \
  -H "X-KRNLA-Upstream-Authorization: Bearer $OPENAI_API_KEY" \
  -H "content-type: application/json" \
  -d '{
        "destination": "https://api.openai.com/v1/chat/completions",
        "stream": true,
        "payload": { "model": "gpt-4o-mini", "stream": true,
                     "messages": [{ "role": "user", "content": "summarize ticket 4412" }] }
      }'

Response headers carry the decision: X-KRNLA-Decision, X-KRNLA-Reason-Code, X-KRNLA-Policy-Id, X-KRNLA-Trace-Id.

Control plane

GET/api/control/v1/meSession identity and its organization
GET / PUT/api/control/v1/organizationGateway configuration for the tenant
GET / POST/api/control/v1/agentsList agents · register an agent (returns the key once)
GET / PUT / DELETE/api/control/v1/agents/:idRead, update status or inbound URL, delete
POST/api/control/v1/agents/:id/rotate-keyIssue a new credential, invalidate the old one
GET / POST/api/control/v1/policiesList and create structured policies
GET / PUT / DELETE/api/control/v1/policies/:idRead, edit, enable/disable, delete
GET/api/control/v1/activityPaginated, server-side-filtered security events
GET/api/control/v1/overviewAggregated metrics from rollups

Operations

GET/api/gateway/v1/healthPublic liveness check, no tenant data
GET/api/internal/v1/metricsKRNLA infrastructure metrics (session-authenticated)

Policy model

A policy is data, not text for a model to interpret. Conditions reference normalized facts produced by the deterministic detector; the engine evaluates policies in ascending priority and the first match decides.

{
  "name": "Customer data protection",
  "priority": 10,
  "action": "block",
  "reason_code": "PII_DETECTED",
  "conditions": { "match": "all",
                  "conditions": [{ "fact": "PII_DETECTED", "operator": "eq", "value": true }] },
  "scope": { "channels": ["agent_to_llm"], "source_agents": [], "models": [] }
}

Facts available today: PII_DETECTED, PII_TYPES, PII_MATCH_COUNT, SECRET_DETECTED, SECRET_TYPES, PROMPT_INJECTION_SUSPECTED, DESTINATION_ALLOWLISTED, DESTINATION_HOST, SOURCE_AGENT_NAME, MODEL, TOOL, REQUEST_BYTES, TOKEN_ESTIMATE, CHANNEL. Actions today: ALLOW, BLOCK, REDACT.

Error codes

401UNAUTHENTICATEDMissing or unknown agent credential
403POLICY_BLOCKEDA policy blocked the request
403AGENT_DISABLEDAgent disabled or credential revoked
404DESTINATION_NOT_FOUNDDestination agent not in this organization
413REQUEST_TOO_LARGEAbove the configured request size limit
429RATE_LIMITEDOrganization or agent limit exceeded
503CONFIG_UNAVAILABLEPolicy configuration unavailable and fail mode is closed
504UPSTREAM_TIMEOUTDestination exceeded the configured timeout