Generated banner for Upstash Workflow JS
Generated logo for Upstash Workflow JS

Upstash Workflow JS

UpstashOfficialCreated by Upstash

  • Skill
  • Tool integration
  • Cloud and DevOps
  • MIT
  • Medium risk

From the author

Work with the @upstash/workflow TypeScript/JavaScript SDK for durable, long-running workflows in serverless functions, multi-step processes that survive timeouts, retries, and restarts (built on QStash). Use when defining a workflow endpoint with serve(), running steps with context.run, sleeping for minutes to days without holding a function open, calling external APIs with context.call, waiting for an external event or webhook, invoking other workflows, configuring retries, failure callbacks, and a DLQ, controlling concurrency, rate, and parallelism, triggering, cancelling, or inspecting runs with the Workflow client, building AI agents and orchestrators, human-in-the-loop approvals, realtime updates, local development with the QStash dev server, adding middleware, or migrating workflows safely. Also use when the user asks for durable execution, step functions, saga or orchestration patterns, background jobs with checkpoints, or long-running tasks on Vercel, Next.js, Cloudflare Workers, or other serverless
— the description by Upstash

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The Upstash Workflow SDK enables developers to create reliable, multi-step workflows within serverless environments. By leveraging QStash, it allows functions to survive timeouts, retries, and restarts, effectively managing long-running processes that span minutes or days without keeping the underlying function execution active. It supports complex orchestration patterns, including step-by-step execution, external API calls, event waiting, human-in-the-loop approvals, and sophisticated flow control.

What it does

  • Exposes serverless endpoints for durable workflow execution.
  • Manages multi-step processes that persist across function restarts and timeouts.
  • Provides tools for flow control, including concurrency, rate limiting, and parallelism.
  • Supports advanced patterns like cross-workflow invocation and waiting for external events.
  • Enables local development and testing via the QStash dev server.
  • Facilitates human-in-the-loop workflows and real-time updates.

When to use it

  • When building long-running tasks that exceed standard serverless function execution limits.
  • When implementing saga or orchestration patterns in a distributed system.
  • When you need reliable background jobs with built-in checkpointing and retries.
  • When building AI agents or orchestrators that require stateful, multi-step execution.
  • When integrating human approval steps into automated backend processes.

Advantages

  • Eliminates the need to hold serverless functions open for long durations.
  • Built-in support for retries, failure callbacks, and dead-letter queues.
  • Seamless integration with popular serverless platforms like Vercel and Cloudflare Workers.
  • Simplifies complex state management for asynchronous operations.

Usage examples

“How do I define a basic two-step workflow using the Upstash SDK?”
The agent provides a code snippet using the serve() function and context.run() to define sequential steps that persist across execution.
“How can I trigger a workflow from my existing backend code?”
The agent demonstrates initializing the Workflow Client with a QStash token and using the trigger() method to initiate the workflow URL.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/upstash/upstash-workflow-js/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip upstash-workflow-js.zip -d .agents/skills

Documentation by Upstash

Upstash Workflow SDK

Bundled docs and source

Before writing or debugging SDK code, check node_modules/@upstash/workflow/docs/ for bundled docs and node_modules/@upstash/workflow/src/ for readable TypeScript source. Read and search the relevant files when present; otherwise use the references in this skill.

Quick Start

The Upstash Workflow SDK lets you expose serverless workflow endpoints and run them reliably using QStash under the hood.

Install:

npm install @upstash/workflow

Define a simple workflow endpoint:

import { serve } from "@upstash/workflow";

export const { POST } = serve(async (context) => {
  await context.run("step-1", () => console.log("step 1"));
  await context.run("step-2", () => console.log("step 2"));
});

Trigger it from your backend:

import { Client } from "@upstash/workflow";

const client = new Client({ token: process.env.QSTASH_TOKEN! });
await client.trigger({ url: "https://your-app.com/api/workflow" });

Other Skill Files

These files contain the full documentation. Use them for details, patterns, and advanced behavior.

  • basics:

    • basics/serve – How to expose workflow endpoints.

    • basics/context – Full API for workflow context (steps, waits, webhooks, events, invoke, etc.).

    • basics/client – Using the Workflow client to trigger, cancel, inspect, and notify runs.

  • features:

    • features/invoke – Cross‑workflow invocation.

    • features/reliability – Retries, failure callbacks, and DLQ.

    • features/flow-control – Rate limits, concurrency, and parallelism.

    • features/wait-for-event – Notify and wait-for-event patterns.

    • features/webhooks – Webhook creation and consumption.

  • how to:

    • how-to/local-dev – Local QStash dev server (auto via QSTASH_DEV=true) and tunneling.

    • how-to/realtime – Realtime and human‑in‑the‑loop workflows.

    • how-to/migrations – Migrating workflows safely.

    • how-to/middleware – Adding middleware to workflows.

  • other files:

    • rest-api – Low-level REST endpoints for interacting with QStash/Workflow.

    • troubleshooting – Common debugging and environment issues.

    • agents – Using Workflow with agents, orchestrators, and automation patterns.

