Kong AI Gateway + Meridian
Send Kong AI Gateway audit logs to Meridian with http-log, map Kong consumers to agents in the gateway key registry, and verify usage in the ledger.
Available to customers now. We confirm the first import with you in a sandbox before production.
Best for: Teams standardizing on Kong AI Gateway
Kong AI Gateway + Meridian gateway ingest
Egress: api.onaro.io:443 (HTTPS)
What it does
Kong AI Gateway writes an AI audit entry for every request that passes through its ai-proxy plugin: the provider, the model requested and returned, prompt and completion tokens, and who made the call. Kong's http-log plugin can send those entries to any HTTP endpoint. Point it at Meridian and each request becomes a usage record, mapped to the Open Agent Spend Attribution (OASA) 0.2.0 usage record, tied to an agent through the Kong consumer that made it, and rolled into the spend ledger every hour.
You run Kong. Onaro does not host or proxy your traffic, and Meridian stores no Kong admin credentials. The only data that leaves your boundary is the log entry Kong already builds, sent by http-log to api.onaro.io over HTTPS.
There is no Connect card for Kong in the Meridian app. Setup is a key from Onaro, two plugins on your AI routes, and a mapping from Kong consumers to agents.
Prerequisites
- Kong Gateway 3.9.x with AI Gateway. Meridian's mapping is pinned to the 3.9.0 log shape described in Kong's AI Gateway audit log reference and configured with the HTTP Log plugin (both verified as of 2026-10-07).
- Kong consumers with an authentication plugin (for example key-auth) on the AI routes. Meridian attributes spend by consumer username. Without consumers, it falls back to the credential id, then the client IP address, which rarely identifies an agent.
- A Meridian ingest key. An organization admin creates it in Meridian: open Settings → Usage ingest keys, select Create key, name it after this gateway (for example "Kong production"), and copy the key from the dialog. The key has the
meridian:ingestscope only. The keys created on the Discovery event keys page are a different kind and are rejected by this endpoint with 401. The key is shown once; store it in Kong's vault or your secret manager. See Manage ingest keys. - Outbound HTTPS from the Kong data plane to
https://api.onaro.io. - Access to the Gateway key registry in Meridian at
/meridian/settings/gateway-keys. The page is not linked from the Settings menu yet; open it by path in the Meridian app.
Setup
1. Confirm the endpoint
POST https://api.onaro.io/v1/meridian/ingest/gateways/kong Authorization: Bearer MERIDIAN_INGEST_KEY Content-Type: application/json
The body is one Kong log entry or a JSON array of them, up to 1,000 per request.
2. Add ai-proxy statistics and http-log to the route
The ai-proxy plugin only writes token usage into the log when logging.log_statistics is on. http-log sends the entry to Meridian. Batch the queue: with a batch size of 1, every model call is its own HTTP request and counts against your key's per-minute and per-day limits.
_format_version: "3.0" services: - name: ai-chat url: https://api.openai.com routes: - name: ai-chat-completions paths: - /v1/chat/completions plugins: - name: key-auth - name: ai-proxy config: route_type: llm/v1/chat logging: log_statistics: true log_payloads: false auth: header_name: Authorization header_value: Bearer UPSTREAM_PROVIDER_KEY model: provider: openai name: gpt-4o - name: http-log config: http_endpoint: https://api.onaro.io/v1/meridian/ingest/gateways/kong method: POST content_type: application/json headers: Authorization: Bearer MERIDIAN_INGEST_KEY queue: max_batch_size: 100 max_coalescing_delay: 5
| Placeholder | Value |
|---|---|
MERIDIAN_INGEST_KEY | The meridian:ingest key created in Settings → Usage ingest keys (a Kong vault reference works here) |
UPSTREAM_PROVIDER_KEY | Your own provider key; Meridian never sees it |
Set the content type with content_type, not in headers. Keep log_payloads off: Meridian does not read prompts or responses, and leaving them out keeps message content inside your boundary. Keep max_batch_size at or below 1,000.
3. Cover every AI route
ai-proxy is configured per route, because each route targets one provider and model. http-log does not need to be: you can attach it once to the service, or globally, so new AI routes report to Meridian without extra configuration. If you attach it globally, it also sends non-AI traffic, which has no model or tokens and only adds noise to the ingest counts and your request limits, so scope it to the services that carry AI traffic. After adding a route, send one request through it and confirm it appears in the next ingest response.
4. Map Kong consumers to agents
Kong identity is registry-only. Meridian reads the gateway key ref from the log entry in this order: consumer.username, then credential.id, then client_ip. Map each consumer to an agent:
- Open
/meridian/settings/gateway-keysin the Meridian app. - Choose Gateway
kong, enter the consumer username as Gateway key ref, and enter the Agent id. Optionally add Cost center, Pool id and Endpoint id, then Save mapping. - For many consumers, upload a CSV with the required columns
gateway,gateway_key_refand the optional columnsagent_id,cost_center,pool_id,endpoint_id,active.
gateway,gateway_key_ref,agent_id,cost_center kong,support-triage-bot,support-triage,CC-4100 kong,invoice-matcher-svc,invoice-matcher,CC-2200
If no agent has the id you enter yet, Meridian creates one on the first matching call. Rename it and give it a department on the Agents page. Consumers Meridian has seen without a mapping appear under Unmapped keys on the same page.
5. Forward proxy
If the data plane must leave through a corporate proxy, configure Kong's outbound proxy settings for plugin traffic, allowlist api.onaro.io on the proxy and any TLS inspection device, and redact the Authorization header from proxy logs.
What Meridian receives
| Meridian field | Kong log field |
|---|---|
| Record id | request.id (turned into a stable UUID, so replays are dropped as duplicates) |
| Occurred at (required) | started_at |
| Provider | ai.proxy.meta.provider_name |
| Model | ai.proxy.meta.request_model, else ai.proxy.meta.response_model |
| Input tokens | ai.proxy.usage.prompt_tokens |
| Output tokens | ai.proxy.usage.completion_tokens |
| Cost | ai.proxy.meta.estimated_cost; $0 when absent |
| Operation | Always chat |
| Gateway key ref | consumer.username, else credential.id, else client_ip |
Records are written as usage records with source_system gateway:kong and currency USD. Everything else in the Kong log, including request and response headers, is ignored.
Cost. Kong reports the cost of a request at ai.proxy.usage.cost. Meridian's Kong mapping reads ai.proxy.meta.estimated_cost instead, and when that field is absent it records $0. Unlike the other gateways, a missing Kong cost does not fall back to your rate card or the model price catalog. Today, Kong requests arrive with tokens and models but $0 cost. See Limits.
Timing. Records are stored as they arrive. The rollup into the spend ledger runs every hour at 20 minutes past, in UTC, and looks back 7 days.
Verification
- Send one request through the route as a mapped consumer.
- Read the response body. Meridian returns HTTP 200 for any well-formed batch, even when every record is rejected, so Kong treats delivery as successful either way. Replay one entry from Kong's logs with curl to see the body:
curl -s https://api.onaro.io/v1/meridian/ingest/gateways/kong \ -H "Authorization: Bearer $MERIDIAN_INGEST_KEY" \ -H "Content-Type: application/json" \ -d @one-kong-entry.json
A good response has accepted of 1 and an empty rejected list.
- Check the health endpoint with the same key:
GET https://api.onaro.io/v1/meridian/ingest/healthreturnslast_ingest_at, totals, the duplicate rate and a key expiry warning. - Check the registry. If the consumer appears under Unmapped keys, map it.
- Check the ledger after the next rollup: the request appears under the agent on Agents & allocation, or under Unattributed.
What gets attributed and what doesn't
- Attributed: requests made by a Kong consumer whose username is mapped in the Gateway key registry.
- Unattributed: requests from unmapped consumers, and anonymous requests keyed by credential id or client IP. They roll up as unattributed and appear in the attribution inbox (Agents & allocation → Unattributed), where you can assign them by hand. Manual assignments survive later rollups.
- No declared mode. Kong logs carry no agent field, so Meridian does not read an agent id from the request. The registry is the only way to attribute Kong traffic.
- Cost center values from the registry are stored with the raw event but not written to the ledger, so they do not drive department reporting.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| 401 "API key required" | The key is not a meridian:ingest key. Create an ingest key in Settings → Usage ingest keys. |
| 401 "Invalid API key", "revoked" or "expired" | Create a new key in Settings → Usage ingest keys, update the plugin header, then revoke the old key. |
| 403 "Scope 'meridian:ingest' required" | The scope must be listed exactly; meridian:* does not imply it. |
429 with Retry-After | Limits count HTTP requests per key, per minute and per day; the lowest key tier allows 20 a minute and 100 a day. Raise max_batch_size and max_coalescing_delay so each request carries many entries. |
200 with {"error": "batch_too_large"} | More than 1,000 entries in one request. Lower max_batch_size. |
| Records accepted but zero tokens | logging.log_statistics is off on ai-proxy. Turn it on. |
| Every request keyed by an IP address | The route has no authentication plugin, so there is no consumer. Add key-auth (or another auth plugin) and consumers. |
| Costs show $0 | Expected today; see the Cost note above. |
200 with field: "occurred_at" | The entry had no started_at. Check that http-log is sending Kong's standard log serializer output. |
Limits
- Early access. The mapping is pinned to Kong 3.9.0 and was built from Kong's documented log shape. Check your first responses for rejections before relying on totals.
- Cost is $0 for Kong requests today. Meridian reads a cost field Kong does not populate and does not fall back to a rate card. Tokens and models are recorded, but Kong spend is not counted in Meridian until the mapping reads
ai.proxy.usage.cost. - Ingest keys are managed by organization admins. Up to 10 active ingest keys per organization. See Manage ingest keys.
- The registry pages are reachable by path only until they are linked from Settings.
- HTTP 200 does not mean accepted. Read
acceptedandrejected. - Registry-only identity. No agent id is read from Kong requests, and the registry's cost center does not reach the ledger.
- Late data. Entries that arrive more than 7 days after the request are stored but not rolled up.