mcpField
W
workflow

workflow

github.com/pedronauck開発647218 回インストール1 週間前に更新
リポジトリ

workflow について

Workflow DevKitを使う開発者向けのリファレンススキルです。インストール済みパッケージのドキュメント参照を促し、永続ワークフロー、ステップ、フック、ストリーミング、デバッグを説明します。

主な機能

  1. 01同梱されたWorkflowドキュメントの検索
  2. 02オーケストレーションとステップの分離
  3. 03DurableAgentによる状態保持型AIワークフロー
  4. 04フックによるワークフローの一時停止と再開
  5. 05ワークフロー出力のストリーミング
  6. 06サンドボックス制約とデバッグの確認

活用シーン

  1. 01インストール済みWorkflowのAPI確認
  2. 02再試行可能な処理のステップ関数化
  3. 03外部イベントを待つワークフローの構築
  4. 04ワークフローのエンドポイントや実行の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pedronauck/skills --skill workflow

インストール後、Claude Code で/workflowを入力して読み込まれたか確認します。

詳細

重要: 常に正しい workflow ドキュメントを使用する

workflow に関する知識は古くなっています。

以下に示す workflow ドキュメントは、インストールされている Workflow DevKit のバージョンに対応しています。 workflow 関連の作業を始める前に、次の手順に従ってください。

バンドルされているドキュメントを node_modules/workflow/docs/ で検索します。

  1. ドキュメントを検索: glob "node_modules/workflow/docs/**/*.mdx"
  2. 内容を検索: grep "your query" node_modules/workflow/docs/

node_modules/workflow/docs/ のドキュメント構成:

  • getting-started/ - フレームワークのセットアップ(next.mdx、express.mdx、hono.mdx など)
  • foundations/ - コア概念(workflows-and-steps.mdx、hooks.mdx、streaming.mdx など)
  • api-reference/workflow/ - API ドキュメント(sleep.mdx、create-hook.mdx、fatal-error.mdx など)
  • api-reference/workflow-api/ - クライアント API(start.mdx、get-run.mdx、resume-hook.mdx など)
  • ai/ - AI SDK の統合ドキュメント
  • errors/ - エラーコードのドキュメント

関連パッケージにも、バンドルされたドキュメントが含まれています。

  • @workflow/ai: node_modules/@workflow/ai/docs/ - DurableAgent と AI の統合
  • @workflow/core: node_modules/@workflow/core/docs/ - コアランタイム(foundations、how-it-works)
  • @workflow/next: node_modules/@workflow/next/docs/ - Next.js の統合

迷った場合は、Workflow DevKit を最新バージョンに更新してください。

公式リソース
クイックリファレンス

ディレクティブ:

"use workflow"; // First line - makes async function durable
"use step"; // First line - makes function a cached, retryable unit

必須のインポート:

// Workflow primitives
import { sleep, fetch, createHook, createWebhook, getWritable } from "workflow";
import { FatalError, RetryableError } from "workflow";
import { getWorkflowMetadata, getStepMetadata } from "workflow";

// API operations
import { start, getRun, resumeHook, resumeWebhook } from "workflow/api";

// Framework integrations
import { withWorkflow } from "workflow/next";
import { workflow } from "workflow/vite";
import { workflow } from "workflow/astro";
// Or use modules: ["workflow/nitro"] for Nitro/Nuxt

// AI agent
import { DurableAgent } from "@workflow/ai/agent";

サンドボックスエラーを避けるため、ステップ関数を優先する

"use workflow" 関数はサンドボックス化された VM で実行されます。"use step" 関数では Node.js の全機能を利用できます。ロジックはステップに記述し、ワークフロー関数はオーケストレーションのみに使用してください。

// Steps have full Node.js and npm access
async function fetchUserData(userId: string) {
  "use step";
  const response = await fetch(`https://api.example.com/users/${userId}`);
  return response.json();
}

async function processWithAI(data: any) {
  "use step";
  // AI SDK works in steps without workarounds
  return await generateText({
    model: openai("gpt-4"),
    prompt: `Process: ${JSON.stringify(data)}`,
  });
}

// Workflow orchestrates steps - no sandbox issues
export async function dataProcessingWorkflow(userId: string) {
  "use workflow";
  const data = await fetchUserData(userId);
  const processed = await processWithAI(data);
  return { success: true, processed };
}

