Your logs, your browser
Point Loupe at your own assistant.
Drop a chat log or an OpenTelemetry agent trace. Loupe answers who uses it, what for, where it fails, which sub-agent people react to, and whether a gap between two models is real or just different people. The file never leaves this page.
No logs of your own? Use your own AI history: export it from ChatGPT (Settings → Data controls → Export data) or Claude (Settings → Privacy → Export data) and drop the zip here. Claude emails a list of links; the one you need is conversations-000.zip.
What fields Loupe looks for
Conversations: one object per conversation with a list under messages (or conversation, turns), each with role and content. Optional: user_id, timestamp, model, and responder on assistant messages. Message rows: one row per message with a conversation id and a role. Agent traces: OTLP JSON; spans are grouped by trace, gen_ai.input.messages and gen_ai.output.messages give the turns, gen_ai.agent.name names the responder, user.id the person. Personal exports: the zip from ChatGPT or Claude, or the conversations.json inside it; only that file is opened, and Loupe follows the thread you saw in each conversation. Without a user field each conversation counts as its own person; without timestamps there are no weekly trends; without a model field there is no model comparison. Loupe tells you which applies.
What was copied
Model or users?
Is the gap between two models real, or just different people?
Usage logs compare models across whoever chose them. Loupe also compares the same people on both. If the gap disappears, it was user mix.
Did my change help?
Before and after a change, for the same people
Pick when you changed a prompt, a model or a feature. Loupe compares the people who used the assistant on both sides, so new or departing users can't fake an effect, then reruns the test at an earlier date as a placebo.
How to mark a change
Loupe lists a change for each new value of prompt_version, app_version, release or version on your conversations (or service.version on OpenTelemetry spans), dated by when it first appears. Without one, pick a date. The comparison holds the person fixed but not the calendar: anything else that changed that week is mixed in, which is what the placebo run checks for. For a clean answer, randomize the change.
Turn failures into tests
Every conversation where someone corrected a reply or asked again, ready for your evals and backlog
What's in the files
Eval cases: one line per conversation, holding the messages up to the reply that failed, that reply, and what the person said next, with its intent and responder. promptfoo config: the same cases as tests, each replaying the conversation and asserting with a rubric that the new reply avoids the problem the person flagged; set the provider to your assistant and run npx promptfoo eval. Backlog: failures grouped by intent and responder with the most common reason and example asks, for import into Linear or Jira. Each eval case also carries its reason. The files hold your users' real messages; they are built in this page and saved only to your machine.
What people use it for
What this measures
Each conversation's first two user messages are classified into seven intents by Loupe's classifier, running in this page. Its held-out accuracy is against an 87.1% inter-rater ceiling, the same gate as the production model.
Where it fails them
What this measures
Repeated request (the same ask again, word overlap 0.6 or more) and correction follow-up ("no, that's wrong") are the two friction signals that cleared Loupe's 70% precision check. One-turn share is shown as engagement depth, not failure.
Who is answerable: friction per 1,000 replies, by responder
What this measures
Each repeat or correction is charged to the responder whose reply the person had just read: the model, or the sub-agent named by responder or gen_ai.agent.name.