メインコンテンツへスキップ
オートメーションはアプリの一部で、スケジュールに従って、または外部サービスからイベントが送信されたときに自動的に実行されます。 kazzle.config.ts の process コンポーネントで宣言します。1 つのコンポーネントは必要なだけ多くのトリガーを持つことができます。

構造

{
  name: 'events',
  type: 'process',
  path: './components/events/index.ts',
  processMode: 'persistent', // or 'triggered'
  triggers: [
    { name: 'daily-digest', kind: 'schedule', schedule: '0 9 * * *', path: '/cron/daily-digest' },
    { name: 'stripe',       kind: 'webhook',                          path: '/webhook/stripe' },
  ],
}
ここで 2 つのことが起こっています:
  • processModeライフサイクルを選択します — 長時間実行されるサーバー、またはトリガーごとの 1 回限りの実行。
  • triggers[] はこのコンポーネントを実行するイベントをリストアップします。
この 2 つの部分は独立しています。永続的なサーバーは cron を持つことができます。一時的なプロセスはウェブフックを持つことができます。ワークロードに合ったライフサイクルを選択してから、必要なだけ多くのトリガーを追加してください。

processMode

モード実行内容使用時期
persistent (デフォルト)長時間実行される HTTP サーバー。トリガーは POST されます。コンポーネントが既に HTTP を提供している、またはメモリ内に状態を保持している(キュー、ウェブソケット、キャッシュ)。
triggeredエントリスクリプトはトリガーごとにスポーンされ、終了します。純粋なバックグラウンドジョブ — 夜間クリーンアップ、単一の Stripe ウェブフックハンドラーなど。アイドルサーバーなし。

トリガー

各トリガーには name(コンポーネント内で一意)、kind、およびモードに応じて schedule および/または path があります。
フィールド必須条件注記
name常にウェブフック URL セグメントとログで使用されます。ケバブケース。
kind常に'schedule' または 'webhook'
schedulekind: 'schedule' の場合5 フィールド cron 式。分単位の解像度が最小です。
pathprocessMode: 'persistent' の場合トリガーが到達するサーバー上の HTTP ルート。

永続モード — サーバーへの HTTP

永続的なコンポーネントのトリガーが発火すると、Kazzle は宣言された path でサーバーに POST します。リクエストは以下を含みます:
ヘッダー内容
Authorization: Bearer ${KAZZLE_TRIGGER_SECRET}これを検証してください。一致しない呼び出しは拒否してください。
x-kazzle-trigger-nameマニフェストからのトリガーの name
x-kazzle-trigger-run-idログ相関用の不透明 ID。
x-kazzle-triggered-bycron | webhook | manual
ウェブフックトリガーの場合、元のリクエストボディは POST ボディとして転送されます。スケジュールトリガーの場合、ボディは空です。
// components/events/index.ts (persistent mode)
const TRIGGER_SECRET = process.env.KAZZLE_TRIGGER_SECRET ?? '';

Bun.serve({
  port: Number(process.env.PORT),
  hostname: process.env.HOST,
  async fetch(req) {
    const url = new URL(req.url);

    if (req.method === 'POST' && url.pathname === '/cron/daily-digest') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      await sendDigest();
      return Response.json({ ok: true });
    }

    if (req.method === 'POST' && url.pathname === '/webhook/stripe') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      const event = await req.json();
      await handleStripe(event);
      return Response.json({ ok: true });
    }

    return new Response('not found', { status: 404 });
  },
});

トリガーモード — トリガーごとの 1 回限り

triggered コンポーネントのトリガーが発火すると、Kazzle はエントリスクリプトを新たにスポーンし、終了を待ちます。path はありません。スクリプトは環境変数からどのトリガーが発火したかを学習します。
環境変数
TRIGGER_NAMEマニフェストからのトリガーの name
TRIGGERED_BYcron | webhook | manual
RUN_IDログ相関用の不透明 ID。
WEBHOOK_PAYLOADJSON ボディ(ウェブフックトリガーのみ)。
// components/events/index.ts (triggered mode)
const trigger = process.env.TRIGGER_NAME;
const runId = process.env.RUN_ID;

if (trigger === 'daily-digest') {
  await sendDigest();
} else if (trigger === 'stripe') {
  const event = JSON.parse(process.env.WEBHOOK_PAYLOAD ?? '{}');
  await handleStripe(event);
}

console.log(`run ${runId} done`);
トリガーされたコンポーネントは本番環境にアイドルマシンがありません — 呼び出しごとにスピンアップし、終了時にシャットダウンします。

ウェブフック URL

POST https://api.kazzle.app/webhooks/{spaceId}/{appId}/{componentName}/{triggerName}
triggerName セグメントは、そのコンポーネントの triggers[] 内の kind: 'webhook' エントリと一致する必要があります。不明なトリガー名は 404 を返します。

スケジュール解像度

Cron 式は 5 フィールド(分、時間、日、月、曜日)で、分単位の解像度が最小です。分未満のスケジュールはマニフェスト検証時に拒否されます。

実行の記録方法

各トリガー発火は process_runs 行を trigger_nametriggered_byrun_id、および実行の終了ステータスで書き込みます。独自のコードからこれらをクエリするか、アプリの実行ビューで検査できます。

クレジット不足

失敗した実行は記録およびログされますが、スケジュールは通常のペースで実行を続けます — 不安定な実行がトリガーを無効にすることはありません。実行を停止する唯一のことはクレジットです:すべてのトリガー発火はスペースの残高に対してチェックされ、スペースがクレジット不足(またはビリング設定がない)の間、実行は 402 でスキップされます。これは自己修復可能です — スケジュールは武装したままで、トップアップ後の次の発火は通常どおり実行され、手動での再開は不要です。

後からオートメーションを追加

シンプルなアプリはトリガーなしで開始し、後で追加できます — 日次サマリーを追加、Stripe を接続、クリーンアップを実行。コンポーネントのライフサイクル(processMode)とトリガー(triggers[])は独立しているため、アプリの残りの部分を書き直さずに変更できます。