Skip to content

feat: Support parallel waits (native Promise.all) #3346

@nickluger

Description

@nickluger

Is your feature request related to a problem? Please describe.

Missing parallel waits (e.g., in Promise.all or just used by tools you don't control like Vercel AI SDK) is a potential deal-breaker for many agentic workflows, because it breaks quite natural behavior in the JS ecosystem.

In other words, AI agents cannot call trigger.dev subtasks themselves autonomously if they happen to call more than one tool that uses a subtask.

In other words, tasks themselves are NOT a valid, native primitive in AI/agentic flows or operations if any form of concurrency is required.

This is worse than it sounds in the first place. In some way it breaks the value-add provided by trigger dev.

The concept behind tools is dependency injection, so things like batchTriggerAndWait aren't helpful workarounds here. It's crazy to watch your entire code base and npm dependencies for nested Promise.all calls (a native primitive thought to be simply functioning in JS).

Also, for some models, preventing parallel tool calls might still be best effort not all have parallel_tool_calls: false

Of course you can use functions instead of subtask-triggering, but then you cannot vary machine sizes or other options like retries depending on the task type - which makes this an either or - use JS-native primitives OR be able to leverage the Trigger.dev primitives/features

I'm thinking about writing a helper that somehow collects all native trigger-invocations in a tick or some time-span, then batches them into one triggerByTaskAndWait call, then resolves them back to their respective call sites. But I feel strongly that should not be in userland, plus it's brittle and does not correctly represent the actual behavior of Promise.all.

Describe the solution you'd like to see

await Promise.all(multiplePromisesTriggeringTasks)

or

   await generateText({
          messages: [systemMessage, userMessage],
          // ....
          tools: {
            searchWeb: makeSearchWebTool({
              searchWeb: effectiveSearchWeb,
            }),
            visitUrl: makeVisitUrlTool({
              contentMode: VisitUrlToolContentMode.SAMPLED_MARKDOWN,
              visitUrl: effectiveVisitUrl,
            }),
          },
        })

Should "just work" - when these tools might trigger new task runs concurrently - which would cause multiple parallel waits.

Describe alternate solutions

Requiring special wrappers would be ok, too:

await someSpecialWrapperHandlingMultipleAwaits(Promise.all(multiplePromisesTriggeringTasks))

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions