Durable FunctionsでSlackを使った承認ステップを実装してみた

Durable FunctionsでSlackを使った承認ステップを実装してみた

2025.12.03

はじめに

先日AWS Lambda Durable Functionsが発表されました。これにより、複数の手順が必要なアプリケーションやAIワークフローをLambda関数の中だけで簡単に構築できます。

https://aws.amazon.com/jp/about-aws/whats-new/2025/12/lambda-durable-multi-step-applications-ai-workflows/

本機能の全体像は以下の記事が参考になります。

https://dev.classmethod.jp/articles/aws-lambda-durable-functions-awsreinvent/

マルチステップでフローを定義して実行が可能で、人間による承認などの外部イベントの結果を待機するために使用できるコールバックを作成することができます。

こちらの記事でPythonと、AWSマネジメントコンソール経由でこの承認ステップを承認/拒否する例が載っています。

https://aws.amazon.com/jp/blogs/aws/build-multi-step-applications-and-ai-workflows-with-aws-lambda-durable-functions/

今回はこちらをTypeScriptとSlackを利用して実装してみます。

概要

登場するLambdaは以下の2つです

  • Durable Function(承認などのマルチステップを管理するLambda)
  • Slack Webhookを処理するLambda

architecture.drawio

動作している感じは以下の通りです。
ezgif-15458e4a251731ce

Slackのメッセージから承認と却下の2つのパターンを行っています。Slackのメッセージのボタンを押した瞬間に右側のLambdaの実行が完了しているのが見えると思います。これはDurable Lambdaがcallbackを返し、その結果をSlack→Slack Webhookを処理するLambdaが呼ばれ、そこからDurable Executionのコールバックを完了させることで、待機中だったDurable Lambdaのワークフローが再開し正常終了しているためです。

処理概要を箇条で書きます。

    1. Durable Functionの処理
    • 1.1. order_idを受け取る
    • 1.2. order_idバリデーションをする
    • 1.3. callback_idの発行
    • 1.4. callback_idを埋め込んだ承認/却下メッセージをSlackへ送信
    • 1.5. Durable Functionは待機状態へ
    1. Slackにて人が承認
    • 2.1. (1.4の結果)承認/拒否ボタンが置いてあるInteractiveなメッセージが送信されているので、人間が手動で押下
    1. Lambda(標準, Slack Webhook を処理する関数URLサーバー)
    • 3.1. 項2.1.の結果を受け取り、Durableのcallback_idに対して結果を送信
    1. 項3.1.によりDurable Functionが再開
    • 4.1.a. 却下の場合、Slackへ却下通知
    • 4.1.b. 承認の場合、注文処理を実施して、Slackへ承認通知

ソースコードはこちらのリポジトリに置いています。

https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop

以下順で構築していきます。

  • 承認等マルチステップを実行するLambda(Durable Function)
  • Slack Webhookを処理するLambda
  • Slack App

構築

承認等マルチステップを実行するLambda(Durable Function)の構築

上記のリポジトリを利用する想定で説明します。

pnpm install
# Durable Functionが利用可能なオハイオリージョンを選択
export AWS_REGION=us-east-2
# AWSアカウントIDを設定
export ACCOUNT_ID="<YOUR AWS ACCOUNT_ID>"

# AWS資格情報を取得

IAMロールの作成

aws iam create-role \
  --role-name "durable-function-role" \
  --assume-role-policy-document "file://lambda/durable/trust-policy.json"

AWSLambdaBasicExecutionRoleのアタッチ

aws iam attach-role-policy \
  --role-name "durable-function-role" \
  --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"

チェックポイント用ポリシーの作成

# テンプレートからポリシーファイルを生成
perl -pe "s/REGION/us-east-2/g; s/ACCOUNT_ID/${ACCOUNT_ID}/g" \
  lambda/durable/checkpoint-policy-template.json > lambda/durable/checkpoint-policy.json

# ポリシーを作成
aws iam create-policy \
  --policy-name "durable-checkpoint-policy" \
  --policy-document "file://lambda/durable/checkpoint-policy.json"

