Skip to content

Commit 85ce7fe

Browse files
committed
feat(webapp): pin the dashboard agent to a deployed version
The dashboard agent (a chat.agent in its own Trigger.dev project) can now be deployed independently of the app that talks to it. A new workflow deploys the agent with --skip-promotion, so a deploy never becomes current on its own, and the app pins its sessions to a specific version via DASHBOARD_AGENT_VERSION (unset falls back to the project env's current version). The pin flows through to session start, head start, and every continuation run, so cutting over is a config flip rather than a redeploy.
1 parent cbd1060 commit 85ce7fe

4 files changed

Lines changed: 86 additions & 2 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: "🤖 Deploy dashboard agent"
2+
3+
# Deploys the @internal/dashboard-agent chat.agent to its Trigger.dev project
4+
# with --skip-promotion, so a deploy never becomes "current" on its own. The
5+
# consuming app cuts over by pinning DASHBOARD_AGENT_VERSION to the new version.
6+
# Pushes to main that touch the agent auto-deploy to staging; prod is a manual
7+
# workflow_dispatch. The project ref + a scoped deploy PAT come from the target
8+
# environment (dashboard-agent-staging / dashboard-agent-prod).
9+
10+
on:
11+
push:
12+
branches: [main]
13+
paths:
14+
- "internal-packages/dashboard-agent/**"
15+
workflow_dispatch:
16+
inputs:
17+
environment:
18+
description: "Trigger.dev environment to deploy to"
19+
type: choice
20+
options: [staging, prod]
21+
default: staging
22+
23+
permissions: {}
24+
25+
concurrency:
26+
group: dashboard-agent-deploy-${{ github.event.inputs.environment || 'staging' }}
27+
cancel-in-progress: false
28+
29+
jobs:
30+
deploy:
31+
name: Deploy dashboard agent
32+
runs-on: ubuntu-latest
33+
environment: dashboard-agent-${{ github.event.inputs.environment || 'staging' }}
34+
permissions:
35+
contents: read
36+
env:
37+
TRIGGER_API_URL: https://api.trigger.dev
38+
TRIGGER_DASHBOARD_AGENT_PROJECT_REF: ${{ vars.TRIGGER_DASHBOARD_AGENT_PROJECT_REF }}
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
42+
with:
43+
persist-credentials: false
44+
45+
- name: Setup pnpm
46+
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
47+
with:
48+
version: 10.33.2
49+
50+
- name: Setup node
51+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
52+
with:
53+
node-version: 20.20.2
54+
cache: "pnpm"
55+
56+
- name: Install + build the CLI and the agent's deps
57+
run: |
58+
set -euo pipefail
59+
pnpm install --frozen-lockfile
60+
# Prisma client is needed because the build closure pulls in @trigger.dev/database.
61+
pnpm run generate
62+
# Config-time imports the agent's trigger.config.ts needs: defineConfig (sdk), aptGet (build).
63+
pnpm run build --filter trigger.dev --filter @trigger.dev/build --filter @trigger.dev/sdk
64+
65+
- name: Deploy (--skip-promotion)
66+
working-directory: internal-packages/dashboard-agent
67+
env:
68+
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_DASHBOARD_AGENT_DEPLOY_TOKEN }}
69+
# Invoke the built CLI directly (what the workspace .bin/trigger wrapper does),
70+
# so a not-yet-linked bin after a fresh install can't break the deploy.
71+
run: node ../../packages/cli-v3/dist/esm/index.js deploy --skip-promotion --env ${{ github.event.inputs.environment || 'staging' }}

apps/webapp/app/env.server.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ const EnvironmentSchema = z
106106
// standard chat.agent SDK flow. When unset, the live agent is disabled — the
107107
// conversation store / History still work, no chat can start.
108108
DASHBOARD_AGENT_SECRET_KEY: z.string().optional(),
109+
// Pins agent sessions to a specific deployed version (paired with
110+
// --skip-promotion deploys); unset => the project env's current version.
111+
DASHBOARD_AGENT_VERSION: z.string().optional(),
109112
// Global default for the `hasDashboardAgentAccess` flag. "0" (off) ships the
110113
// agent dark; flip to "1" to enable it for everyone at GA. Per-org overrides
111114
// (org featureFlags) win regardless.

apps/webapp/app/services/dashboardAgent.server.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,22 @@ export function isDashboardAgentConfigured(): boolean {
5757
return Boolean(env.DASHBOARD_AGENT_SECRET_KEY);
5858
}
5959

60+
// Pins every agent session (and its continuation runs) to a deployed version
61+
// when DASHBOARD_AGENT_VERSION is set; unset runs on the env's current version.
62+
export function dashboardAgentTriggerConfig(): { lockToVersion: string } | undefined {
63+
return env.DASHBOARD_AGENT_VERSION ? { lockToVersion: env.DASHBOARD_AGENT_VERSION } : undefined;
64+
}
65+
6066
export async function startDashboardAgentSession(params: {
6167
chatId: string;
6268
clientData?: Record<string, unknown>;
6369
}): Promise<{ publicAccessToken: string }> {
6470
const config = dashboardAgentConfig();
6571
if (!config) throw new Error("DASHBOARD_AGENT_SECRET_KEY is not set");
66-
const startSession = chat.createStartSessionAction(TASK_ID, { apiClient: config });
72+
const startSession = chat.createStartSessionAction(TASK_ID, {
73+
apiClient: config,
74+
triggerConfig: dashboardAgentTriggerConfig(),
75+
});
6776
return startSession({ chatId: params.chatId, clientData: params.clientData });
6877
}
6978

apps/webapp/app/services/dashboardAgentHeadStart.server.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import { chat as chatServer } from "@trigger.dev/sdk/chat-server";
1010
import { streamText, type UIMessage } from "ai";
1111
import { env } from "~/env.server";
12-
import { dashboardAgentApiOrigin } from "~/services/dashboardAgent.server";
12+
import { dashboardAgentApiOrigin, dashboardAgentTriggerConfig } from "~/services/dashboardAgent.server";
1313
import { logger } from "~/services/logger.server";
1414

1515
const TASK_ID = "dashboard-agent";
@@ -43,6 +43,7 @@ export async function startDashboardAgentHeadStart(params: {
4343
chatId: params.chatId,
4444
messages: params.messages,
4545
metadata: params.metadata,
46+
triggerConfig: dashboardAgentTriggerConfig(),
4647
// Scope session creation + the agent trigger to the agent's project/env. The
4748
// Anthropic key here only powers the warm step-1 call.
4849
apiClient: {

0 commit comments

Comments
 (0)