From 8790e657e999e4cf3396a0c7d8d35a9388ed9bda Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 11:48:38 -0400 Subject: [PATCH] feat(ai): include org slug in Assistant Braintrust span metadata (#49692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _Requested by **Matt Rossman** ยท [Slack thread](https://supabase.slack.com/archives/D0A79RYJKRB/p1787926891744399)_ # Problem Assistant spans in Braintrust record only the numeric `orgId`, whereas support tickets show org slug. This incurs an extra manual step to resolve the ID through admin studio before the trace can be found. # Fix Adds `orgSlug` to spans, sourced from the same verified org lookup that produces `orgId`. Renamed the request body's `orgSlug` to `rawOrgSlug` to distinguish the verified slug from getAIDetails, following the existing rawRequestedModel / requestedModel pattern. ## How to review See sample trace [94863b6d-aaa9-449a-a9c9-981ad40e614a](https://www.braintrust.dev/app/supabase.io/p/Assistant/trace?object_type=project_logs&object_id=5a8d02e5-b3b6-40cc-ba76-ecee286478f4&r=223112cd-33f4-45c4-a273-8d3781689448&s=223112cd-33f4-45c4-a273-8d3781689448) produced from sending a chat from the [Preview](https://studio-staging-git-mattrossman-ai-1149-include-698a5f-supabase.vercel.app/dashboard/org) on this PR. Note it now includes the org slug in span metadata: CleanShot 2026-08-28 at 10 59 49@2x If desired you can test yourself too by chatting with Assistant in the preview and looking up the corresponding Chat ID from Braintrust [logs](https://www.braintrust.dev/app/supabase.io/p/Assistant/logs). Closes AI-1149 --- _Generated by [Claude Code](https://claude.ai/code/session_01N2ziJech9dV19pJ9MisYdX)_ --------- Co-authored-by: Claude --- apps/studio/lib/ai/ai-details.test.ts | 3 +++ apps/studio/lib/ai/ai-details.ts | 3 +++ apps/studio/lib/ai/generate-assistant-response.ts | 3 +++ apps/studio/pages/api/ai/sql/generate-v4.ts | 9 ++++++--- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/studio/lib/ai/ai-details.test.ts b/apps/studio/lib/ai/ai-details.test.ts index 56e4b61b3a2..343d36ea6eb 100644 --- a/apps/studio/lib/ai/ai-details.test.ts +++ b/apps/studio/lib/ai/ai-details.test.ts @@ -91,6 +91,7 @@ describe('getAIDetails', () => { hasAccessToAdvanceModel: false, hasHipaaAddon: false, orgId: 1, + orgSlug: ORG_SLUG, planId: 'pro', region: 'us-east-1', isSensitive: false, @@ -189,6 +190,7 @@ describe('getAIDetails', () => { expect(result.aiOptInLevel).toBe('disabled') expect(result.hasAccessToAdvanceModel).toBe(false) expect(result.orgId).toBeUndefined() + expect(result.orgSlug).toBeUndefined() expect(result.planId).toBeUndefined() }) @@ -216,6 +218,7 @@ describe('getAIDetails', () => { expect(result.aiOptInLevel).toBe('disabled') expect(result.orgId).toBeUndefined() + expect(result.orgSlug).toBeUndefined() }) it('falls back to the most restrictive posture when project detail is unavailable', async () => { diff --git a/apps/studio/lib/ai/ai-details.ts b/apps/studio/lib/ai/ai-details.ts index be61660368d..9a4fe56875c 100644 --- a/apps/studio/lib/ai/ai-details.ts +++ b/apps/studio/lib/ai/ai-details.ts @@ -11,6 +11,7 @@ export type AIDetails = { hasAccessToAdvanceModel: boolean hasHipaaAddon: boolean | undefined orgId: number | undefined + orgSlug: string | undefined planId: string | undefined region: string | undefined isSensitive: boolean | null | undefined @@ -56,6 +57,7 @@ export const getAIDetails = async ({ // Undefined rather than false so isTracingAllowed fails closed hasHipaaAddon: undefined, orgId: undefined, + orgSlug: undefined, planId: undefined, region, isSensitive, @@ -72,6 +74,7 @@ export const getAIDetails = async ({ hasAccessToAdvanceModel: advanceModelAccess.hasAccess, hasHipaaAddon, orgId: selectedOrg.id, + orgSlug: selectedOrg.slug, planId: selectedOrg.plan.id, region, isSensitive, diff --git a/apps/studio/lib/ai/generate-assistant-response.ts b/apps/studio/lib/ai/generate-assistant-response.ts index a46b4c6f89e..ccb02cc2866 100644 --- a/apps/studio/lib/ai/generate-assistant-response.ts +++ b/apps/studio/lib/ai/generate-assistant-response.ts @@ -39,6 +39,7 @@ export async function generateAssistantResponse({ supportMode, userId, orgId, + orgSlug, planId, includesLogsSnippets, isExplorerEnabled, @@ -60,6 +61,7 @@ export async function generateAssistantResponse({ supportMode?: boolean userId?: string orgId?: number + orgSlug?: string planId?: string /** Whether any user message in the conversation attached a logs (ClickHouse) query. */ includesLogsSnippets?: boolean @@ -171,6 +173,7 @@ export async function generateAssistantResponse({ aiOptInLevel, userId, orgId, + orgSlug, planId, requestedModel, gitBranch: process.env.VERCEL_GIT_COMMIT_REF, diff --git a/apps/studio/pages/api/ai/sql/generate-v4.ts b/apps/studio/pages/api/ai/sql/generate-v4.ts index 1b056af7c64..bd16a812d6c 100644 --- a/apps/studio/pages/api/ai/sql/generate-v4.ts +++ b/apps/studio/pages/api/ai/sql/generate-v4.ts @@ -96,7 +96,7 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse, claims?: Jw messages: rawMessages, projectRef, connectionString, - orgSlug, + orgSlug: rawOrgSlug, chatId, chatName, model: rawRequestedModel, @@ -126,6 +126,7 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse, claims?: Jw let projectIsSensitive: boolean | null | undefined let projectRegion: string | undefined let orgId: number | undefined + let orgSlug: string | undefined let planId: string | undefined if (!IS_PLATFORM) { @@ -133,14 +134,15 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse, claims?: Jw hasAccessToAdvanceModel = true } - if (IS_PLATFORM && orgSlug && authorization && projectRef) { + if (IS_PLATFORM && rawOrgSlug && authorization && projectRef) { try { - const aiDetails = await getAIDetails({ orgSlug, projectRef, authorization }) + const aiDetails = await getAIDetails({ orgSlug: rawOrgSlug, projectRef, authorization }) aiOptInLevel = aiDetails.aiOptInLevel hasAccessToAdvanceModel = aiDetails.hasAccessToAdvanceModel orgHasHipaaAddon = aiDetails.hasHipaaAddon orgId = aiDetails.orgId + orgSlug = aiDetails.orgSlug planId = aiDetails.planId projectIsSensitive = aiDetails.isSensitive projectRegion = aiDetails.region @@ -234,6 +236,7 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse, claims?: Jw supportMode, userId, orgId, + orgSlug, planId, includesLogsSnippets, isExplorerEnabled: explorerEnabled,