# ポリシーをアタッチ
aws iam attach-role-policy \
  --role-name "durable-function-role" \
  --policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/durable-checkpoint-policy"

S3バケットの作成

aws s3 mb "s3://my-lambda-deploy-bucket-${ACCOUNT_ID}"

Lambda関数の作成(初回ビルド・デプロイ含む)

cd lambda/durable

# ビルド(依存関係も含めてバンドル)& zipにまとめる
pnpm build && zip function.zip dist/index.mjs

# S3にアップロード
aws s3 cp function.zip "s3://my-lambda-deploy-bucket-${ACCOUNT_ID}/"

# Lambda関数を作成
aws lambda create-function \
  --function-name "myDurableFunction" \
  --runtime "nodejs24.x" \
  --role "arn:aws:iam::${ACCOUNT_ID}:role/durable-function-role" \
  --handler "dist/index.handler" \
  --code "S3Bucket=my-lambda-deploy-bucket-${ACCOUNT_ID},S3Key=function.zip" \
  --durable-config '{"ExecutionTimeout": 900, "RetentionPeriodInDays":1}'

これでデプロイは完了です。オハイオリージョンのLambda一覧にタイプ=永続で作成されていることが確認できます。まだSlackのトークンを環境変数に入れていないのでエラーになります。この後の手順で更新します。

CleanShot 2025-12-03 at 18.27.46@2x

中のコードについて解説します。基本的にはコメント通りですが、注意点を補足します。

https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop/blob/2c07a6622031c7fefccab22eb5a43038180907d2/lambda/durable/src/index.ts#L1-L183

本処理でcallbackの結果を待機します。
https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop/blob/2c07a6622031c7fefccab22eb5a43038180907d2/lambda/durable/src/index.ts#L44-L45

Slackで却下をしたら、notify-result でSlackへ却下通知。Slackで承認したら、process-order で 注文処理をして、 notify-result でSlackへ承認通知を行います。
https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop/blob/2c07a6622031c7fefccab22eb5a43038180907d2/lambda/durable/src/index.ts#L52-L81

Slack Webhookを処理するLambdaの構築

SlackからのWebhookを処理するHono on Lambda関数URLでpublicに公開しています。サーバー実装は以下の通りです。WebhookのPOSTボディ部にDurable Functionのcallback_idが入っている想定です。

https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop/blob/2c07a6622031c7fefccab22eb5a43038180907d2/lambda/server/src/index.ts#L1-L35

以下がDurable Functionへコールバックに結果を送信している箇所です。

https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop/blob/2c07a6622031c7fefccab22eb5a43038180907d2/lambda/server/src/index.ts#L22-L30

リポジトリのコードを使う場合、以下のコマンドでデプロイできます。

# Durable Functionが利用可能なオハイオリージョンを選択
export AWS_REGION=us-east-2
# AWS資格情報取得

$ cd iac
$ pnpm cdk deploy
$ pnpm cdk deploy
Bundling asset for-durable-lambda-stack/WebhookLambda/Code/Stage...

for-durable-lambda-stack: creating CloudFormation changeset...

(中略)

 ✅  for-durable-lambda-stack

✨  Deployment time: 61.17s

Outputs:
for-durable-lambda-stack.WebhookUrl = https://dk4mb2fhclsjqlg3mafq73ev6m0eozgv.lambda-url.us-east-2.on.aws/
Stack ARN:
arn:aws:cloudformation:us-east-2:111111111111:stack/for-durable-lambda-stack/03d9a350-cff4-11f0-a106-0af9bed2d1b9

✨  Total time: 62.08s

出力されたURL https://xxxxxxx.lambda-url.us-east-2.on.aws/webhook/slack をつけた https://xxxxxxx.lambda-url.us-east-2.on.aws/webhook/slack のURLをSlack Appで利用します。

Slack Appの作成

https://api.slack.com/apps

Slack Appを作成します
CleanShot 2025-12-03 at 11.43.19@2x

