Architecture: Trigger.dev Integration
Status: Active
Last updated: 2026-05-02
Audience: AI agents and engineers reasoning about how the API
hands long-running work off to Trigger.dev, why the platform splits
the API process from the worker process, and what the dispatch
contracts look like end-to-end.
1. Purpose
Long-running operations (work generation, Awesome README import, scheduled dispatch) cannot run inside an HTTP request — they take minutes to hours, must survive API redeploys, and need their own resource budget. The platform delegates these to Trigger.dev: the API enqueues a typed payload, Trigger.dev runs the task on its own infrastructure, and the worker calls back into the API over a narrow internal HTTP surface to read work state, write generation history, and update plugin settings.
This spec covers the integration story — the dispatch path, the
payload contracts, the cross-process callback channel, the
configuration contract, the run lifecycle, and the operational
surface (cancellation, retries, monitoring). For the internal task
package layout and bootstrap pattern, see the companion
trigger-worker spec.
2. The Two-Process Split
┌──────────────────────────────────────────────────────────────────┐
│ apps/api (NestJS HTTP server) │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ WorkGenerationService.startGeneration() │ │
│ │ ├── Create WorkGenerationHistory row │ │
│ │ ├── Build WorkGenerationPayload │ │
│ │ └── Call WORK_GENERATION_DISPATCHER.dispatch(...) │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ TriggerService (packages/tasks/src/trigger/) │ │
│ │ workGenerationTask.trigger(payload, { tags, ... }) │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ TriggerInternalController (POST /internal/trigger/*) │ │
│ │ - GET /works/:id/context │ │