workflow-automation
ワークフロー自動化は、AIエージェントを安定稼働させるための基盤インフラです。耐久性のある実行環境がなければ、10ステップの決済フロー中にネットワーク障害が発生した際、損失や顧客クレームに直結しますが、この仕組みがあれば中断した箇所から正確に処理を再開できます。
description の原文を見る
Workflow automation is the infrastructure that makes AI agents reliable. Without durable execution, a network hiccup during a 10-step payment flow means lost money and angry customers. With it, workflows resume exactly where they left off.
SKILL.md 本文
ワークフロー自動化
ワークフロー自動化は、AI エージェントを信頼性の高いものにするインフラストラクチャです。耐久的実行がなければ、10ステップの支払いフロー中のネットワーク障害は資金喪失と顧客満足度低下を意味します。耐久的実行があれば、ワークフローは中断したところから正確に再開できます。
このスキルは、脆弱なスクリプトを本番グレードの自動化に変えるプラットフォーム(n8n、Temporal、Inngest)とパターン(順序実行、並列実行、オーケストレーター・ワーカー)をカバーしています。
重要な洞察:プラットフォームは異なるトレードオフを行います。n8n はアクセシビリティに最適化され、Temporal は正確性に、Inngest は開発者体験に最適化されています。ハイプではなく、実際のニーズに基づいて選択してください。
原則
- 耐久的実行は金銭または状態が重要なワークフローでは必須です
- イベントはワークフロー トリガーの普遍的な言語です
- ステップはチェックポイント - 各ステップは独立して再試行可能である必要があります
- シンプルな状態から始めて、信頼性が必要な場合にのみ複雑さを追加します
- 監視可能性はオプションではありません - ワークフローがどこで失敗するかを確認する必要があります
- ワークフローとエージェントは共進化します - 両方に対して設計してください
機能
- workflow-automation
- workflow-orchestration
- durable-execution
- event-driven-workflows
- step-functions
- job-queues
- background-jobs
- scheduled-tasks
スコープ
- multi-agent-coordination → multi-agent-orchestration
- ci-cd-pipelines → devops
- data-pipelines → data-engineer
- api-design → api-designer
ツーリング
プラットフォーム
- n8n - 使用時機:ローコード自動化、迅速なプロトタイピング、非技術系ユーザー 注記:自己ホスト可能、400以上の統合、ビジュアルワークフローに最適
- Temporal - 使用時機:ミッションクリティカルなワークフロー、金融取引、マイクロサービス 注記:最強の耐久性保証、急な学習曲線
- Inngest - 使用時機:イベント駆動型サーバーレス、TypeScript コードベース、AI ワークフロー 注記:最高の開発者体験、あらゆるホスティングで動作
- AWS Step Functions - 使用時機:AWS ネイティブスタック、既存の Lambda 関数 注記:タイトな AWS 統合、JSON ベースのワークフロー定義
- Azure Durable Functions - 使用時機:Azure スタック、.NET または TypeScript 注記:AI エージェント対応、チェックポイントと再生
パターン
順序実行パターン
ステップは順序で実行され、各出力は次の入力になります
使用時機:コンテンツパイプライン、データ処理、順序付き操作
ステップ 1 → ステップ 2 → ステップ 3 → 出力
↓ ↓ ↓
(各ステップでチェックポイント)
Inngest の例(TypeScript)
import { inngest } from "./client";
export const processOrder = inngest.createFunction(
{ id: "process-order" },
{ event: "order/created" },
async ({ event, step }) => {
// ステップ 1: 注文を検証
const validated = await step.run("validate-order", async () => {
return validateOrder(event.data.order);
});
// ステップ 2: 支払いを処理(耐久的 - クラッシュから復帰)
const payment = await step.run("process-payment", async () => {
return chargeCard(validated.paymentMethod, validated.total);
});
// ステップ 3: 配送を作成
const shipment = await step.run("create-shipment", async () => {
return createShipment(validated.items, validated.address);
});
// ステップ 4: 確認メールを送信
await step.run("send-confirmation", async () => {
return sendEmail(validated.email, { payment, shipment });
});
return { success: true, orderId: event.data.orderId };
}
);
Temporal の例(TypeScript)
import { proxyActivities } from '@temporalio/workflow';
import type * as activities from './activities';
const { validateOrder, chargeCard, createShipment, sendEmail } =
proxyActivities<typeof activities>({
startToCloseTimeout: '30 seconds',
retry: {
maximumAttempts: 3,
backoffCoefficient: 2,
}
});
export async function processOrderWorkflow(order: Order): Promise<void> {
const validated = await validateOrder(order);
const payment = await chargeCard(validated.paymentMethod, validated.total);
const shipment = await createShipment(validated.items, validated.address);
await sendEmail(validated.email, { payment, shipment });
}
n8n パターン
[Webhook: order.created]
↓
[HTTP リクエスト: 注文を検証]
↓
[HTTP リクエスト: 支払いを処理]
↓
[HTTP リクエスト: 配送を作成]
↓
[メール送信: 確認]
各ノードをフェイル時の再試行で設定します。
エラーハンドリングには Error Trigger を使用します。
並列実行パターン
独立したステップが同時に実行され、結果を集約
使用時機:複数の独立した分析、複数のソースからのデータ
┌→ ステップ A ─┐
入力 ──┼→ ステップ B ─┼→ 集約 → 出力
└→ ステップ C ─┘
Inngest の例
export const analyzeDocument = inngest.createFunction(
{ id: "analyze-document" },
{ event: "document/uploaded" },
async ({ event, step }) => {
// 分析を並列実行
const [security, performance, compliance] = await Promise.all([
step.run("security-analysis", () =>
analyzeForSecurityIssues(event.data.document)
),
step.run("performance-analysis", () =>
analyzeForPerformance(event.data.document)
),
step.run("compliance-analysis", () =>
analyzeForCompliance(event.data.document)
),
]);
// 結果を集約
const report = await step.run("generate-report", () =>
generateReport({ security, performance, compliance })
);
return report;
}
);
AWS Step Functions(Amazon States Language)
{
"Type": "Parallel",
"Branches": [
{
"StartAt": "SecurityAnalysis",
"States": {
"SecurityAnalysis": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:security-analyzer",
"End": true
}
}
},
{
"StartAt": "PerformanceAnalysis",
"States": {
"PerformanceAnalysis": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:performance-analyzer",
"End": true
}
}
}
],
"Next": "AggregateResults"
}
オーケストレーター・ワーカーパターン
中央コーディネーターが専門化されたワーカーに作業をディスパッチ
使用時機:異なる専門知識が必要な複雑なタスク、動的サブタスク作成
┌─────────────────────────────────────┐
│ オーケストレーター │
│ - タスクを分析 │
│ - サブタスクを作成 │
│ - ワーカーにディスパッチ │
│ - 結果を集約 │
└─────────────────────────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│ワーカー1│ │ワーカー2│ │ワーカー3│
│作成 │ │修正 │ │削除 │
└───────┘ └───────┘ └───────┘
Temporal の例
export async function orchestratorWorkflow(task: ComplexTask) {
// オーケストレーターが実行する必要のある作業を決定
const plan = await analyzeTask(task);
// 専門化されたワーカーワークフローにディスパッチ
const results = await Promise.all(
plan.subtasks.map(subtask => {
switch (subtask.type) {
case 'create':
return executeChild(createWorkerWorkflow, { args: [subtask] });
case 'modify':
return executeChild(modifyWorkerWorkflow, { args: [subtask] });
case 'delete':
return executeChild(deleteWorkerWorkflow, { args: [subtask] });
}
})
);
// 結果を集約
return aggregateResults(results);
}
AI オーケストレーション付き Inngest
export const aiOrchestrator = inngest.createFunction(
{ id: "ai-orchestrator" },
{ event: "task/complex" },
async ({ event, step }) => {
// AI が何をする必要があるかを決定
const plan = await step.run("create-plan", async () => {
return await llm.chat({
messages: [
{ role: "system", content: "このタスクをサブタスクに分割..." },
{ role: "user", content: event.data.task }
]
});
});
// 各サブタスクを耐久的ステップとして実行
const results = [];
for (const subtask of plan.subtasks) {
const result = await step.run(`execute-${subtask.id}`, async () => {
return executeSubtask(subtask);
});
results.push(result);
}
// 最終的な統合
return await step.run("synthesize", async () => {
return synthesizeResults(results);
});
}
);
イベント駆動型トリガーパターン
スケジュールではなくイベントで駆動されるワークフロー
使用時機:リアクティブシステム、ユーザーアクション、Webhook 統合
イベント駆動型トリガー
Inngest イベントベース
// TypeScript 型を使用してイベントを定義
type Events = {
"user/signed.up": {
data: { userId: string; email: string };
};
"order/completed": {
data: { orderId: string; total: number };
};
};
// このイベントで駆動される関数
export const onboardUser = inngest.createFunction(
{ id: "onboard-user" },
{ event: "user/signed.up" }, // このイベントで駆動
async ({ event, step }) => {
// 1 時間待機してからウェルカムメールを送信
await step.sleep("wait-for-exploration", "1 hour");
await step.run("send-welcome", async () => {
return sendWelcomeEmail(event.data.email);
});
// 3 日間待機してエンゲージメントを確認
await step.sleep("wait-for-engagement", "3 days");
const engaged = await step.run("check-engagement", async () => {
return checkUserEngagement(event.data.userId);
});
if (!engaged) {
await step.run("send-nudge", async () => {
return sendNudgeEmail(event.data.email);
});
}
}
);
// どこからでもイベントを送信
await inngest.send({
name: "user/signed.up",
data: { userId: "123", email: "user@example.com" }
});
n8n Webhook トリガー
[Webhook: POST /api/webhooks/order]
↓
[スイッチ: event.type]
↓ order.created
[新規注文処理サブワークフロー]
↓ order.cancelled
[キャンセル処理サブワークフロー]
再試行と復帰パターン
バックオフ付き自動再試行、デッドレター処理
使用時機:外部依存を持つあらゆるワークフロー
再試行と復帰
Temporal 再試行設定
const activities = proxyActivities<typeof activitiesType>({
startToCloseTimeout: '30 seconds',
retry: {
initialInterval: '1 second',
backoffCoefficient: 2,
maximumInterval: '1 minute',
maximumAttempts: 5,
nonRetryableErrorTypes: [
'ValidationError', // 検証失敗は再試行しない
'InsufficientFunds', // 支払い失敗は再試行しない
]
}
});
Inngest 再試行設定
export const processPayment = inngest.createFunction(
{
id: "process-payment",
retries: 5, // 最大 5 回再試行
},
{ event: "payment/initiated" },
async ({ event, step, attempt }) => {
// attempt は 0 インデックスの再試行カウント
const result = await step.run("charge-card", async () => {
try {
return await stripe.charges.create({...});
} catch (error) {
if (error.code === 'card_declined') {
// カード拒否は再試行しない
throw new NonRetriableError("Card declined");
}
throw error; // その他のエラーは再試行
}
});
return result;
}
);
デッドレターハンドリング
// n8n: Error Trigger ノードを使用
[Error Trigger]
↓
[エラーデータベースにログ]
↓
[Slack にアラートを送信]
↓
[Jira でチケットを作成]
// Inngest: onFailure でハンドル
export const myFunction = inngest.createFunction(
{
id: "my-function",
onFailure: async ({ error, event, step }) => {
await step.run("alert-team", async () => {
await slack.postMessage({
channel: "#errors",
text: `Function failed: ${error.message}`
});
});
}
},
{ event: "..." },
async ({ step }) => { ... }
);
スケジュール実行パターン
定期的なタスク用の時間ベースのトリガー
使用時機:日報、定期同期、バッチ処理
スケジュール実行
Inngest Cron
export const dailyReport = inngest.createFunction(
{ id: "daily-report" },
{ cron: "0 9 * * *" }, // 毎日午前 9 時
async ({ step }) => {
const data = await step.run("gather-metrics", async () => {
return gatherDailyMetrics();
});
await step.run("generate-report", async () => {
return generateAndSendReport(data);
});
}
);
export const syncInventory = inngest.createFunction(
{ id: "sync-inventory" },
{ cron: "*/15 * * * *" }, // 15 分ごと
async ({ step }) => {
await step.run("sync", async () => {
return syncWithSupplier();
});
}
);
Temporal Cron ワークフロー
// ワークフローを Cron スケジュールで実行
const handle = await client.workflow.start(dailyReportWorkflow, {
taskQueue: 'reports',
workflowId: 'daily-report',
cronSchedule: '0 9 * * *', // 毎日午前 9 時
});
n8n スケジュール トリガー
[スケジュール トリガー: 毎日午前 9:00]
↓
[HTTP リクエスト: メトリクスを取得]
↓
[コード ノード: レポートを生成]
↓
[メール送信: レポート]
鋭い落とし穴
耐久性ワークフロー内の冪等性がないステップ
重大度:CRITICAL
状況:外部状態を修正するワークフローステップを記述
症状: 顧客が 2 回請求される。メールが 3 回送信される。データベースレコードが複数回作成される。ワークフロー再試行は副作用の重複を引き起こします。
これが失敗する理由: 耐久的実行は再開時にワークフローを最初から再生します。ステップ 3 がクラッシュしてワークフローが再開すると、ステップ 1 と 2 が再び実行されます。冪等性キーがないと、外部サービスはこれらが再試行であることを知りません。
推奨修正:
常に外部呼び出しに冪等性キーを使用します:
### Stripe の例:
await stripe.paymentIntents.create({
amount: 1000,
currency: 'usd',
idempotency_key: `order-${orderId}-payment` # 重要!
});
### メールの例:
await step.run("send-confirmation", async () => {
const alreadySent = await checkEmailSent(orderId);
if (alreadySent) return { skipped: true };
return sendEmail(customer, orderId);
});
### データベースの例:
await db.query(`
INSERT INTO orders (id, ...) VALUES ($1, ...)
ON CONFLICT (id) DO NOTHING
`, [orderId]);
冪等性キーを安定した入力から生成し、ランダム値から生成しないでください
数時間/数日間チェックポイントなしで実行するワークフロー
重大度:HIGH
状況:チェックポイント間隔が長い長時間実行ワークフロー
症状: メモリ消費が増加します。ワーカーがタイムアウトします。クラッシュ後に進捗が失われます。「ワークフローが最大期間を超過」エラーが発生します。
これが失敗する理由: ワークフローはチェックポイントまでメモリに状態を保持します。24 時間実行され、1 時間ごとに 1 ステップ実行するワークフローは、24 時間分の状態を蓄積します。ワーカーはメモリ制限があります。関数は実行時間制限があります。
推奨修正:
チェックポイント付きステップに長時間ワークフローを分割します:
### 間違い - 1 つの長いステップ:
await step.run("process-all", async () => {
for (const item of thousandItems) {
await processItem(item); // 数時間の作業、1 つのチェックポイント
}
});
### 正しい - 多くの小さいステップ:
for (const item of thousandItems) {
await step.run(`process-${item.id}`, async () => {
return processItem(item); // 各ステップ後にチェックポイント
});
}
非常に長い待機には sleep を使用します:
await step.sleep("wait-for-trial", "14 days");
// 待機中はリソースを消費しません
長いプロセスには子ワークフローを検討します:
await step.invoke("process-batch", {
function: batchProcessor,
data: { items: batch }
});
タイムアウト設定がないアクティビティ
重大度:HIGH
状況:ワークフローアクティビティから外部サービスを呼び出す
症状: ワークフローが無期限にハングします。ワーカープールが枯渇します。完了しない、または失敗しないデッドワークフロー。スタックされたワークフローを強制終了するために手動介入が必要です。
これが失敗する理由: 外部 API は無期限にハングする可能性があります。タイムアウトなしで、ワークフローは無期限に待機します。HTTP クライアントとは異なり、ワークフローアクティビティにはほとんどのプラットフォームでデフォルトのタイムアウトがありません。
推奨修正:
常にアクティビティにタイムアウトを設定します:
### Temporal:
const activities = proxyActivities<typeof activitiesType>({
startToCloseTimeout: '30 seconds', # 必須!
scheduleToCloseTimeout: '5 minutes',
heartbeatTimeout: '10 seconds', # 長いアクティビティ用
retry: {
maximumAttempts: 3,
initialInterval: '1 second',
}
});
### Inngest:
await step.run("call-api", { timeout: "30s" }, async () => {
return fetch(url, { signal: AbortSignal.timeout(25000) });
});
## AWS Step Functions:
{
"Type": "Task",
"TimeoutSeconds": 30,
"HeartbeatSeconds": 10,
"Resource": "arn:aws:lambda:..."
}
ルール:アクティビティタイムアウト < ワークフロータイムアウト
ステップ/アクティビティ境界外の副作用
重大度:CRITICAL
状況:ワークフロー再生中に実行されるコードを記述
症状: 再生時のランダムな失敗。「ワークフロー破損」エラー。再生時に最初の実行と異なる動作。非決定論的エラー。
これが失敗する理由: ワークフローコードはすべての再生で実行されます。ワークフローコードでランダム ID を生成すると、再生のたびに異なる ID を取得します。現在の時刻を読むと、異なる時刻を取得します。これは決定論を破ります。
推奨修正:
### 間違い - ワークフローコード内の副作用:
export async function orderWorkflow(order) {
const orderId = uuid(); // 再生のたびに異なる!
const now = new Date(); // 再生のたびに異なる!
await activities.process(orderId, now);
}
### 正しい - アクティビティ内の副作用:
export async function orderWorkflow(order) {
const orderId = await activities.generateOrderId(); # 記録される
const now = await activities.getCurrentTime(); # 記録される
await activities.process(orderId, now);
}
### また正しい - Temporal workflow.now() と sideEffect:
import { sideEffect } from '@temporalio/workflow';
const orderId = await sideEffect(() => uuid());
const now = workflow.now(); # 決定論的な再生安全な時刻
ワークフローコードで安全な副作用:
- 関数引数の読み取り
- シンプルな計算(ランダムなし)
- ロギング(通常)
指数バックオフなしの再試行設定
重大度:MEDIUM
状況:失敗するステップの再試行動作を設定
症状: 失敗するサービスに圧力がかかります。レート制限。カスケード障害。再試行ストームが停止を引き起こします。外部 API によってブロックされます。
これが失敗する理由: サービスが苦しんでいる場合、即座の再試行はそれを悪化させます。100 個のワークフローが即座に再試行 = 既に失敗しているサービスに 100 個のリクエストがヒットします。バックオフはサービスに復帰する時間を与えます。
推奨修正:
常に指数バックオフを使用します:
### Temporal:
const activities = proxyActivities({
retry: {
initialInterval: '1 second',
backoffCoefficient: 2, # 1s, 2s, 4s, 8s, 16s...
maximumInterval: '1 minute', # バックオフをキャップ
maximumAttempts: 5,
}
});
### Inngest(組み込みバックオフ):
{
id: "my-function",
retries: 5, # デフォルトで指数バックオフを使用
}
### 手動バックオフ:
const backoff = (attempt) => {
const base = 1000;
const max = 60000;
const delay = Math.min(base * Math.pow(2, attempt), max);
const jitter = delay * 0.1 * Math.random();
return delay + jitter;
};
スタンピングの群れを防ぐためにジッターを追加します
ワークフロー状態への大規模データの保存
重大度:HIGH
状況:ワークフローステップ間で大規模なペイロードを渡す
症状: ワークフロー実行が遅くなります。メモリエラー。「ペイロードが大きすぎます」エラー。ストレージコストが高くなります。再生が遅くなります。
これが失敗する理由: ワークフロー状態は永続化され、再生されます。10 MB のペイロードは保存、シリアライズ、すべてのステップで逆シリアライズされます。これはレイテンシーとコストを追加します。一部のプラットフォームにはハードリミットがあります(例:Step Functions 256KB)。
推奨修正:
### 間違い - ワークフロー内の大規模データ:
await step.run("fetch-data", async () => {
const largeDataset = await fetchAllRecords(); // 100MB!
return largeDataset; // ワークフロー状態に保存
});
### 正しい - 参照を保存、データではなく:
await step.run("fetch-data", async () => {
const largeDataset = await fetchAllRecords();
const s3Key = await uploadToS3(largeDataset);
return { s3Key }; // 参照のみ
});
const processed = await step.run("process-data", async () => {
const data = await downloadFromS3(fetchResult.s3Key);
return processData(data);
});
Step Functions の場合、大規模ペイロードに S3 を使用します:
{
"Type": "Task",
"Resource": "arn:aws:states:::s3:putObject",
"Parameters": {
"Bucket": "my-bucket",
"Key.$": "$.outputKey",
"Body.$": "$.largeData"
}
}
デッドレターキューまたはフェイルハンドラーがない
重大度:HIGH
状況:すべての再試行を使い果たすワークフロー
症状: 失敗したワークフローが静かに消える。問題が発生しても、アラートなし。顧客の問題が数日後に発見されます。手動復帰が不可能です。
これが失敗する理由: 再試行でも、一部のワークフローは永続的に失敗します。デッドレターハンドリングがなければ、失敗を知りません。顧客は無期限に待機し、あなたは気付かず、デバッグするデータがありません。
推奨修正:
// Inngest onFailure ハンドラー:
export const myFunction = inngest.createFunction(
{
id: "process-order",
onFailure: async ({ error, event, step }) => {
// エラー追跡にログ
await step.run("log-error", () =>
sentry.captureException(error, { extra: { event } })
);
// チームにアラート
await step.run("alert", () =>
slack.postMessage({
channel: "#alerts",
text: `Order ${event.data.orderId} failed: ${error.message}`
})
);
// 手動レビュー用にキュー
await step.run("queue-review", () =>
db.insert(failedOrders, { orderId, error, event })
);
}
},
{ event: "order/created" },
async ({ event, step }) => { ... }
);
n8n エラーハンドリング:
[Error Trigger] → [DB にログ] → [Slack アラート] → [チケット作成]
Temporal:workflow.failed またはワークフロー信号を使用します
エラートリガーなしの n8n ワークフロー
重大度:MEDIUM
状況:本番環境 n8n ワークフロー構築
症状: ワークフローが静かに失敗します。エラーは실行ログでのみ表示されます。アラートなし、復帰なし、誰かが気付くまで可視性なし。
これが失敗する理由: n8n はデフォルトで失敗時に通知しません。Error Trigger ノードがアラート機能に接続されていないと、失敗は UI にのみ表示されます。本番環境の失敗は気付かれません。
推奨修正:
すべての本番環境 n8n ワークフローには以下が必要です:
-
Error Trigger ノード
- ワークフロー内の任意のノード失敗をキャッチ
- エラーの詳細とコンテキストを提供
-
接続されたエラーハンドリング:
[Error Trigger] ↓ [設定: エラーの詳細を抽出] ↓ [HTTP: エラーサービスにログ] ↓ [Slack/メール: チームにアラート] -
デッドレターパターンを検討:
[Error Trigger] ↓ [Redis/Postgres: 失敗したジョブを保存] ↓ [別の復帰ワークフロー]
また使用:
- ノード失敗時の再試行(組み込み)
- ノードタイムアウト設定
- ワークフロータイムアウト
ハートビートなしの長実行 Temporal アクティビティ
重大度:MEDIUM
状況:数秒以上実行されるアクティビティ
症状: アクティビティがタイムアウトしても、作業が進行中です。ワーカーが再開時に作業が失われます。長時間実行されるアクティビティをキャンセルできません。
これが失敗する理由: Temporal はハートビート経由でスタックしたアクティビティを検出します。ハートビートなしで、Temporal はアクティビティが動作しているか、スタックしているかを判断できません。長いアクティビティはハングしているように見え、タイムアウトする可能性があり、適切にキャンセルできません。
推奨修正:
// 10 秒以上のアクティビティの場合、ハートビートを追加:
import { heartbeat, activityInfo } from '@temporalio/activity';
export async function processLargeFile(fileUrl: string): Promise<void> {
const chunks = await downloadChunks(fileUrl);
for (let i = 0; i < chunks.length; i++) {
// キャンセルをチェック
const { cancelled } = activityInfo();
if (cancelled) {
throw new CancelledFailure('Activity cancelled');
}
await processChunk(chunks[i]);
// 進捗を報告
heartbeat({ progress: (i + 1) / chunks.length });
}
}
// ハートビートタイムアウトを設定:
const activities = proxyActivities({
startToCloseTimeout: '10 minutes',
heartbeatTimeout: '30 seconds', # 30 秒ごとにハートビート必須
});
30 秒間ハートビートなしで、アクティビティはスタックと見なされます
検証チェック
冪等性キーなしの外部呼び出し
重大度:ERROR
Stripe/支払い呼び出しは冪等性キーを使用すべき
メッセージ:idempotency_key なしの支払い呼び出し。再試行時の重複請求を防ぐために冪等性キーを追加します。
重複排除なしのメール送信
重大度:WARNING
ワークフロー内のメール送信は既送を確認すべき
メッセージ:重複排除チェックなしでワークフロー内でメール送信。再試行が重複メールを送信する可能性があります。
タイムアウトなし Temporal アクティビティ
重大度:ERROR
すべての Temporal アクティビティにはタイムアウト設定が必要
メッセージ:タイムアウトなしの proxyActivities。無期限のハングを防ぐために startToCloseTimeout を追加します。
タイムアウトなしで外部 API を呼び出す Inngest ステップ
重大度:WARNING
外部 API 呼び出しはタイムアウトを持つべき
メッセージ:タイムアウトなしのステップ内での外部 API 呼び出し。ワークフローハングを防ぐためにタイムアウトを追加します。
ワークフローコード内のランダム値
重大度:ERROR
ランダム値は再生時に決定論を破ります
メッセージ:ワークフローコード内のランダム値。アクティビティ/ステップに移動するか、sideEffect を使用します。
ワークフローコード内の Date.now()
重大度:ERROR
現在時刻は再生時に決定論を破ります
メッセージ:ワークフローコード内の現在時刻。workflow.now() を使用するか、アクティビティ/ステップに移動します。
onFailure ハンドラーなし Inngest 関数
重大度:WARNING
本番環境の関数はフェイルハンドラーを持つべき
メッセージ:onFailure ハンドラーなしの Inngest 関数。本番環境の信頼性のためにフェイルハンドリングを追加します。
エラーハンドリングなしのステップ
重大度:WARNING
ステップはエラーを適切にハンドルすべき
メッセージ:try/catch なしのステップ。特定のエラーケースのハンドリングを検討します。
ステップから返される可能性のある大規模データ
重大度:INFO
ワークフロー状態内の大規模データは実行を遅くします
メッセージ:ステップから可能性のある大規模データを返却。S3/DB に保存して参照を返すことを検討します。
バックオフ設定なしの再試行
重大度:WARNING
再試行は指数バックオフを使用すべき
メッセージ:バックオフなしで設定された再試行。backoffCoefficient と initialInterval を追加します。
コラボレーション
委譲トリガー
- ユーザーがマルチエージェント調整が必要 -> multi-agent-orchestration(ワークフローはインフラを提供し、オーケストレーションはパターンを提供)
- ユーザーがワークフロー用のツール構築が必要 -> agent-tool-builder(ワークフローが呼び出せるツール)
- ユーザーが Zapier/Make 統合が必要 -> zapier-make-patterns(ノーコード自動化プラットフォーム)
- ユーザーがワークフロー内のブラウザ自動化が必要 -> browser-automation(Playwright/Puppeteer アクティビティ)
- ユーザーがワークフロー内のコンピューター制御が必要 -> computer-use-agents(デスクトップ自動化アクティビティ)
- ユーザーがワークフロー内の LLM 統合が必要 -> llm-architect(AI 駆動ワークフローステップ)
関連スキル
相性の良いスキル:multi-agent-orchestration、agent-tool-builder、backend、devops
使用時機
- ユーザーが workflow について言及または暗示
- ユーザーが automation について言及または暗示
- ユーザーが n8n について言及または暗示
- ユーザーが temporal について言及または暗示
- ユーザーが inngest について言及または暗示
- ユーザーが step function について言及または暗示
- ユーザーが background job について言及または暗示
- ユーザーが durable execution について言及または暗示
- ユーザーが event-driven について言及または暗示
- ユーザーが scheduled task について言及または暗示
- ユーザーが job queue について言及または暗示
- ユーザーが cron について言及または暗示
- ユーザーが trigger について言及または暗示
制限事項
- このスキルは上記のスコープで説明されたタスクに明確に一致する場合にのみ使用します。
- 出力を環境固有の検証、テスト、または専門家レビューの代替として扱わないでください。
- 必要な入力、権限、安全性の境界、または成功基準が不足している場合は、停止して明確化を求めてください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- sickn33
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/sickn33/antigravity-awesome-skills / ライセンス: MIT
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。