トリガー・スケジューラ¶
主トリガは Backlog Webhook(status / コメント / 投稿日時更新の即応)。配信時刻トリガは EventBridge Scheduler の動的
at(投稿日時)schedule。Scan Lambda はrate(1 day)の日次セーフティネットとして Webhook 取りこぼしを救済する。
トリガー種別¶
| 種別 | 起動条件 | 実装 | 反応時間 |
|---|---|---|---|
| status 変化 | Backlog 課題が automedia承認 に遷移 |
Backlog Webhook → webhook-backlog Lambda → EventBridge Schedule at(max(投稿日時, now+5s)) 登録 |
秒精度 |
| コメントコマンド | /automedia send 等 |
同上 → Deliver/Preview/Cancel Lambda invoke | 秒精度 |
| 投稿日時到達 | EventBridge Schedule at(投稿日時) |
Schedule 発火 → Deliver Lambda invoke | 秒精度 |
| セーフティネット | rate(1 day) で Webhook 取りこぼしを救済 |
EventBridge Scheduler → Scan Lambda | 最大 24h(漏れ救済) |
| LINE follow / message | LINE Webhook | LINE Webhook Lambda → 即応 reply or SQS | 5 秒以内 |
稼働環境 — 担当者の PC は不要¶
重要
Backlog Webhook 受信は AWS API Gateway + webhook-backlog Lambda、配信時刻トリガは EventBridge Scheduler、配信実行は deliver Lambda(Claude Platform on AWS) であり、すべて spin-dd の AWS アカウント上で動く。担当者の PC を起動しておく必要はない。週末・深夜・祝日でも、誰がログインしていなくても自動で実行される。
| Q | A |
|---|---|
| 週末でも投稿される? | はい |
| 深夜帯の配信は? | 静粛時間帯を project.yml で除外しない限り配信される |
| 担当者が休暇中でも? | はい |
| ランナーは誰が動かす? | AWS のマネージドサービス(API Gateway + EventBridge + Lambda)。自前 runner / EC2 は不要 |
Webhook 主体の設計¶
Backlog Webhook を主トリガ にすることで以下のメリットを実現:
| 観点 | 値 |
|---|---|
| 反応時間(status 変化) | 秒精度 (Webhook 受信 → 即 Schedule upsert) |
| 反応時間(コメントコマンド) | 秒精度 |
| Backlog API 呼び出し | イベント駆動のみ + 日次セーフティネット 1 回 |
| 配信時刻精度 | 秒精度(動的 at(投稿日時) schedule) |
| 取りこぼし | Webhook 取りこぼし → 日次 Scan で救済 |
Backlog Webhook → Lambda の経路¶
sequenceDiagram
participant U as 運用担当者
participant BL as Backlog
participant APIGW as API Gateway
participant BWHL as Backlog Webhook Lambda
participant EB as EventBridge Scheduler
participant DLV as Deliver Lambda
U->>BL: 課題を `automedia承認` に遷移 (投稿日時は未来)
BL->>APIGW: webhook IssueUpdated
APIGW->>BWHL: invoke
BWHL->>BWHL: 署名検証 / tenant 解決
BWHL->>EB: PutSchedule(at(投稿日時), input={tenant, issueKey})
BWHL-->>APIGW: 200 OK
Note over EB: 投稿日時に到達
EB->>DLV: invoke (秒精度)
DLV->>BL: 配信結果コメント + 自動配信実行日時 更新
EventBridge Schedule の運用¶
- Schedule 名:
automedia-deliver-${tenant}-${issueKey}で一意化 - Schedule action:
aws:lambda:InvokeFunctionでDeliver Lambdaを起動、payload に{tenant, issueKey}を含める IssueUpdatedで投稿日時が変わったら 同名 Schedule を update(create or replace)IssueUpdatedで status が戻ったら /cancelコマンドが来たら Schedule を delete- Schedule 発火後は自動削除されるが、念のため Deliver Lambda が完了時に delete を呼ぶ(残骸クリーンアップ)
タイムゾーン規約¶
- Backlog「投稿日時」: 入力は JST(
Asia/Tokyo)固定。Backlog UI も JST 表示 - EventBridge Schedule: タイムゾーン指定可。
at(2026-05-20T19:00:00)+timezone=Asia/Tokyoで登録 - Lambda: 環境変数
TZ=Asia/Tokyoを設定 orIntl.DateTimeFormatで明示 - プロジェクト別の上書き:
.automedia/project.yml > default_timezoneで対応可能(将来用)
Backlog Webhook Lambda の Schedule 登録擬似コード:
import { SchedulerClient, CreateScheduleCommand, UpdateScheduleCommand } from '@aws-sdk/client-scheduler';
const scheduler = new SchedulerClient({ region: 'ap-northeast-1' });
async function upsertDeliverSchedule(tenant: string, issueKey: string, scheduledJST: string) {
const name = `automedia-deliver-${tenant}-${issueKey}`;
const payload = JSON.stringify({ tenant, issueKey });
const params = {
Name: name,
ScheduleExpression: `at(${scheduledJST})`, // e.g. at(2026-05-20T19:00:00)
ScheduleExpressionTimezone: 'Asia/Tokyo',
Target: {
Arn: process.env.DELIVER_LAMBDA_ARN!,
RoleArn: process.env.SCHEDULER_ROLE_ARN!,
Input: payload,
},
FlexibleTimeWindow: { Mode: 'OFF' },
};
try {
await scheduler.send(new CreateScheduleCommand(params));
} catch (e: any) {
if (e.name === 'ConflictException') {
await scheduler.send(new UpdateScheduleCommand(params));
} else throw e;
}
}
静粛時間帯(quiet hours)¶
業務的・倫理的に深夜配信を避けたい場合、.automedia/project.yml で静粛時間帯を定義する。Backlog Webhook Lambda が Schedule 登録前に判定する。
判定:
- 投稿日時が静粛時間帯に 入る 場合:
- 既定: Schedule を登録せず、Backlog コメントで警告(「投稿日時を見直してください」)
- オプション: 翌朝の
quiet_hours.toまで遅延配信(Schedule の時刻を自動補正)
二重 invoke の防止(冪等性)¶
Backlog カスタムフィールド 自動配信実行日時 を冪等性キーとして使う。
- Deliver Lambda は配信成功時に「自動配信実行日時 = now()」を書き込む
- 同一の
(tenant, issueKey)で複数経路(Webhook 起動 / Schedule 発火 / Scan 救済)から invoke されても、Deliver Lambda 側で DynamoDB lock を取得して二重実行を防止 - 配信失敗時にリトライしたい場合は、人間が手動で
自動配信実行日時をクリア、またはfailedラベル付与で再 invoke 許可
同時 invoke の防止¶
Deliver Lambda は invoke 時に DynamoDB の条件付き put で (tenant, issueKey) の lock を取得:
await ddb.send(new PutItemCommand({
TableName: 'automedia-deliver-locks',
Item: { tenant, issueKey, takenAt: now, ttl: now + 3600 },
ConditionExpression: 'attribute_not_exists(issueKey)',
}));
取得失敗時は no-op で終了。TTL 1 時間で自動失効。
Scheduler 設計(Phase 1b 全体)¶

