はじめに
非同期処理って、書くのは簡単だけど運用が地味に面倒なんですよね。
「途中で処理が落ちたらどうする?」「リトライロジックを自前で書くのか?」「ログはどこで取る?」
こういう課題に対して、Vercelが面白いソリューションを出してきました。Workflow DevKit(通称Workflow)というTypeScriptベースの開発キットです。
個人的には「これ、もっと早く欲しかった」という感想ですね。
Workflowとは
Workflowは、Vercelが開発したTypeScriptベースの開発キットです。非同期JavaScriptアプリケーションとAIエージェントに耐久性、信頼性、可観測性を付与するために設計されています。
一言でいうと、「TypeScript関数を永続的にするツール」という話。
export async function userSignup(email) {
"use workflow";
// この中の処理が永続化される
}
この"use workflow"ディレクティブを追加するだけで、関数が永続的で再開可能になるんですよ。正直なところ、これはかなり画期的だと思います。
特徴・メリット
1. 永続化と再開が簡単
従来、長時間実行される処理やステートフルなワークフローを実装するには、キューシステムやステート管理を自前で構築する必要がありました。Workflowを使えば、ディレクティブ一つでその辺りを解決できます。
2. ゼロコンフィグ
YAMLファイルをゴリゴリ書いたり、複雑な設定をしなくていいのがありがたいですね。コードに集中できます。
3. 可観測性が標準装備
ステップごとの実行状況をエンドツーエンドで検査可能。トレース、ログ、メトリクスが自動的にキャプチャされます。これ、意外と重要で。運用フェーズになってから「ログ取っておけばよかった」ってなることありますからね。
4. 幅広いフレームワーク対応
- Next.js
- Nuxt
- SvelteKit
- Astro
- Vite
- Express
- Fastify
- Hono
- Nitro
主要なフレームワークはほぼ網羅されています。既存プロジェクトへの導入もスムーズにできそうです。
5. ポータビリティ
ローカル、Docker、Vercel、他のクラウドで同じコードが動作します。ベンダーロックインを気にしなくていいのは精神衛生上いいですね。
インストール方法
インストールはシンプルです。
npm i workflow
これだけ。あとはプロジェクトに組み込んでいくだけです。
基本的な使い方
ワークフローの定義
"use workflow"ディレクティブを使って、永続化したい関数を定義します。
export async function userSignup(email: string) {
"use workflow";
const user = await createUser(email);
await sendWelcomeEmail(email);
// 7日間待機(この間も状態は保持される)
await sleep("7 days");
await sendOneWeekCheckInEmail(email);
return { userId: user.id, status: "done" };
}
この例だと、ユーザー登録後にウェルカムメールを送って、7日後にフォローアップメールを送るという流れ。途中でサーバーが再起動しても、状態は保持されて処理が継続されます。
ステップの定義
個別のステップを定義することもできます。
export async function sendWelcomeEmail(email: string) {
"use step";
// メール送信ロジック
await emailService.send({
to: email,
template: "welcome",
});
}
"use step"を使うことで、そのステップが完了したかどうかを追跡できるようになります。リトライ時に同じ処理が重複実行されるのを防げるわけです。
sleepの活用
await sleep("7 days");
await sleep("1 hour");
await sleep("30 minutes");
普通のsetTimeoutと違って、このsleepは永続化されます。アプリケーションがクラッシュしても、指定した時間が経過したら処理が再開されるという仕組み。
実践的なユースケース
1. オンボーディングフロー
export async function onboardingFlow(userId: string) {
"use workflow";
// 即座にウェルカムメール
await sendWelcomeEmail(userId);
// 3日後にTips紹介
await sleep("3 days");
await sendTipsEmail(userId);
// 7日後に活用状況確認
await sleep("4 days");
const usage = await checkUserUsage(userId);
if (usage.isActive) {
await sendPowerUserTips(userId);
} else {
await sendReEngagementEmail(userId);
}
}
マーケティングオートメーション的なことが、シンプルなコードで実現できます。
2. AIエージェントの状態管理
長時間実行されるAIエージェントの状態を保持するのにも使えます。これ、最近のAIエージェント開発では結構重要なポイントなんですよね。
export async function aiAgentTask(taskId: string) {
"use workflow";
const context = await initializeAgent(taskId);
while (!context.isComplete) {
const result = await processNextStep(context);
context.update(result);
// 長時間処理の途中でも状態が保持される
}
return context.finalResult;
}
3. CI/CDパイプライン
デプロイメントフローなど、複数のステップを順序立てて実行する必要がある場面でも活躍します。
まとめ
Workflowは、非同期処理の永続化という地味だけど重要な課題を、エレガントに解決してくれるツールです。
個人的に特に良いと思うポイントは:
- 学習コストが低い: ディレクティブを追加するだけ
- 既存コードへの影響が小さい: 関数単位で導入できる
- 運用が楽: 可観測性が標準で組み込まれている
現在ベータ版ですが、Vercelが開発しているということで今後の発展にも期待できます。長時間実行される処理や、複雑なワークフローを扱っているプロジェクトがあれば、試してみる価値はあると思いますね。
公式サイト: useworkflow.dev GitHub: vercel/workflow