Skip to main content
Sentry tells you that an exception was thrown: an issue spikes, a regression appears, a transaction slows. It can’t tell you whether the person was actually blocked or what they saw when it fired. Subtext can. Attach the Subtext session URL to your Sentry events as a tag and every issue becomes a jumping-off point — your agent reads the subtext_url, opens that person’s real session, and walks the decisive moments with screenshots, the component tree, network, and console. Sentry detects; Subtext diagnoses.
This guide assumes the Subtext capture snippet is installed and the Sentry JavaScript SDK (@sentry/browser or a framework-specific package) is initialized.

Attach the session URL

Store the current Subtext session URL on your Sentry events as a tag so it travels with every error. Tags are indexable and searchable in the Sentry UI, and there are two ways to set one.

As a global tag

Set the URL as a Sentry tag once, after identification. It rides on every subsequent error event and shows up wherever you filter issues. Session URL values fit within Sentry’s 200-character tag limit.

Per error, with beforeSend

beforeSend runs on every captured event and reads the URL fresh, so each error gets a link to the exact moment it occurred rather than a frozen session-start link. beforeSendTransaction does the same for performance events.
Reach for beforeSend when moment-level precision on errors matters more than simplicity. The two patterns can coexist — beforeSend overwrites the global tag value for each specific event.
Don’t read FS('getSession') at module top level — it returns null until the session has started. Don’t put the URL in event.extra; use event.tags so it stays searchable in the Sentry UI. The session URL changes on a new session and when FS('setIdentity') is called with a different uid, so re-call Sentry.setTag whenever you re-identify. beforeSend reads the URL fresh on every event, so it never needs re-attaching.

From signal to session

However you first hear about a problem in Sentry — a paged alert, a “New Issue” email, an assigned ticket — the path is the same: get to the subtext_url on the event, then hand it to your agent. Sentry tells you an exception was thrown; the session tells you whether the user was actually blocked, what they saw, and the exact sequence that triggered it. That gap is the Detect-vs-Diagnose read, and the output is a structured summary you can paste back into the Sentry issue.
A Sentry “New Issue” or “Regression” email lands in your inbox: TypeError: cannot read properties of undefined (reading 'total') — CheckoutForm.tsx.Click through to the issue from the email, open the latest event, go to the Tags section, and copy the subtext_url value. Then hand it to your agent:
The Sentry Slack integration posts “Issue spiking — 142 events in 10 min, first seen in release web@2.8.0.”Click the Slack alert; it deep-links to the issue. Because a spike is many sessions, grab subtext_url from three or four different recent events.
Your Sentry inbox has a stack of issues assigned to you for the shift.In the Issues view, filter has:subtext_url to surface only the issues that have a session attached — those are the ones you can actually see. Triage those first and copy the tag from each. Run the per-issue prompt above, and for anything where the session shows no real impact, downgrade it:
After the review, paste the agent’s structured summary back into the Sentry issue as a comment so the next person inherits the diagnosis, not just the stack trace. For a spike across several sessions, ask your agent to roll the findings into one proof document (doc-create) with a screenshot per session and a single shared link, then drop that link into the issue.

For agents

An autonomous agent can run the whole loop against Sentry directly: discover the worst issues, extract the subtext_url, and hand each session to the Subtext MCP. Sentry ships a first-party MCP server at https://mcp.sentry.dev/mcp (Streamable HTTP, with SSE fallback); for self-hosted Sentry, run it locally over stdio with npx @sentry/mcp-server@latest. The hosted endpoint authenticates with OAuth through your Sentry org; local uses a User Auth Token with the scopes Sentry’s MCP docs require: org:read, project:read, project:write, team:read, team:write, and event:write.
1

Discover the worst issues

Use search_issues to rank hotspots — pass a query and a sort, e.g. search_issues(query="is:unresolved", sort="freq"). Drill into an issue with get_issue_details, search_issue_events, search_events, or get_event_stacktrace. Over REST, the org-level Issues endpoint does the same (the project-level one is deprecated):
Append has:subtext_url to the query to keep only issues with a session attached; its inverse !has:subtext_url surfaces capture gaps.
2

Extract the session URL

subtext_url is stored as an event tag. Read the aggregate of values seen on an issue with get_issue_tag_values(tagKey="subtext_url"). Over REST:
3

Hand off to Subtext

For each URL, call review-open(session_url=<subtext_url>) on the Subtext MCP, then read the event map and step to the error moment for a Detect-vs-Diagnose read. When triaging a spike, pull subtext_url from several affected events and review them together to find the common trigger.
subtext_url only round-trips if it was attached at capture time (see Attach the session URL). beforeSend produces moment-precise links; the global tag opens at session start. Sentry caps tag values at 200 characters — session URLs fit, but verify if you ever see truncation.