メリット: ステップには自動リトライがあり、再生用に結果が永続化され、サンドボックスによる制限もありません。

ワークフローのサンドボックスに関する制限

ワークフロー関数内で直接ロジックを実行する必要がある場合(ステップ内ではない場合)は、次の制限が適用されます。

制限回避策
fetch() を使用できないimport { fetch } from "workflow" を実行し、globalThis.fetch = fetch を設定する
setTimeout/setInterval を使用できない"workflow" の sleep("5s") を使用する
Node.js モジュール(fs、crypto など)を使用できないステップ関数に移す

例 - ワークフローコンテキストでの fetch の使用:

import { fetch } from "workflow";

export async function myWorkflow() {
  "use workflow";
  globalThis.fetch = fetch; // Required for AI SDK and HTTP libraries
  // Now generateText() and other libraries work
}

注: @workflow/ai の DurableAgent は、fetch の割り当てを自動的に処理します。

DurableAgent — ワークフロー内の AI エージェント

DurableAgent を使用すると、状態を保持し、中断後も動作を継続する AI エージェントを構築できます。ワークフローのサンドボックスを自動的に処理するため、globalThis.fetch を手動で設定する必要はありません。

import { DurableAgent } from "@workflow/ai/agent";
import { getWritable } from "workflow";
import { z } from "zod";
import type { UIMessageChunk } from "ai";

async function lookupData({ query }: { query: string }) {
  "use step";
  // Step functions have full Node.js access
  return `Results for "${query}"`;
}

export async function myAgentWorkflow(userMessage: string) {
  "use workflow";

  const agent = new DurableAgent({
    model: "anthropic/claude-sonnet-4-5",
    system: "You are a helpful assistant.",
    tools: {
      lookupData: {
        description: "Search for information",
        inputSchema: z.object({ query: z.string() }),
        execute: lookupData,
      },
    },
  });

  const result = await agent.stream({
    messages: [{ role: "user", content: userMessage }],
    writable: getWritable<UIMessageChunk>(),
    maxSteps: 10,
  });

  return result.messages;
}

要点:

  • getWritable<UIMessageChunk>() は、出力をワークフロー実行のデフォルトストリームに送信します
  • Node.js/npm へのアクセスが必要なツールの execute 関数では、"use step" を使用してください
  • ワークフローのプリミティブ(sleep()、createHook())を使用するツールの execute 関数では、"use step" を 使用しないでください — ワークフローレベルで実行されます
  • maxSteps は LLM 呼び出しの回数を制限します(デフォルトでは無制限です)
  • マルチターン: 以降の agent.stream() 呼び出しには、result.messages と新しいユーザーメッセージを渡します

DurableAgent の詳細については、node_modules/@workflow/ai/docs/ の AI ドキュメントを確認してください。

ワークフローと子ワークフローの開始

API ルートからワークフローを起動するには start() を使用します。start() はワークフローコンテキスト内から直接呼び出せません — ステップ関数でラップしてください。

import { start } from "workflow/api";

// From an API route — works directly
export async function POST() {
  const run = await start(myWorkflow, [arg1, arg2]);
  return Response.json({ runId: run.runId });
}

// No-args workflow
const run = await start(noArgWorkflow);

ワークフロー内から子ワークフローを開始する場合 — ステップを使用する必要があります:

import { start } from "workflow/api";

// Wrap start() in a step function
async function triggerChild(data: string) {
  "use step";
  const run = await start(childWorkflow, [data]);
  return run.runId;
}

export async function parentWorkflow() {
  "use workflow";
  const childRunId = await triggerChild("some data"); // Fire-and-forget via step
  await sleep("1h");
}

start() はすぐに返されます — ワークフローの完了を待つことはありません。完了を待つには run.returnValue を使用してください。

フック — 外部イベントによる一時停止と再開

フックを使用すると、ワークフローは外部データを待機できます。ワークフロー内で createHook() を使用し、API ルートから resumeHook() を呼び出します。

単一イベント
import { createHook } from "workflow";

