Agent Skillslobehub/lobehub › upstash-workflow

upstash-workflow

GitHub

Upstash Workflow与QStash异步工作流实现指南,涵盖三层架构及Dry-Run、Fan-Out、单任务执行模式,用于处理高并发、分页及限流场景。

.agents/skills/upstash-workflow/SKILL.md lobehub/lobehub

Trigger Scenarios

需要实现基于Upstash的异步后台任务 处理大批量数据并行处理或分页逻辑 设计具有幂等性和重试机制的工作流

Install

npx skills add lobehub/lobehub --skill upstash-workflow -g -y
More Options

Non-standard path

npx skills add https://github.com/lobehub/lobehub/tree/canary/.agents/skills/upstash-workflow -g -y

Use without installing

npx skills use lobehub/lobehub@upstash-workflow

指定 Agent (Claude Code)

npx skills add lobehub/lobehub --skill upstash-workflow -a claude-code -g -y

安装 repo 全部 skill

npx skills add lobehub/lobehub --all -g -y

预览 repo 内 skill

npx skills add lobehub/lobehub --list

SKILL.md

Frontmatter
{
    "name": "upstash-workflow",
    "description": "LobeHub Upstash Workflow and QStash guide. Use for async workflows, process\/paginate\/execute fan-out, serve handlers, context.run\/call\/sleep, or workflow triggers.",
    "user-invocable": false
}

Upstash Workflow Implementation Guide

Standard patterns for implementing Upstash Workflow + QStash async workflows in the LobeHub codebase.

🎯 The Three Core Patterns

Every workflow in LobeHub combines these three patterns. They exist because the platform constrains you in three ways: rate limits make blind fan-out dangerous, step limits cap a single workflow's size, and idempotency demands that retries don't double-process.

  1. 🔍 Dry-Run Mode — get statistics without triggering actual execution
  2. 🌟 Fan-Out Pattern — split large batches into smaller chunks for parallel processing
  3. 🎯 Single Task Execution — each workflow execution processes exactly ONE item

Architecture Overview

All workflows follow the same 3-layer architecture:

Layer 1: Entry Point (process-*)
  ├─ Validates prerequisites
  ├─ Calculates total items to process
  ├─ Filters existing items
  ├─ Supports dry-run mode (statistics only)
  └─ Triggers Layer 2 if work is needed

Layer 2: Pagination (paginate-*)
  ├─ Handles cursor-based pagination
  ├─ Implements fan-out for large batches
  ├─ Recursively processes all pages
  └─ Triggers Layer 3 for each item

Layer 3: Single Task Execution (execute-* / generate-*)
  └─ Performs actual business logic for ONE item

Real examples in this codebase: welcome-placeholder, agent-welcome — see references/examples.md.


The Three Patterns in 60 Seconds

1. Dry-Run Mode

Short-circuit Layer 1 before any side effects so callers can preview what would happen:

if (dryRun) {
  return {
    ...result,
    dryRun: true,
    message: `[DryRun] Would process ${itemsNeedingProcessing.length} items`,
  };
}

Use case: check how many items will be processed before committing.

2. Fan-Out Pattern

Layer 2 splits oversized batches into chunks and recursively re-triggers itself with each chunk. This avoids hitting workflow step limits when one page contains too many items:

const CHUNK_SIZE = 20;

if (itemIds.length > CHUNK_SIZE) {
  const chunks = chunk(itemIds, CHUNK_SIZE);
  await Promise.all(
    chunks.map((ids, idx) =>
      context.run(`workflow:fanout:${idx + 1}/${chunks.length}`, () =>
        WorkflowClass.triggerPaginateItems({ itemIds: ids }),
      ),
    ),
  );
}

Defaults: PAGE_SIZE = 50 (items per page), CHUNK_SIZE = 20 (items per fan-out chunk).

3. Single Task Execution

Layer 3 always processes exactly one item per invocation. Parallelism comes from Layer 2 fanning out to many Layer 3 invocations, controlled by flowControl:

export const { POST } = serve<ExecutePayload>(
  async (context) => {
    const { itemId } = context.requestPayload ?? {};
    if (!itemId) return { success: false, error: 'Missing itemId' };

    const item = await context.run('workflow:get-item', () => getItem(itemId));
    const result = await context.run('workflow:execute', () => processItem(item));
    await context.run('workflow:save', () => saveResult(itemId, result));

    return { success: true, itemId, result };
  },
  {
    flowControl: { key: 'workflow.execute', parallelism: 10, ratePerSecond: 5 },
  },
);

