diff --git a/apps/webapp/app/components/dashboard-agent/DashboardAgent.tsx b/apps/webapp/app/components/dashboard-agent/DashboardAgent.tsx
index 47e280da1f1..2796c8516df 100644
--- a/apps/webapp/app/components/dashboard-agent/DashboardAgent.tsx
+++ b/apps/webapp/app/components/dashboard-agent/DashboardAgent.tsx
@@ -1,4 +1,3 @@
-import { SparklesIcon } from "@heroicons/react/20/solid";
import { useState } from "react";
import {
ResizableHandle,
@@ -6,17 +5,19 @@ import {
ResizablePanelGroup,
} from "~/components/primitives/Resizable";
import { DashboardAgentPanel } from "./DashboardAgentPanel";
+import { DashboardAgentProvider } from "./dashboardAgentLauncher";
/**
* Mounts the dashboard agent in the env layout. Renders the page content
- * (`children` = the route Outlet); when the agent is open it splits the layout
- * into a resizable content + agent panel using the shared Resizable primitive,
- * with `autosaveId` persisting the width. When closed it's a floating launcher.
+ * (`children` = the route Outlet) and shares the open/close state via context so
+ * the page-header launcher (`DashboardAgentLauncher`) can toggle it. When open it
+ * splits the layout into a resizable content + agent panel, `autosaveId` persists
+ * the width.
*
- * `hasAccess` is resolved server-side in the env layout loader (via
- * `canAccessDashboardAgent`: global env, admins/impersonators, then the
- * global/per-org feature flag, default off), so the launcher is hidden unless
- * the agent is enabled. The resource routes enforce the same check server-side.
+ * `hasAccess` is resolved server-side in the env layout loader
+ * (`canAccessDashboardAgent`); when false we render the content untouched and
+ * never expose the context, so the launcher stays hidden. The resource routes
+ * enforce the same check server-side.
*/
export function DashboardAgent({
children,
@@ -31,36 +32,25 @@ export function DashboardAgent({
return