1+ import { tasks } from '@trigger.dev/sdk'
12import { type NextRequest , NextResponse } from 'next/server'
23import { validate as uuidValidate , v4 as uuidv4 } from 'uuid'
34import { z } from 'zod'
45import { checkHybridAuth } from '@/lib/auth/hybrid'
6+ import { env , isTruthy } from '@/lib/core/config/env'
57import { generateRequestId } from '@/lib/core/utils/request'
68import { SSE_HEADERS } from '@/lib/core/utils/sse'
9+ import { getBaseUrl } from '@/lib/core/utils/urls'
710import { processInputFileFields } from '@/lib/execution/files'
811import { preprocessExecution } from '@/lib/execution/preprocessing'
912import { createLogger } from '@/lib/logs/console/logger'
@@ -17,6 +20,7 @@ import {
1720} from '@/lib/workflows/persistence/utils'
1821import { createStreamingResponse } from '@/lib/workflows/streaming/streaming'
1922import { createHttpResponseFromBlock , workflowHasResponseBlock } from '@/lib/workflows/utils'
23+ import type { WorkflowExecutionPayload } from '@/background/workflow-execution'
2024import { type ExecutionMetadata , ExecutionSnapshot } from '@/executor/execution/snapshot'
2125import type { StreamingExecution } from '@/executor/types'
2226import { Serializer } from '@/serializer'
@@ -217,6 +221,64 @@ function resolveOutputIds(
217221 } )
218222}
219223
224+ type AsyncExecutionParams = {
225+ requestId : string
226+ workflowId : string
227+ userId : string
228+ input : any
229+ triggerType : 'api' | 'webhook' | 'schedule' | 'manual' | 'chat'
230+ }
231+
232+ /**
233+ * Handles async workflow execution by queueing a background job.
234+ * Returns immediately with a 202 Accepted response containing the job ID.
235+ */
236+ async function handleAsyncExecution ( params : AsyncExecutionParams ) : Promise < NextResponse > {
237+ const { requestId, workflowId, userId, input, triggerType } = params
238+ const useTrigger = isTruthy ( env . TRIGGER_DEV_ENABLED )
239+
240+ if ( ! useTrigger ) {
241+ logger . warn ( `[${ requestId } ] Async mode requested but TRIGGER_DEV_ENABLED is false` )
242+ return NextResponse . json (
243+ { error : 'Async execution is not enabled. Set TRIGGER_DEV_ENABLED=true to use async mode.' } ,
244+ { status : 400 }
245+ )
246+ }
247+
248+ const payload : WorkflowExecutionPayload = {
249+ workflowId,
250+ userId,
251+ input,
252+ triggerType,
253+ }
254+
255+ try {
256+ const handle = await tasks . trigger ( 'workflow-execution' , payload )
257+
258+ logger . info ( `[${ requestId } ] Queued async workflow execution` , {
259+ workflowId,
260+ jobId : handle . id ,
261+ } )
262+
263+ return NextResponse . json (
264+ {
265+ success : true ,
266+ async : true ,
267+ jobId : handle . id ,
268+ message : 'Workflow execution queued' ,
269+ statusUrl : `${ getBaseUrl ( ) } /api/jobs/${ handle . id } ` ,
270+ } ,
271+ { status : 202 }
272+ )
273+ } catch ( error : any ) {
274+ logger . error ( `[${ requestId } ] Failed to queue async execution` , error )
275+ return NextResponse . json (
276+ { error : `Failed to queue async execution: ${ error . message } ` } ,
277+ { status : 500 }
278+ )
279+ }
280+ }
281+
220282/**
221283 * POST /api/workflows/[id]/execute
222284 *
@@ -291,6 +353,8 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
291353
292354 const streamHeader = req . headers . get ( 'X-Stream-Response' ) === 'true'
293355 const enableSSE = streamHeader || streamParam === true
356+ const executionModeHeader = req . headers . get ( 'X-Execution-Mode' )
357+ const isAsyncMode = executionModeHeader === 'async'
294358
295359 logger . info ( `[${ requestId } ] Starting server-side execution` , {
296360 workflowId,
@@ -301,6 +365,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
301365 streamParam,
302366 streamHeader,
303367 enableSSE,
368+ isAsyncMode,
304369 } )
305370
306371 const executionId = uuidv4 ( )
@@ -349,6 +414,16 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
349414 workspaceId : workflow . workspaceId ,
350415 } )
351416
417+ if ( isAsyncMode ) {
418+ return handleAsyncExecution ( {
419+ requestId,
420+ workflowId,
421+ userId : actorUserId ,
422+ input,
423+ triggerType : loggingTriggerType ,
424+ } )
425+ }
426+
352427 let cachedWorkflowData : {
353428 blocks : Record < string , any >
354429 edges : any [ ]
0 commit comments