diff --git a/static/app/components/sidebar/index.tsx b/static/app/components/sidebar/index.tsx
index 305e8c8655a1bf..0f9f105e32edcd 100644
--- a/static/app/components/sidebar/index.tsx
+++ b/static/app/components/sidebar/index.tsx
@@ -53,7 +53,12 @@ import {useLocation} from 'sentry/utils/useLocation';
import useMedia from 'sentry/utils/useMedia';
import useOrganization from 'sentry/utils/useOrganization';
import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
+import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
+import {
+ AGENTS_LANDING_SUB_PATH,
+ AGENTS_SIDEBAR_LABEL,
+} from 'sentry/views/insights/pages/agents/settings';
import {
AI_LANDING_SUB_PATH,
AI_SIDEBAR_LABEL,
@@ -380,13 +385,26 @@ function Sidebar() {
id="performance-domains-mobile"
icon={}
/>
- }
- />
+ (
+ }
+ />
+ )}
+ >
+ }
+ />
+
);
diff --git a/static/app/routes.tsx b/static/app/routes.tsx
index 6de4b01a93ad69..8511087af5e12e 100644
--- a/static/app/routes.tsx
+++ b/static/app/routes.tsx
@@ -17,6 +17,7 @@ import AuthLayout from 'sentry/views/auth/layout';
import {automationRoutes} from 'sentry/views/automations/routes';
import {detectorRoutes} from 'sentry/views/detectors/routes';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
+import {AGENTS_LANDING_SUB_PATH} from 'sentry/views/insights/pages/agents/settings';
import {AI_LANDING_SUB_PATH} from 'sentry/views/insights/pages/ai/settings';
import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
@@ -1797,6 +1798,16 @@ function buildRoutes() {
{traceViewRoute}
{moduleRoutes}
+
+ import('sentry/views/insights/agentMonitoring/views/agentsOverviewPage')
+ )}
+ />
+ {transactionSummaryRoutes}
+ {traceViewRoute}
+ {moduleRoutes}
+
import('sentry/views/projects/'))}>
{projectsChildRoutes}
diff --git a/static/app/utils/analytics/insightAnalyticEvents.tsx b/static/app/utils/analytics/insightAnalyticEvents.tsx
index 855fc0b322777e..fd0c77a1a8047d 100644
--- a/static/app/utils/analytics/insightAnalyticEvents.tsx
+++ b/static/app/utils/analytics/insightAnalyticEvents.tsx
@@ -23,6 +23,7 @@ export type InsightEventParameters = {
'insight.general.select_region_value': {regions: string[]};
'insight.general.table_paginate': {direction: string; source: string};
'insight.general.table_sort': {direction: string; field: string; source: string};
+ 'insight.page_loads.agents': {has_ever_sent_data: boolean; view: DomainView};
'insight.page_loads.ai': {has_ever_sent_data: boolean; view: DomainView};
'insight.page_loads.app_start': {has_ever_sent_data: boolean; view: DomainView};
'insight.page_loads.assets': {has_ever_sent_data: boolean; view: DomainView};
@@ -55,6 +56,7 @@ export type InsightEventKey = keyof InsightEventParameters;
export const insightEventMap: Record = {
'insights.page_loads.overview': 'Insights: Overview Page Load',
'insight.page_loads.ai': 'Insights: AI Page Load',
+ 'insight.page_loads.agents': 'Insights: Agents Page Load',
'insight.page_loads.app_start': 'Insights: App Start Page Load',
'insight.page_loads.assets': 'Insights: Assets Page Load',
'insight.page_loads.cache': 'Insights: Cache Page Load',
diff --git a/static/app/views/insights/agentMonitoring/settings.ts b/static/app/views/insights/agentMonitoring/settings.ts
new file mode 100644
index 00000000000000..cac0d93346e5f8
--- /dev/null
+++ b/static/app/views/insights/agentMonitoring/settings.ts
@@ -0,0 +1,11 @@
+import {t} from 'sentry/locale';
+
+export const MODULE_TITLE = t('Overview');
+export const BASE_URL = '';
+
+export const DATA_TYPE = t('Agent');
+export const DATA_TYPE_PLURAL = t('Agents');
+
+export const MODULE_DOC_LINK = 'https://docs.sentry.io/product/insights/ai/';
+
+export const MODULE_FEATURES = ['insights-addon-modules', 'agents-insights'];
diff --git a/static/app/views/insights/agentMonitoring/utils/features.tsx b/static/app/views/insights/agentMonitoring/utils/features.tsx
new file mode 100644
index 00000000000000..ce893506b9f76a
--- /dev/null
+++ b/static/app/views/insights/agentMonitoring/utils/features.tsx
@@ -0,0 +1,17 @@
+import Feature from 'sentry/components/acl/feature';
+import {NoAccess} from 'sentry/components/noAccess';
+import type {Organization} from 'sentry/types/organization';
+
+export function hasAgentInsights(organization: Organization) {
+ return organization.features.includes('agents-insights');
+}
+
+type AgentInsightsFeatureProps = Omit[0], 'features'>;
+
+export function AgentInsightsFeature(props: AgentInsightsFeatureProps) {
+ return (
+
+ {props.children}
+
+ );
+}
diff --git a/static/app/views/insights/agentMonitoring/views/agentsOverviewPage.tsx b/static/app/views/insights/agentMonitoring/views/agentsOverviewPage.tsx
new file mode 100644
index 00000000000000..c0218da5fb4adb
--- /dev/null
+++ b/static/app/views/insights/agentMonitoring/views/agentsOverviewPage.tsx
@@ -0,0 +1,57 @@
+import styled from '@emotion/styled';
+
+import * as Layout from 'sentry/components/layouts/thirds';
+import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
+import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
+import {ModulePageFilterBar} from 'sentry/views/insights/common/components/modulePageFilterBar';
+import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders';
+import {ModuleBodyUpsellHook} from 'sentry/views/insights/common/components/moduleUpsellHookWrapper';
+import {AgentsPageHeader} from 'sentry/views/insights/pages/agents/agentsPageHeader';
+import {ModuleName} from 'sentry/views/insights/types';
+
+function AgentsMonitoringPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ Agent Monitoring Dashboard
+
+
+
+
+
+
+ );
+}
+
+function PageWithProviders() {
+ return (
+
+
+
+
+
+ );
+}
+
+const DashboardPlaceholder = styled('div')`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: ${p => p.theme.gray300};
+ font-size: ${p => p.theme.fontSizeLarge};
+ font-weight: ${p => p.theme.fontWeightBold};
+`;
+
+export default PageWithProviders;
diff --git a/static/app/views/insights/common/components/modulesOnboarding.tsx b/static/app/views/insights/common/components/modulesOnboarding.tsx
index 85ce0d7f57d7af..df1060d77359b4 100644
--- a/static/app/views/insights/common/components/modulesOnboarding.tsx
+++ b/static/app/views/insights/common/components/modulesOnboarding.tsx
@@ -307,6 +307,13 @@ const EMPTY_STATE_CONTENT: Record = {
imageSrc: llmPreviewImg,
supportedSdks: ['python'],
},
+ agents: {
+ heading: t('TODO'),
+ description: t('TODO'),
+ valuePropDescription: t('Mobile UI load insights include:'),
+ valuePropPoints: [],
+ imageSrc: screenLoadsPreviewImg,
+ },
'mobile-ui': {
heading: t('TODO'),
description: t('TODO'),
diff --git a/static/app/views/insights/common/queries/useHasFirstSpan.tsx b/static/app/views/insights/common/queries/useHasFirstSpan.tsx
index cdd1ede6ba6637..392033cb223202 100644
--- a/static/app/views/insights/common/queries/useHasFirstSpan.tsx
+++ b/static/app/views/insights/common/queries/useHasFirstSpan.tsx
@@ -11,6 +11,7 @@ const excludedModuleNames = [
ModuleName.CRONS,
ModuleName.UPTIME,
ModuleName.SESSIONS,
+ ModuleName.AGENTS,
] as const;
type ExcludedModuleNames = (typeof excludedModuleNames)[number];
diff --git a/static/app/views/insights/common/utils/useModuleURL.tsx b/static/app/views/insights/common/utils/useModuleURL.tsx
index c5b9cc07f43c57..353444f781f7d8 100644
--- a/static/app/views/insights/common/utils/useModuleURL.tsx
+++ b/static/app/views/insights/common/utils/useModuleURL.tsx
@@ -1,5 +1,6 @@
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useOrganization from 'sentry/utils/useOrganization';
+import {BASE_URL as AGENTS_BASE_URL} from 'sentry/views/insights/agentMonitoring/settings';
import {BASE_URL as RESOURCES_BASE_URL} from 'sentry/views/insights/browser/resources/settings';
import {BASE_URL as VITALS_BASE_URL} from 'sentry/views/insights/browser/webVitals/settings';
import {BASE_URL as CACHE_BASE_URL} from 'sentry/views/insights/cache/settings';
@@ -33,6 +34,7 @@ export const MODULE_BASE_URLS: Record = {
[ModuleName.VITAL]: VITALS_BASE_URL,
[ModuleName.RESOURCE]: RESOURCES_BASE_URL,
[ModuleName.AI]: AI_BASE_URL,
+ [ModuleName.AGENTS]: AGENTS_BASE_URL,
[ModuleName.MOBILE_UI]: MOBILE_UI_BASE_URL,
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_BASE_URL,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_BASE_URL,
diff --git a/static/app/views/insights/common/views/spans/selectors/actionSelector.tsx b/static/app/views/insights/common/views/spans/selectors/actionSelector.tsx
index 395d2f3748926c..07faca7fa8ac42 100644
--- a/static/app/views/insights/common/views/spans/selectors/actionSelector.tsx
+++ b/static/app/views/insights/common/views/spans/selectors/actionSelector.tsx
@@ -132,5 +132,6 @@ const LABEL_FOR_MODULE_NAME: Record = {
'mobile-vitals': t('Action'),
'screen-rendering': t('Action'),
ai: 'Action',
+ agents: t('Action'),
sessions: t('Action'),
};
diff --git a/static/app/views/insights/pages/agents/agentsPageHeader.tsx b/static/app/views/insights/pages/agents/agentsPageHeader.tsx
new file mode 100644
index 00000000000000..cfe1835270a090
--- /dev/null
+++ b/static/app/views/insights/pages/agents/agentsPageHeader.tsx
@@ -0,0 +1,51 @@
+import normalizeUrl from 'sentry/utils/url/normalizeUrl';
+import useOrganization from 'sentry/utils/useOrganization';
+import {
+ AGENTS_LANDING_SUB_PATH,
+ AGENTS_LANDING_TITLE,
+ MODULES,
+} from 'sentry/views/insights/pages/agents/settings';
+import {
+ DomainViewHeader,
+ type Props as HeaderProps,
+} from 'sentry/views/insights/pages/domainViewHeader';
+import {DOMAIN_VIEW_BASE_URL} from 'sentry/views/insights/pages/settings';
+
+type Props = {
+ breadcrumbs?: HeaderProps['additionalBreadCrumbs'];
+ headerActions?: HeaderProps['additonalHeaderActions'];
+ headerTitle?: HeaderProps['headerTitle'];
+ hideDefaultTabs?: HeaderProps['hideDefaultTabs'];
+ module?: HeaderProps['selectedModule'];
+ tabs?: HeaderProps['tabs'];
+};
+
+export function AgentsPageHeader({
+ module,
+ headerTitle,
+ headerActions,
+ breadcrumbs,
+ tabs,
+ hideDefaultTabs,
+}: Props) {
+ const {slug} = useOrganization();
+
+ const agentsBaseUrl = normalizeUrl(
+ `/organizations/${slug}/${DOMAIN_VIEW_BASE_URL}/${AGENTS_LANDING_SUB_PATH}`
+ );
+
+ return (
+
+ );
+}
diff --git a/static/app/views/insights/pages/agents/settings.ts b/static/app/views/insights/pages/agents/settings.ts
new file mode 100644
index 00000000000000..fd5ef5f7d64b94
--- /dev/null
+++ b/static/app/views/insights/pages/agents/settings.ts
@@ -0,0 +1,8 @@
+import {t} from 'sentry/locale';
+import {ModuleName} from 'sentry/views/insights/types';
+
+export const AGENTS_LANDING_SUB_PATH = 'agents';
+export const AGENTS_LANDING_TITLE = t('Agents');
+export const AGENTS_SIDEBAR_LABEL = t('Agents');
+
+export const MODULES = [ModuleName.AGENTS];
diff --git a/static/app/views/insights/settings.ts b/static/app/views/insights/settings.ts
index b27be8d60d6848..a574dd92e08585 100644
--- a/static/app/views/insights/settings.ts
+++ b/static/app/views/insights/settings.ts
@@ -1,4 +1,11 @@
import {t} from 'sentry/locale';
+import {
+ DATA_TYPE as AGENTS_DATA_TYPE,
+ DATA_TYPE_PLURAL as AGENTS_DATA_TYPE_PLURAL,
+ MODULE_DOC_LINK as AGENTS_MODULE_DOC_LINK,
+ MODULE_FEATURES as AGENTS_MODULE_FEATURES,
+ MODULE_TITLE as AGENTS_MODULE_TITLE,
+} from 'sentry/views/insights/agentMonitoring/settings';
import {
DATA_TYPE as RESOURCE_DATA_TYPE,
DATA_TYPE_PLURAL as RESOURCE_DATA_TYPE_PLURAL,
@@ -128,6 +135,7 @@ export const MODULE_TITLES: Record = {
[ModuleName.VITAL]: VITALS_MODULE_TITLE,
[ModuleName.RESOURCE]: RESOURCES_MODULE_TITLE,
[ModuleName.AI]: AI_MODULE_TITLE,
+ [ModuleName.AGENTS]: AGENTS_MODULE_TITLE,
[ModuleName.MOBILE_UI]: MOBILE_UI_MODULE_TITLE,
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_MODULE_TITLE,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_MODULE_TITLE,
@@ -147,6 +155,7 @@ export const MODULE_DATA_TYPES: Record = {
[ModuleName.VITAL]: WEB_VITALS_DATA_TYPE,
[ModuleName.RESOURCE]: RESOURCE_DATA_TYPE,
[ModuleName.AI]: AI_DATA_TYPE,
+ [ModuleName.AGENTS]: AGENTS_DATA_TYPE,
[ModuleName.MOBILE_UI]: t('Mobile UI'),
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_DATA_TYPE,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_DATA_TYPE,
@@ -166,6 +175,7 @@ export const MODULE_DATA_TYPES_PLURAL: Record = {
[ModuleName.VITAL]: WEB_VITALS_DATA_TYPE_PLURAL,
[ModuleName.RESOURCE]: RESOURCE_DATA_TYPE_PLURAL,
[ModuleName.AI]: AI_DATA_TYPE_PLURAL,
+ [ModuleName.AGENTS]: AGENTS_DATA_TYPE_PLURAL,
[ModuleName.MOBILE_UI]: t('Mobile UI'),
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_DATA_TYPE_PLURAL,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_DATA_TYPE_PLURAL,
@@ -188,6 +198,7 @@ export const MODULE_PRODUCT_DOC_LINKS = {
[ModuleName.VITAL]: VITALS_MODULE_DOC_LINK,
[ModuleName.RESOURCE]: RESOURCES_MODULE_DOC_LINK,
[ModuleName.AI]: AI_MODULE_DOC_LINK,
+ [ModuleName.AGENTS]: AGENTS_MODULE_DOC_LINK,
[ModuleName.MOBILE_UI]: MODULE_UI_DOC_LINK,
[ModuleName.MOBILE_VITALS]: MODULE_SCREENS_DOC_LINK,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_MODULE_DOC_LINK,
@@ -212,6 +223,7 @@ export const MODULE_FEATURE_MAP: Record = {
[ModuleName.CACHE]: CACHE_MODULE_FEATURES,
[ModuleName.QUEUE]: QUEUE_MODULE_FEATURES,
[ModuleName.AI]: AI_MODULE_FEATURES,
+ [ModuleName.AGENTS]: AGENTS_MODULE_FEATURES,
[ModuleName.SCREEN_LOAD]: SCREEN_LOADS_MODULE_FEATURES,
[ModuleName.MOBILE_UI]: MOBILE_UI_MODULE_FEATURES,
[ModuleName.MOBILE_VITALS]: [MOBILE_SCREENS_MODULE_FEATURE],
@@ -234,6 +246,7 @@ export const MODULE_FEATURE_VISIBLE_MAP: Record = {
[ModuleName.CACHE]: ['insights-entry-points'],
[ModuleName.QUEUE]: ['insights-entry-points'],
[ModuleName.AI]: ['insights-entry-points'],
+ [ModuleName.AGENTS]: ['insights-entry-points'],
[ModuleName.SCREEN_LOAD]: ['insights-entry-points'],
[ModuleName.MOBILE_UI]: ['insights-entry-points'],
[ModuleName.MOBILE_VITALS]: ['insights-entry-points'],
diff --git a/static/app/views/insights/types.tsx b/static/app/views/insights/types.tsx
index af3bf96a61592f..6b42fa5cc13d01 100644
--- a/static/app/views/insights/types.tsx
+++ b/static/app/views/insights/types.tsx
@@ -11,6 +11,7 @@ export enum ModuleName {
APP_START = 'app_start',
RESOURCE = 'resource',
AI = 'ai',
+ AGENTS = 'agents',
MOBILE_UI = 'mobile-ui',
MOBILE_VITALS = 'mobile-vitals',
SCREEN_RENDERING = 'screen-rendering',
diff --git a/static/app/views/nav/secondary/sections/insights/insightsSecondaryNav.tsx b/static/app/views/nav/secondary/sections/insights/insightsSecondaryNav.tsx
index c2d32f728fb20e..d1119cf93bf5a0 100644
--- a/static/app/views/nav/secondary/sections/insights/insightsSecondaryNav.tsx
+++ b/static/app/views/nav/secondary/sections/insights/insightsSecondaryNav.tsx
@@ -8,7 +8,12 @@ import type {Project} from 'sentry/types/project';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import useProjects from 'sentry/utils/useProjects';
+import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
+import {
+ AGENTS_LANDING_SUB_PATH,
+ AGENTS_SIDEBAR_LABEL,
+} from 'sentry/views/insights/pages/agents/settings';
import {
AI_LANDING_SUB_PATH,
AI_SIDEBAR_LABEL,
@@ -91,12 +96,25 @@ export function InsightsSecondaryNav() {
>
{MOBILE_SIDEBAR_LABEL}
- (
+
+ {AI_SIDEBAR_LABEL}
+
+ )}
>
- {AI_SIDEBAR_LABEL}
-
+
+ {AGENTS_SIDEBAR_LABEL}
+
+