What every trace stores

Every request writes one trace row: which model was requested and which actually served it, the routing reason and predicted difficulty/task type, token counts, cost breakdown (provider cost vs. our fee), routing and upstream latency, fallback path, cache hit/miss, and status. This is what backs /logs and /usage, visible only to your own account.

What a trace never stores

Your message content is not in the trace store. No prompt text, no completion text, no raw message array — the schema has no column for it. The one content-derived field is prefix_hash, a one-way SHA-256 hash of your multi-turn prefix used only for cache/sticky-routing analytics — it can't be reversed back into your text.

Attribution fields are the exception

If you send app-attribution headers or the user field, those exact strings (your app name, referrer, end-user id) are stored as given, since that's the point of sending them — don't put anything in them you wouldn't want stored plainly.

The one place bodies are stored

The response cache is the single exception: it's opt-in per request, stores the full request/response body only for that entry, is always namespaced to your own org (never shared across tenants), skips tool/function-calling requests entirely, and expires on a TTL (default 5 minutes, capped at 24 hours). If you never send the opt-in header, none of this applies to you.

What the upstream provider sees

Your prompt is, of course, sent to whichever provider serves the request — that's inherent to getting a completion back. What that provider retains is governed by their own terms, not ours; we don't add a retention layer of our own on top beyond what's described above.