File Structure

src/
├── app/(backend)/api/workflows/
│   └── {workflow-name}/
│       ├── process-{entities}/route.ts      # Layer 1
│       ├── paginate-{entities}/route.ts     # Layer 2
│       └── execute-{entity}/route.ts        # Layer 3
│
└── server/workflows/
    └── {workflowName}/
        └── index.ts                          # Workflow class

Where to Go Next

Pick the reference that matches what you're doing:

You want to... Read
Write the Workflow class + 3 routes from scratch references/implementation.md
Tune flowControl, error handling, logging, testing references/best-practices.md
See two real workflows end-to-end references/examples.md
Deploy on lobehub-cloud (re-exports, cloud-only ops) references/cloud.md

Environment Variables

# Required for all workflows
APP_URL=https://your-app.com # Base URL for workflow endpoints
QSTASH_TOKEN=qstash_xxx      # QStash authentication token

# Optional (for custom QStash URL)
QSTASH_URL=https://custom-qstash.com

Checklist for New Workflows

Planning

  • Identify the entity to process (users, agents, items, …)
  • Define the per-item business logic
  • Determine filtering logic (Redis cache, database state, …)

Implementation

  • Define payload types with TypeScript interfaces
  • Create workflow class with static trigger methods
  • Layer 1: entry point with dry-run support
  • Layer 1: filtering logic to avoid duplicate work
  • Layer 2: pagination with fan-out
  • Layer 3: single-task execution (ONE item per run)
  • Configure appropriate flowControl for each layer
  • Consistent logging with workflow prefixes
  • Validate all required payload parameters
  • Unique context.run() step names

Quality & Deployment

  • Return consistent response shapes
  • Configure cloud deployment (references/cloud.md if on lobehub-cloud)
  • Write integration tests (dryRun path + full path)
  • Smoke-test with dry-run first
  • Test with a small batch before full rollout

Additional Resources

Version History

  • 29fe043 Current 2026-08-20 18:34

Same Skill Collection

.agents/skills/add-provider-doc/SKILL.md
.agents/skills/add-setting-env/SKILL.md
.agents/skills/agent-runtime-hooks/SKILL.md
.agents/skills/agent-signal/SKILL.md
.agents/skills/agent-testing-bot/SKILL.md
.agents/skills/agent-tracing/SKILL.md
.agents/skills/agent-work/SKILL.md
.agents/skills/builtin-tool/SKILL.md
.agents/skills/chat-sdk/SKILL.md
.agents/skills/cleanup-git-worktrees/SKILL.md
.agents/skills/cli/SKILL.md
.agents/skills/data-fetching-architecture/SKILL.md
.agents/skills/db-migrations/SKILL.md
.agents/skills/debug-package/SKILL.md
.agents/skills/deep-review/SKILL.md
.agents/skills/design-prototype/SKILL.md
.agents/skills/desktop/SKILL.md
.agents/skills/docs-changelog/SKILL.md
.agents/skills/drizzle/SKILL.md
.agents/skills/heterogeneous-agent/SKILL.md
.agents/skills/hotkey/SKILL.md
.agents/skills/i18n/SKILL.md
.agents/skills/linear/SKILL.md
.agents/skills/llm-generation/SKILL.md
.agents/skills/modal/SKILL.md
.agents/skills/model-bank-metadata/SKILL.md
.agents/skills/product-design/SKILL.md
.agents/skills/project-overview/SKILL.md
.agents/skills/react/SKILL.md
.agents/skills/response-compliance/SKILL.md
.agents/skills/skills-audit/SKILL.md
.agents/skills/spa-routes/SKILL.md
.agents/skills/split-micro-app/SKILL.md
.agents/skills/store-data-structures/SKILL.md
.agents/skills/testing/SKILL.md
.agents/skills/trpc-router/SKILL.md
.agents/skills/typescript/SKILL.md
.agents/skills/ux-audit/SKILL.md
.agents/skills/ux/SKILL.md
.agents/skills/version-release/SKILL.md
.agents/skills/zustand/SKILL.md
.agents/skills/agent-testing/SKILL.md
.agents/skills/compose-atoms/SKILL.md
.agents/skills/debug-frontend-with-browser/SKILL.md
.agents/skills/pr/SKILL.md
packages/builtin-skills/src/acceptance/SKILL.md

Metadata

Files
0
Version
a06b4e2
Hash
848bdad6
Indexed
2026-08-20 18:34

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-30 06:28
浙ICP备14020137号-1 $お客様$