export async function approvalWorkflow() {
  "use workflow";

  const hook = createHook<{ approved: boolean }>({
    token: "approval-123", // deterministic token for external systems
  });

  const result = await hook; // Workflow suspends here
  return result.approved;
}
複数イベント(イテラブルフック)

フックは AsyncIterable を実装しています。for await...of を使用して複数のイベントを受信できます。

import { createHook } from "workflow";

export async function chatWorkflow(channelId: string) {
  "use workflow";

  const hook = createHook<{ text: string; done?: boolean }>({
    token: `chat-${channelId}`,
  });

  for await (const event of hook) {
    await processMessage(event.text);
    if (event.done) break;
  }
}

各 resumeHook(token, payload) 呼び出しは、次の値をループに配信します。

API ルートからの再開
import { resumeHook } from "workflow/api";

export async function POST(req: Request) {
  const { token, data } = await req.json();
  await resumeHook(token, data);
  return new Response("ok");
}

エラーハンドリング

永続的な失敗(リトライなし)には FatalError を、一時的な失敗には RetryableError を使用します。

import { FatalError, RetryableError } from "workflow";

if (res.status >= 400 && res.status < 500) {
  throw new FatalError(`Client error: ${res.status}`);
}
if (res.status === 429) {
  throw new RetryableError("Rate limited", { retryAfter: "5m" });
}

シリアライゼーション

ワークフローおよびステップとの間で受け渡されるすべてのデータは、シリアライズ可能でなければなりません。

サポートされる型: string、number、boolean、null、undefined、bigint、プレーンオブジェクト、配列、Date、RegExp、URL、URLSearchParams、Map、Set、Headers、ArrayBuffer、型付き配列、Request、Response、ReadableStream、WritableStream。

サポートされない型: 関数、クラスインスタンス、Symbol、WeakMap/WeakSet。コールバックではなくデータを渡してください。

ストリーミング

getWritable() を使用してワークフローからデータをストリーミングします。getWritable() はワークフローとステップの両方のコンテキストで呼び出せますが、ワークフロー関数内でストリームを直接操作する(getWriter()、write()、close() を呼び出す)ことはできません。実際の I/O にはストリームをステップ関数に渡す必要があります。または、ステップ自体が getWritable() を呼び出すこともできます。

ワークフローでストリームを取得し、ステップに渡す:

import { getWritable } from "workflow";

export async function myWorkflow() {
  "use workflow";
  const writable = getWritable();
  await writeData(writable, "hello world");
}

async function writeData(writable: WritableStream, chunk: string) {
  "use step";
  const writer = writable.getWriter();
  try {
    await writer.write(chunk);
  } finally {
    writer.releaseLock();
  }
}

ステップ内で直接 getWritable() を呼び出す(渡す必要はありません):

import { getWritable } from "workflow";

async function streamData(chunk: string) {
  "use step";
  const writer = getWritable().getWriter();
  try {
    await writer.write(chunk);
  } finally {
    writer.releaseLock();
  }
}

デバッグ

# Check workflow endpoints are reachable
npx workflow health
npx workflow health --port 3001  # Non-default port

# Visual dashboard for runs
npx workflow web
npx workflow web <run_id>

# CLI inspection (use --json for machine-readable output, --help for full usage)
npx workflow inspect runs
npx workflow inspect run <run_id>

# For Vercel-deployed projects, specify backend and project
npx workflow inspect runs --backend vercel --project <project-name> --team <team-slug>
npx workflow inspect run <run_id> --backend vercel --project <project-name> --team <team-slug>

# Open Vercel dashboard in browser for a specific run
npx workflow inspect run <run_id> --web
npx workflow web <run_id> --backend vercel --project <project-name> --team <team-slug>

# Cancel a running workflow
npx workflow cancel <run_id>
npx workflow cancel <run_id> --backend vercel --project <project-name> --team <team-slug>
# --env defaults to "production"; use --env preview for preview deployments

デバッグのヒント:

  • 機械可読な出力を得るには、任意のコマンドで --json(-j)を使用します
  • ブラウザで Vercel Observability ダッシュボードを開くには --web を使用します
  • 完全な使用法の詳細については、任意のコマンドで --help を使用します
  • 実際に使用するワークフロー API のみをインポートしてください。未使用のインポートは 500 エラーの原因になることがあります。

コメント