Recurring problems and feedback
All of these are events: records attached to a conversation. They never change the agent by themselves.
You need: introspection login and a deployed runtime with some finished conversations.
| Event | Event name | Records |
|---|---|---|
| Observation | introspection.observation | Something notable in one conversation, through one lens |
| Pattern | introspection.pattern | A recurring behavior, and the observations in it |
| Judgement | introspection.judgement | A judge’s verdict: pass, fail, not_applicable, or error (the grader failed) |
| Feedback | introspection.feedback | A rating from your app, or a thumbs rating in Chat with recipe |
| Annotation | introspection.annotation | A teammate’s label or comment (Annotate conversations) |
| Tracked event | API only: GET /v1/events?event_name=introspection.track | A business event your code sends with track() |
events list also reads introspection.pattern.assignment (an observation assigned to, or removed from, a pattern) and introspection.observation_clustering.run (one run that groups observations into patterns).
See recurring problems
Open Patterns in the dashboard, pick a lens, select a pattern, and open a conversation behind it.
From the CLI:
introspection events list --event-name introspection.pattern --filter lens=agent_struggle
introspection events list --event-name introspection.observation --filter pattern_id=<pattern-id> --lookback 30d --page-allLenses: user_intent, task_resolution (resolved, blocked, abandoned), user_sentiment, agent_struggle (loops, retries), and environment_issue (tool, dependency, or data problems).
Observations arrive about 30 minutes after a conversation goes idle. Patterns are kept per runtime and lens across versions, and are periodically renamed, merged, or retired. To turn extraction off for a project, contact us.
Find failing judgements
introspection events list --event-name introspection.judgement \
--filter judge_id=<judge-id> --lookback 7d \
--query "[?payload.result=='fail'].{conversation:conversation_id,reason:payload.reasoning}" -o tableFor pass rates over time, query the judgements view in Metrics.
Read feedback
introspection events list --event-name introspection.feedback --lookback 7d \
--query "[?payload.name=='thumbs_down'].{conversation:conversation_id,comments:payload.comments}" -o tableTo count it, the metrics events view groups feedback by sentiment: thumbs_down, negative, and signal_negative count as negative; thumbs_up, positive, and signal_positive as positive.
Send feedback and business events
From your backend, with the Node SDK:
import { IntrospectionLogs } from "@introspection-sdk/introspection-node/otel";
const logs = new IntrospectionLogs({ serviceName: "support-api" });
await logs.withUserId(user.id, async () => {
logs.feedback("thumbs_down", {
conversationId: task.id,
previousResponseId: task.metadata.last_response.response_id, // the answer being rated
comments: "Applied the wrong refund rule",
});
logs.track("case_closed", { value: 1, plan: "pro" });
});Inside a task, use process.env.INTROSPECTION_TASK_ID as the conversation. Read tracked events with GET /v1/events?event_name=introspection.track&name=case_closed, or count them in Metrics.
Limits
| Not supported | Do this instead |
|---|---|
Filtering events list by verdict or rating on the server | Filter the output with --query as above, or use the metrics views. |
| Slack reactions as feedback | Not delivered; see Slack limits. |
| The agent reading feedback | Feed it into evals (Add production cases to an eval). |
| Misspelled filter keys | The server ignores unknown keys, so check spelling when a list is empty. |
Or ask your agent: “Summarize last week’s patterns and negative feedback for support-agent and name the one failure worth fixing.”