Skip to content

Commit 593d1b1

Browse files
azulusclaude
andcommitted
fix(seer): Only create API token when code mode is enabled
Extract token creation into standalone create_explorer_api_token() function and only call it when enable_code_mode_tools is True. This avoids creating unnecessary tokens when the feature is off, and eliminates expensive collect_user_org_context queries in continue_run that were only needed for the token. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ad3e294 commit 593d1b1

File tree

2 files changed

+30
-31
lines changed

2 files changed

+30
-31
lines changed

src/sentry/seer/explorer/client.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
ExplorerRunsRequest,
2121
ExplorerUpdateRequest,
2222
collect_user_org_context,
23+
create_explorer_api_token,
2324
fetch_run_status,
2425
make_explorer_chat_request,
2526
make_explorer_runs_request,
@@ -269,7 +270,11 @@ def start_run(
269270
raise ValueError("artifact_key and artifact_schema must be provided together")
270271

271272
user_org_context = collect_user_org_context(self.user, self.organization, request=request)
272-
user_auth_token = user_org_context.pop("user_auth_token", None)
273+
user_auth_token = (
274+
create_explorer_api_token(self.user, self.organization)
275+
if self.enable_code_mode_tools
276+
else None
277+
)
273278

274279
chat_body: ExplorerChatRequest = ExplorerChatRequest(
275280
organization_id=self.organization.id,
@@ -372,8 +377,11 @@ def continue_run(
372377
if bool(artifact_schema) != bool(artifact_key):
373378
raise ValueError("artifact_key and artifact_schema must be provided together")
374379

375-
user_org_context = collect_user_org_context(self.user, self.organization, request=request)
376-
user_auth_token = user_org_context.pop("user_auth_token", None)
380+
user_auth_token = (
381+
create_explorer_api_token(self.user, self.organization)
382+
if self.enable_code_mode_tools
383+
else None
384+
)
377385

378386
chat_body: ExplorerChatRequest = ExplorerChatRequest(
379387
organization_id=self.organization.id,

src/sentry/seer/explorer/client_utils.py

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,27 @@ def collect_user_org_context(
287287
# Get IP address from http request, if provided
288288
user_ip: str | None = request.META.get("REMOTE_ADDR") if request else None
289289

290-
# Create a short-lived API token for Seer to call back into Sentry on behalf of the user
291-
user_auth_token: str | None = None
290+
return {
291+
"org_slug": organization.slug,
292+
"user_id": user.id,
293+
"user_ip": user_ip,
294+
"user_name": user_name,
295+
"user_email": user.email,
296+
"user_timezone": user_timezone,
297+
"user_teams": user_teams,
298+
"user_projects": user_projects,
299+
"all_org_projects": all_org_projects,
300+
}
301+
302+
303+
def create_explorer_api_token(user: SentryUser | RpcUser, organization: Organization) -> str | None:
304+
"""Create a short-lived read-only API token for Seer to call back into Sentry."""
292305
try:
293306
from sentry.models.apitoken import ApiToken
294307
from sentry.types.token import AuthTokenType
295-
from sentry.users.models.user import User
296-
297-
# request.user may be an RpcUser proxy — ApiToken needs the real User model
298-
real_user = User.objects.get(id=user.id)
308+
from sentry.users.models.user import User as UserModel
299309

310+
real_user = UserModel.objects.get(id=user.id)
300311
token = ApiToken.objects.create(
301312
user=real_user,
302313
token_type=AuthTokenType.USER,
@@ -311,30 +322,10 @@ def collect_user_org_context(
311322
],
312323
expires_at=timezone.now() + timedelta(hours=1),
313324
)
314-
user_auth_token = token.plaintext_token
315-
logger.info(
316-
"seer_explorer.auth_token_created",
317-
extra={
318-
"user_id": user.id,
319-
"org_id": organization.id,
320-
"expires_at": str(token.expires_at),
321-
},
322-
)
325+
return token.plaintext_token
323326
except Exception:
324327
logger.exception("Failed to create short-lived API token for Seer Explorer")
325-
326-
return {
327-
"org_slug": organization.slug,
328-
"user_id": user.id,
329-
"user_ip": user_ip,
330-
"user_name": user_name,
331-
"user_email": user.email,
332-
"user_timezone": user_timezone,
333-
"user_teams": user_teams,
334-
"user_projects": user_projects,
335-
"all_org_projects": all_org_projects,
336-
"user_auth_token": user_auth_token,
337-
}
328+
return None
338329

339330

340331
def fetch_run_status(run_id: int, organization: Organization) -> SeerRunState:

0 commit comments

Comments
 (0)