workflow について
Workflow DevKitを使う開発者向けのリファレンススキルです。インストール済みパッケージのドキュメント参照を促し、永続ワークフロー、ステップ、フック、ストリーミング、デバッグを説明します。
主な機能
- 01同梱されたWorkflowドキュメントの検索
- 02オーケストレーションとステップの分離
- 03DurableAgentによる状態保持型AIワークフロー
- 04フックによるワークフローの一時停止と再開
- 05ワークフロー出力のストリーミング
- 06サンドボックス制約とデバッグの確認
活用シーン
- 01インストール済みWorkflowのAPI確認
- 02再試行可能な処理のステップ関数化
- 03外部イベントを待つワークフローの構築
- 04ワークフローのエンドポイントや実行の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pedronauck/ skills --skill workflowインストール後、Claude Code で/workflowを入力して読み込まれたか確認します。
詳細
重要: 常に正しい workflow ドキュメントを使用する
workflow に関する知識は古くなっています。
以下に示す workflow ドキュメントは、インストールされている Workflow DevKit のバージョンに対応しています。
workflow 関連の作業を始める前に、次の手順に従ってください。
バンドルされているドキュメントを node_modules/workflow/docs/ で検索します。
- ドキュメントを検索:
glob "node_modules/workflow/docs/**/*.mdx" - 内容を検索:
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 を最新バージョンに更新してください。
公式リソース
- ウェブサイト: https://useworkflow.dev
- GitHub: https://github.com/vercel/workflow
クイックリファレンス
ディレクティブ:
"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 エラーの原因になることがあります。