## Summary Adds an in-dashboard AI agent: a chat panel, reachable from any environment page, that answers questions about your runs, errors, tasks, and analytics, diagnoses why a run failed, charts your data, reads your connected repo's source, and answers product and how-to questions. It is gated behind the `hasDashboardAgentAccess` feature flag (global or per-org, default off), so this PR ships disabled: the launcher is hidden unless the flag is enabled. ## Design The agent runs as a standalone `chat.agent` Trigger task in its own internal package, with no access to the webapp database, Prisma, or ClickHouse. It reads the user's data over the public API, acting as the user via a short-lived delegated user-actor token minted server-side each turn (never in the browser), building on [#3997](https://github.com/triggerdotdev/trigger.dev/pull/3997). The error and analytics tools use [#4005](https://github.com/triggerdotdev/trigger.dev/pull/4005) and the TRQL query API. The first turn of a new chat streams from a warm webapp route (Head Start) while the durable agent boots in parallel. Structured answers (a run-failure diagnosis card, a live chart) render through a small typed view catalog rather than arbitrary markup. A knowledge lane forwards product and how-to questions to the support assistant. Conversation history lives in a separate Drizzle-backed store on its own Postgres schema, kept as a display read-model so it can never corrupt the agent's model context. The SDK changes add an `apiClient` option to `chat.createStartSessionAction` and `chat.headStart`, and keep the Head Start tool-approval tail intact across a custom `prepareMessages` hook so prompt caching and Head Start compose.
1.6 KiB
@internal/dashboard-agent
The in-dashboard agent, built on chat.agent and deployed as its own Trigger
project. This is the launch-week dogfood: we run our own product on the
primitive we ship.
Why a separate package (not inside apps/webapp)
The agent has no access to the main database, ClickHouse, or webapp internals — it reads everything via the API. Living in a standalone package that doesn't depend on the webapp makes that firewall structural: the package physically cannot import webapp server code. It also keeps the webapp a pure Remix app instead of a dual Remix-app-and-Trigger-project, and gives the agent a small, fast, independently deployable + testable build context.
It writes conversation state to its own datastore via @internal/dashboard-agent-db
(the same package the webapp reads from for the History tab). It never touches
Prisma.
Deploy / dev
This is a Trigger project with its own trigger.config.ts. The project ref is
read from TRIGGER_DASHBOARD_AGENT_PROJECT_REF (never hardcoded — public repo).
cd internal-packages/dashboard-agent
TRIGGER_DASHBOARD_AGENT_PROJECT_REF=<your-project> pnpm run dev # trigger dev
TRIGGER_DASHBOARD_AGENT_PROJECT_REF=<your-project> pnpm run deploy # trigger deploy
Runtime env the deployed task needs: DASHBOARD_AGENT_DATABASE_URL (the agent
datastore) and OBJECT_STORE_* (chat.agent's built-in conversation snapshot).
Consumed by the webapp
The webapp imports only the task type for transport type-safety:
import type { dashboardAgent } from "@internal/dashboard-agent";
Never a value import (see src/index.ts).