From scratchを選択
CleanShot 2025-12-03 at 11.43.33@2x

アプリの名前とワークスペースを選択
CleanShot 2025-12-03 at 11.44.28@2x

作成したら以下のような画面遷移します
CleanShot 2025-12-03 at 11.45.08@2x

Interactivity & Shortcutsを選択
CleanShot 2025-12-03 at 11.46.27@2x

Slack Webhookを処理するLambda関数のURL(https://xxxxxxx.lambda-url.us-east-2.on.aws/webhook/slack)をセットします。
CleanShot 2025-12-03 at 11.46.44@2x

Durable FunctionからSlackへメッセージを送信するためのトークンを発行します。

CleanShot 2025-12-03 at 12.52.42@2x

scopeは chat:write のみ付与します。
CleanShot 2025-12-03 at 12.52.57@2x
CleanShot 2025-12-03 at 12.53.12@2x

次に「Install to ワークスペース名」でSlack Appをインストールします。
CleanShot 2025-12-03 at 12.53.50@2x

インストール完了すると、Bot User OAuth Tokenが取得できます。こちらを控えておきます。
CleanShot 2025-12-03 at 17.56.34@2x

Slackに戻るとインストールされていることが確認できます。

CleanShot 2025-12-03 at 12.55.27@2x

Slack Appを入れたら、今回利用するチャンネル #approvals#approval-results に招待します。
CleanShot 2025-12-03 at 13.07.07@2x
CleanShot 2025-12-03 at 13.07.16@2x

動作確認は以下のコマンドで可能です。

export SLACK_BOT_TOKEN="xoxb-xxx"
curl -X POST https://slack.com/api/chat.postMessage \
   -H "Content-Type: application/json" \
   -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
   -d '{"channel": "'"#approvals"'","text": "テストメッセージ"}'

承認等マルチステップを実行するLambda(Durable Function)へSLACK_BOT_TOKENを登録

export SLACK_BOT_TOKEN="xoxb-xxx"

aws lambda update-function-configuration \
  --function-name "myDurableFunction" \
  --environment "Variables={SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN}}"

動かしてみる

冒頭と同じですが、動作している様子は以下の通りです。
ezgif-15458e4a251731ce

Lambdaのテストメッセージに以下を指定し、実行します。

{
  "order_id": "order-12345"
}

CleanShot 2025-12-03 at 19.03.59@2x

#approvals チャンネルにメッセージが届きます。承認を押下します。
CleanShot 2025-12-03 at 19.05.21@2x

#approval-results チャンネルに完了が通知されます。
CleanShot 2025-12-03 at 19.06.11@2x

CleanShot 2025-12-03 at 19.07.26@2x

ちなみに却下した結果が以下の通りで、process-orderがないことがわかります。
CleanShot 2025-12-03 at 19.08.48@2x

こちらは処理で外しているためです。

https://github.com/shuntaka9576/lambda-durable-functions-human-in-loop/blob/2c07a6622031c7fefccab22eb5a43038180907d2/lambda/durable/src/index.ts#L51-L61

最後に

今回はDurable Functionsのcallback作成機能についてフォーカスしてブログを書きました。生成AIなどと組み合わせてヒューマン・イン・ザ・ループ(HITL)などで活用できそうですね。SDKでTSでワークフローを書けるので静的解析を使ったり、柔軟な表現が可能です。CDKからデプロイできるようになるのが待ち遠しいです。。

TSのSDKのリポジトリを見る限り、Durable Functionsはテストツールや静的解析ツールなどツールチェインもあるようで気になりますね。。時間を見つけてブログを書いていきたいです!

参考

durable-execution-sdkのサンプル集(公式)

https://github.com/aws/aws-durable-execution-sdk-js/tree/main/packages/aws-durable-execution-sdk-js-examples/src/examples

SDKの使い方関連

https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html
https://docs.aws.amazon.com/lambda/latest/dg/durable-execution-sdk.html

この記事をシェアする

FacebookHatena blogX

関連記事