Files

how-to/migrations.md

Migration Guide for Upstash Workflow (TypeScript)

This document provides a clear, task-focused overview of migrations between Workflow versions. It highlights breaking changes, how to update your code, and common pitfalls to avoid. Code samples combine multiple parameters in each example to reduce redundancy.

January 2026 – Major Release 1.0.0

Agents API → moved to a separate package

The Agents API was removed from the core workflow package and placed into @upstash/workflow-agents so the base SDK no longer depends on large AI-related libraries.

Key changes:

  • Must install and import agentWorkflow from the new package.

  • Agents access now happens through an agents helper created per workflow invocation.

// Before
import { serve } from "@upstash/workflow/nextjs";
export const { POST } = serve(async (context) => {
  const model = context.agents.openai("gpt-3.5-turbo");
  const agent = context.agents.agent({
    /* ... */
  });
  const task = context.agents.task({
    /* ... */
  });
});

// After
import { serve } from "@upstash/workflow/nextjs";
import { agentWorkflow } from "@upstash/workflow-agents";
export const { POST } = serve(async (context) => {
  const agents = agentWorkflow(context);
  const model = agents.openai("gpt-3.5-turbo");
  const agent = agents.agent({
    /* ... */
  });
  const task = agents.task({
    /* ... */
  });
});

keepTriggerConfig and useFailureFunction removed

These fields were redundant—both behaviors are now always enabled.

// Before
await client.trigger({
  url: "...",
  retries: 3,
  keepTriggerConfig: true,
  useFailureFunction: true,
});

// After
await client.trigger({ url: "...", retries: 3 });

Configuration moved from serve() → client.trigger()

Options such as retries, flowControl, retryDelay, and failureUrl no longer belong in serve().

// Before
export const { POST } = serve(
  async (context) => {
    /* ... */
  },
  {
    retries: 3,
    retryDelay: "1000 * (1 + retried)",
    flowControl: { key: "my-key", rate: 10 },
  }
);
await client.trigger({ url: "..." });

// After
export const { POST } = serve(async (context) => {
  /* ... */
});
await client.trigger({
  url: "...",
  retries: 3,
  retryDelay: "1000 * (1 + retried)",
  flowControl: { key: "my-key", rate: 10 },
});

stringifyBody removed from context.call and context.invoke

Bodies must now be strings.

// Before
await context.call("step", {
  url: "https://api.example.com",
  method: "POST",
  body: { key: "value" },
  stringifyBody: true,
});

// After
await context.call("step", {
  url: "https://api.example.com",
  method: "POST",
  body: JSON.stringify({ key: "value" }),
});

// Same change applies to invoke
await context.invoke("other", {
  workflow: otherWorkflow,
  body: JSON.stringify({ key: "value" }),
});

Logger removed → middleware system added

Removed WorkflowLogger class and added WorkflowMiddleware. Updated verbose param to only allow true (in this case, loggingMiddleware will be used which prints to console).

import { loggingMiddleware, WorkflowMiddleware } from "@upstash/workflow";

const stepFinish = new WorkflowMiddleware({
  name: "step-finish",
  callbacks: {
    afterExecution: async ({ stepName, result }) =>
      console.log(`Step ${stepName} finished`, result),
  },
});

export const { POST } = serve(
  async (context) => {
    /* ... */
  },
  {
    middlewares: [loggingMiddleware, stepFinish],
  }
);

October 2024 – Migration from @upstash/qstash

Install the new package

Replace all workflow usage from @upstash/qstash with @upstash/workflow.

Serve import and return shape changed

Most environments now require destructuring { POST }.

// Before
import { serve } from "@upstash/qstash/nextjs";
export const POST = serve(...);

// After
import { serve } from "@upstash/workflow/nextjs";
export const { POST } = serve(...);
context.call updated

Now returns { status, headers, body } and does not fail the workflow if the HTTP call fails.

const { status, headers, body } = await context.call("call-step", {
  url: "https://example.com/api",
  method: "POST",
});

Pitfall: Old runs may not contain status or headers until fully migrated.

Errors renamed
  • QStashWorkflowError → WorkflowError

  • QStashWorkflowAbort → WorkflowAbort


Summary of Common Mistakes

  • Using context.agents instead of the new agentWorkflow() helper.

  • Leaving old serve-config options (retries, flowControl, etc.).

  • Forgetting to JSON.stringify bodies.

  • Assuming context.call failures stop workflow execution.

  • Mix-and-matching @upstash/qstash and @upstash/workflow imports.

This guide ensures smooth migration with minimal friction while highlighting where behavioral changes may break existing workflows.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

Security

What our scanner noticed· Medium risk

  • Possible data-exfiltration endpoints

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Upstash
Publisher
Upstash (Official)
Source
upstash/skills · skills/upstash-workflow-js · commit 9f9e3e5
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Upstash or Upstash.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download upstash-workflow-js.zip