Skip to content

feat(seer-slack): Add analytics for Seer agent Slack responses#113318

Open
alexsohn1126 wants to merge 9 commits intomasterfrom
alexsohn/iswf-2482-add-analytics-for-seer-agent-in-slack
Open

feat(seer-slack): Add analytics for Seer agent Slack responses#113318
alexsohn1126 wants to merge 9 commits intomasterfrom
alexsohn/iswf-2482-add-analytics-for-seer-agent-in-slack

Conversation

@alexsohn1126
Copy link
Copy Markdown
Member

@alexsohn1126 alexsohn1126 commented Apr 17, 2026

We want to add analytics for Seer Agent in Slack.

After some discussion, we decided to send the following information for each chat with the Seer Agent.

  • Org slug
  • Username (Sentry)
  • thread ID
  • prompt length
  • integration ID - in installations shared between orgs
  • Number of messages in the thread
  • Number of Seer Agent messages in the thread
  • Number of unique users in the thread
  • Number of linked users in the thread
    • I was thinking of skipping this as with the current suite of IdentityFilterArgs only offers individual queries, not [...]id__in queries.

class IdentityFilterArgs(TypedDict, total=False):
id: int
user_id: int
identity_ext_id: str
provider_id: int
provider_ext_id: str
provider_type: str

  • However I thought it would be a decently valuable metric so I added an RPC method to allow people to filter by a list of slack user ids
  • Type of conversation
    • Mention? AI Assistant feature? DM?

Record an ai.explorer.slack.responded analytics event each time the Seer
Explorer agent responds to a Slack user. The event captures conversation
type (app mention, direct message, or AI assistant thread), run id, and
thread statistics (total messages, unique users, prior Seer runs) so
downstream analysis can derive metrics like first-vs-continued
engagement.

SeerExplorerOperator.trigger_explorer now returns the run id alongside
the count of prior runs for the same thread, which the task uses to
populate the event.

Refs ISWF-2482
Co-Authored-By: Claude <noreply@anthropic.com>
@linear-code
Copy link
Copy Markdown

linear-code bot commented Apr 17, 2026

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 17, 2026
Comment thread src/sentry/seer/entrypoints/slack/analytics.py
Top-level @mentions have thread_ts=None, but the analytics event field
is typed str. Fall back to the message's own ts, which is the thread
root once Seer replies.

Co-Authored-By: Claude <noreply@anthropic.com>
@alexsohn1126 alexsohn1126 marked this pull request as ready for review April 17, 2026 19:27
@alexsohn1126 alexsohn1126 requested review from a team as code owners April 17, 2026 19:27
Add linked_users_in_thread to the ai.explorer.slack.responded event so
downstream analysis can see how many thread participants have a linked
Sentry identity (proxy for team adoption stickiness).

Adds an identity_ext_ids list filter to the identity RPC service so the
lookup is a single batched query per mention rather than N+1. Includes a
test against real data that exercises the new filter end-to-end.

Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread src/sentry/seer/entrypoints/slack/tasks.py
Comment thread src/sentry/seer/entrypoints/slack/tasks.py Outdated
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were no tests for identity service filtering, I made one

Compute seer_msgs_in_thread by counting bot messages already in the
thread history instead of piggybacking on the Explorer runs count. The
runs count was effectively boolean (0 or 1) since subsequent mentions
continue the existing run rather than create new ones, so the field
name didn't match what the data was saying.

Reverts trigger_explorer back to returning just run_id; the operator
no longer has an analytics concern and limit=1 is restored.

Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread src/sentry/seer/entrypoints/slack/tasks.py Outdated
alexsohn1126 and others added 3 commits April 17, 2026 16:00
msg.get("user") on list[dict] returns Any | None, so the set
comprehension was typed set[Any | None]. Use isinstance in a walrus to
narrow to str, matching the _count_linked_users signature.

Co-Authored-By: Claude <noreply@anthropic.com>
Tasks enqueued by pre-analytics workers during a rolling deploy don't
pass conversation_type. Without a default, those in-flight tasks fail
with TypeError and keep failing on retry since the kwargs are
immutable. Default to DIRECT_MESSAGE so those handful of tasks classify
to a single bucket rather than crashing.

Co-Authored-By: Claude <noreply@anthropic.com>
record_seer_slack_event was a passthrough to analytics.record after the
event-class consolidation. Inline the call in the task and remove the
wrapper.

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f082809. Configure here.

Comment thread src/sentry/seer/entrypoints/slack/analytics.py
@analytics.eventclass only converts the class and sets type; it doesn't
add it to EventManager._event_types. Matches the pattern used by every
other event class under src/sentry/analytics/events/.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant