# AI Gateway Data Handling

> **Scope of this page**
>
> This page documents the Zuplo **gateway** runtime (API, AI, and MCP gateways), not the Developer Portal.
>
> It applies to every Zuplo hosting option: Managed Edge, Managed Dedicated, and Self-Hosted. See [Hosting options](https://zuplo.com/docs/articles/hosting-options).

By default, the AI Gateway records usage metadata for each request (who called,
which model answered, how many tokens it used, what it cost, and how long it
took) and doesn't keep prompt or completion text. Prompt and completion text
leaves the request path only through features you add to an app's
[policy chain](../policy-chains.mdx) or to the gateway's code.

## What Zuplo records by default

Each request to an app produces usage records that power
[AI Gateway analytics](./analytics.mdx) and [budgets](../usage-limits.mdx). They
hold these fields:

| Field                        | What it holds                                                                                                                                               |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| App and pool                 | The app that served the request and the pool it belongs to.                                                                                                 |
| Caller                       | The authenticated caller's identifier (`request.user.sub`), and the person for a request made with a personal key on the [User App](../user-apps.mdx).      |
| Model and provider           | The model that answered and the provider that served it.                                                                                                    |
| Tokens                       | Prompt, completion, and embedding token counts.                                                                                                             |
| Cost                         | The estimated cost, and whether it came from the provider's reported price or a rate card.                                                                  |
| Latency                      | How long the request took. See [How latency is measured](./analytics.mdx#how-latency-is-measured).                                                          |
| Cache outcome                | Whether the semantic cache served the request, its similarity score, and the tokens a hit saved.                                                            |
| Blocks and warnings          | The type of block or warning, such as a guardrail match or an exhausted budget, without the matched text.                                                   |
| Budget values                | For a **By metadata** budget rule, the value its expression read, such as a header value. See [Budget expressions](../usage-limits.mdx#budget-expressions). |
| Request ID, account, project | Identifiers that tie the records to the request's logs.                                                                                                     |

The gateway's request logs also hold the method, the full URL including its
query string, the route, the status code, the duration, and the client's IP
address and location. See
[Logging](../../articles/logging.mdx#viewing-logs-in-the-portal).

The gateway's log messages describe what happened to a request, such as which
provider served it, a fallback to another model, or a policy that blocked it.
When a provider rejects a request, the log message carries the provider's error
message.

Neither the usage records nor the request logs include request or response
bodies. How long Zuplo keeps them depends on your plan. See
[Data retention](../../analytics/access-and-entitlements.md#data-retention).

## Features that store or send content

These features handle prompt or completion text when you turn them on. Each one
is off until you add it.

| Feature                                                                       | Content it handles                                                                                                                                       | Where the content goes                                                                                                                                 |
| ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Semantic Cache](../../policies/ai-gateway-semantic-cache-inbound.mdx)        | The system prompt and the most recent messages, which form the match key, and the provider's response.                                                   | Zuplo's semantic cache, which keeps each app's entries apart. Entries expire after `expirationSecondsTtl` seconds: one hour by default, up to 30 days. |
| [Comet Opik Tracing](../../policies/ai-gateway-opik-tracing-inbound.mdx)      | Prompt messages or input, completion text, model, token counts, temperature and maximum tokens, request ID, and route.                                   | Your Comet Opik workspace and project.                                                                                                                 |
| [Galileo Tracing](../../policies/ai-gateway-galileo-tracing-inbound.mdx)      | Prompt and completion text, model parameters, finish reasons, token counts, duration, request ID, and route.                                             | Your Galileo project and log stream.                                                                                                                   |
| [Akamai AI Firewall](../../policies/ai-gateway-akamai-firewall-inbound.mdx)   | Prompts and completions, for inspection.                                                                                                                 | Akamai Firewall for AI.                                                                                                                                |
| [Prompt Injection Protection](../../policies/ai-gateway-prompt-injection.mdx) | The newest message of each request, for classification.                                                                                                  | The classifier you configure: an OpenAI-compatible API, or another app on the same gateway and its provider.                                           |
| [Smart Router](../../policies/ai-gateway-smart-router-inbound.mdx)            | The last user prompt, for classification.                                                                                                                | The classifier you configure, such as another app on the same gateway and its provider.                                                                |
| [Log plugins](../../articles/logging.mdx#log-integrations)                    | The request logs described earlier and messages that policies write with `context.log`. Content appears only if a custom policy logs it.                 | Your logging service, such as Datadog, Splunk, or AWS CloudWatch.                                                                                      |
| [OpenTelemetry plugin](./tracing.mdx)                                         | Span timings, HTTP method, URL, status code, request ID, model, token usage, and cost. Prompt and completion text only when you turn on content capture. | Zuplo's trace storage or your OpenTelemetry backend.                                                                                                   |

The [Data Loss Prevention](../../policies/ai-gateway-dlp-inbound.mdx) policy
scans content inside the gateway and doesn't send it to another service.

## Capture prompts and completions for an app

To record the content of an app's requests for debugging or evaluation, add a
tracing policy to that app. Other apps on the gateway stay unchanged.

<Stepper>

1. **Open the app's policy chain**

   Open the [**Apps**](https://portal.zuplo.com/+/account/project/ai/apps) tab,
   select the app, and then open its **Policies** tab.

2. **Add a tracing policy**

   Click **Add policy** and choose Comet Opik tracing or Galileo tracing.

3. **Enter the connection settings**

   For Comet Opik, enter the `apiKey`, `projectName`, and `workspace`. For
   Galileo, enter the `apiKey`, `projectId`, and `logStreamId`. Reference the
   API key as an environment variable, such as `$env(COMET_OPIK_API_KEY)`,
   rather than pasting it. See
   [Options and secrets](../policy-chains.mdx#options-and-secrets).

4. **Move the policy to the end of the chain**

   Drag the entry to the end of the chain so the trace records the request that
   earlier policies produced.

</Stepper>

The change applies to new requests after the app's cached configuration
refreshes, with no deploy. To stop capturing content, remove the entry or
disable it.

To capture content for every new app in a pool, add the tracing policy to the
pool's [policy template](../policy-templates.mdx).

## Keep sensitive data out of stored content

Policies run in chain order, and each one sees the request as the earlier
policies left it. Put Data Loss Prevention before the other policies in the
table above, so the cache key, the traces, and the classifiers receive the
masked prompt instead of the original text.

## Related resources

- [AI Gateway analytics](./analytics.mdx)
- [AI Gateway tracing](./tracing.mdx)
- [AI Gateway policy chains](../policy-chains.mdx)
- [AI Gateway policies overview](../policies/overview.mdx)