- 主経路 (統一): Backlog Webhook → EventBridge Schedule 登録 → 投稿日時に発火 → Deliver
- 即時送信も同経路: 投稿日時が過去 / コメント
/automedia sendの場合はat(now+5s)で登録 → 同じ EventBridge 経路で発火 (経路を分けない、Issue #104 確定) - セーフティネット: 日次 Scan Lambda が「漏れ」を検知(通常 0 件、検知時は CloudWatch Alarm)
manual トリガーのコマンド仕様¶
Backlog コメントは Backlog Webhook が IssueCommented イベントで受け、コマンドを parse する。
| コマンド | 説明 | 経路 |
|---|---|---|
/automedia send template=<id> [audience=<tag-expr>] |
即時配信 | Backlog Webhook → Deliver Lambda invoke |
/automedia preview |
草案の配信プレビューを返信 | Backlog Webhook → Preview Lambda |
/automedia cancel |
scheduled 状態の取り消し | Backlog Webhook → EventBridge Schedule delete |
/automedia status |
現在の状態を返信 | Backlog Webhook → 状態取得 → Backlog コメント |
event トリガーの例¶
| イベント | アクション | 経路 |
|---|---|---|
| LINE follow | 登録クーポンの送付 | LINE → API Gateway → LINE Webhook Lambda(即応 reply) |
| 特定アンケート回答 | タグ付与 + 次回配信フラグ | LINE → LINE Webhook Lambda → SQS → Deliver Lambda |
| HubSpot コンタクト更新 | タグ同期 | HubSpot → API Gateway → Webhook Lambda(後続フェーズ) |
並行制御¶
- 同一 ContentTask の同時実行防止: Deliver Lambda の DynamoDB 条件付き put(前述)
- 同一テナントの並行配信数: Lambda の reserved concurrency でテナント別に制限可能
- 外部 API レート制御: Deliver Lambda 内 TypeScript で吸収(指数バックオフ)