AI Asset Inventory
Overview
AI Gateway → Inventory builds a complete list of the AI assets defined in your installation (LLM provider connections, models, MCP and A2A targets) and compares it against real traffic to report shadow AI usage findings — use of a model that its provider does not list, a provider without a matching connection, unregistered MCP/A2A servers, and catalog drift. This is a standalone screen, not a tab embedded in the main Analytics (ai-dashboard) hub — it has its own menu entry, but shares the same viewing permission as Analytics.
This report corresponds to the AI system inventory concept required by ISO/IEC 42001 (knowing every AI asset in your installation) and to the GOVERN (inventory, governance) and MAP (mapping actual usage) functions of the NIST AI RMF. It is not presented as a compliance certificate — it's a starting point for reviewing where your installation stands against those frameworks.
Two-Plane Model
The report works by taking the difference between two independent data sources:
Reflects current configuration: registered LLM provider connections with their models, the aiRouting definitions of deployed proxies, and both registered and inline (embedded in a proxy) MCP/A2A targets. Independent of any time range — it always shows "what's defined right now."
Pulls the model/provider names actually used in your chosen time window from traffic logs with a single aggregation query. It only adds "was this used / when was it last seen" — it doesn't replace the inventory.
Shadow usage is the difference between these two planes. Some findings — models that the provider does not list and unregistered inline MCP/A2A targets — come only from the inventory plane: Elasticsearch cannot observe a blocked request (and therefore which model it tried to reach), because the request was rejected before it ever reached the provider.
Findings and Inventory Tables
The screen shows two separate tables:
- Shadow AI Usage Findings — one row per asset that has findings; each issue detected on the asset shows as a chip (finding code, severity, the asset involved, observed request count, last-seen time)
- AI Asset Inventory — one row per asset (type, name, provider, whether the provider lists it, health status, whether drift was detected, how many proxies use it). Filter it by asset type and health, or search by asset or provider.
The KPI cards at the top (Total Assets, Critical Findings, Warning Findings, Uncataloged Models, Unregistered MCP/A2A) are always the true, pre-filter counts — the severity filter only narrows the findings table below, it never affects the KPI counts. Click a card other than Total Assets to narrow both tables to that slice; a Filtered: … pill appears, and clicking the card again or the pill clears it. The How to read? button opens a short guide to the screen.
The environment, severity and time range (Last N days) filters sit in the bar at the top of the screen. The time range and environment affect only the observation plane (Elasticsearch); the inventory plane always shows current configuration regardless of these filters. The severity filter (All severities, Critical, Warning) narrows only the findings table.
Observed request counts are kept for each LLM provider record. The traffic log stores the id of the provider record that served the call (field aipid); when the call went to a backup provider, it stores the id of the active failover provider. When the log rows carry this id, two providers of the same type each show only their own requests. If a request ends with an error, the log row is counted on the primary provider record, even when the gateway tried a backup first. Only the attempt that served the request carries the backup provider's id.
A model not in catalog finding is one row for each provider record. The row shows the provider name and counts only that provider's requests of the model. If the same model is used under two providers, you see two rows. Two provider records can have the same name in different projects, so the screen tells them apart by the provider record id.
Requests without a provider record id
Requests logged before this version have no provider record id. They are shown apart as +N without provider record (unattributed) and are never assigned to a provider record afterwards. The unattributed requests are split by provider type:
- A provider record is shown only the unattributed requests of its own type.
- In a model not in catalog finding, a provider without a type (a custom provider) is shown only the requests that also have no type.
- In the inventory table, the unattributed request count of a provider without a type is always 0. That row counts only the record's own requests.
- Last Seen is the record's own last request. If the record has none, it is the last unattributed request of its type. It is never the date of another record.
- For a custom provider, Last Seen is not taken from unattributed requests. A model finding of a custom provider shows no last-seen date unless the record has its own request.
The Inventory table has an Observed · Last Seen column and an unattributed request count for each provider row.
When counts fall back to the provider type
The per-record counts need the aipid field to be mapped as a keyword in the traffic log index. The upgrade migration adds this mapping to the index template that Apinizer manages, and it takes effect for new indices after the rollover. If the per-record counts cannot be read, the report counts by provider type, as in earlier versions:
- The index has no keyword mapping for
aipid, for example an Elasticsearch connector or index template that Apinizer does not manage, or a template update that failed. - Elasticsearch refuses the query.
- Elasticsearch returns partial shard results.
In this case every provider of the same type shows the total of its type, the unattributed count is 0, and model findings use the total count of the model. Apinizer API Manager writes a warning to its log (provider record counts not read ... counting by provider type).
Finding Codes
On screen, finding codes, asset types, and severities are shown as translated labels rather than the raw values below — the raw value stays visible alongside the label (for example, in a tooltip or a secondary line) for anyone matching a finding to logs, exports, or an alert payload.
| Code | Severity | Meaning |
|---|---|---|
PROVIDER_ENDPOINT_MISMATCH | Warning | The connection's endpoint differs from the default endpoint of its provider type |
PROVIDER_OBSERVED_NOT_CONFIGURED | Critical | A provider observed in Elasticsearch doesn't match any enabled connection (a stale deployment or a deleted connection) |
MODEL_NOT_IN_CATALOG | Critical if observed, Warning otherwise | A model used in a proxy's routing is not in the model list of the connection's LLM provider — this can produce a runtime error or a silent failover |
MCP_TARGET_UNREGISTERED / A2A_TARGET_UNREGISTERED | Critical | An MCP/A2A target embedded (inline) in a proxy isn't found in the set of registered connections |
MCP_CATALOG_DRIFT / A2A_CATALOG_DRIFT | Warning | Drift detected between the approved catalog hash and the target's live tool/capability list |
Limits of the Observation Plane
This report can only see traffic that goes through the Apinizer AI Gateway. Calls an application makes directly to an LLM provider without going through Apinizer at all — genuinely "shadow" usage in the fullest sense — are not visible in this report: Apinizer does not perform any egress or DNS monitoring. The report audits the consistency of known (gateway-routed) AI traffic against your inventory; it is not a complete external audit of every AI use across your organization.
The observation plane can also be truncated in large installations: if the number of distinct model/provider/tenant names exceeds an internal term limit, the screen shows a "the observation plane truncated some results" banner and the report should be treated as incomplete for that period — narrowing the time range is recommended in that case.
XLSX Export
The report can be exported as a two-sheet Excel workbook, Findings and Inventory; the exported data includes all findings for the selected time range, independent of the on-screen severity filter. Beside the on-screen values, the Findings sheet has the columns Provider Name and Unattributed Requests, and the Inventory sheet has the column Unattributed Requests.
Wiring Into an Alert
The critical finding count from this report can be wired into an alert through the AI Shadow Asset Count trigger. The counter doesn't accumulate over a time window — each check reads the currently critical finding count (a state counter, not an event counter); setting the threshold to 1 gives you an alert for "any shadow AI asset exists at all."