メインコンテンツに移動

builders.flash

AWS Lambda durable functions と AI Agent で勉強会資料作成を任せてみた

2026-07-02 | Author : 廣嶋 聡史(株式会社ウェザーニューズ)、長友 健人

Missing alt text value

はじめに

こんにちは。株式会社ウェザーニューズでリードエンジニアをしています、廣嶋です。

昨今、AI Agent を活用した体験は急速に広がっており、今では IT 企業を中心に話題にこと欠かないと思います。

一方で、AI Agent のアウトプットは人間が行う活動よりさらに多く、場合によっては、チームがまだ十分に理解していない技術や情報も取り込んだアウトプットを生成するため、エンジニア自身も振り返りと学習を継続的に行っていく必要があると思っています。

この記事では、2025年の AWS re:Invent で発表された AWS Lambda durable functions を使い、AI Agent が勉強会資料を自動作成する Bot 「勉強会資料まとめるくん」を構築した事例を紹介します。

勉強会資料 Bot に限らず、AI Agent にタスクを委任して結果を受け取るワークフロー全般に応用できるパターンですので、少しでも参考になればと思います。

X ポスト » | Facebook シェア » | はてブ »

builders.flash メールメンバー登録

builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。

今すぐ登録 »

勉強会資料まとめるくん構築の背景

私たちの開発チームではスクラム開発を行っており、1 週間を 1 スプリントとして進めています。

スプリントの最中に、チームメンバーが気になった技術や、変化していく状況の中でアーキテクチャをどのように変化させていくべきかを議論したい場合には、Slack のリストにトピックを入力していきます。そして、スプリントの最後にチームへ共有し、ディスカッションを行っていました。

しかし、新しい技術を調査するのはかなり時間のかかる作業です。1 週間というスプリントの中で行うにはチームメンバーの負担が大きく、また、調査できる範囲も限られていました。その結果、勉強会で話す内容も、だんだんと過去に扱ったものと似たような内容に収束していきました。

そこで、チームメンバーが登録したトピックを起点に、生成 AI が調査・整理・共有準備を支援する仕組みを構築しました。
動作フローとしては、まずチームメンバーが気になった技術や議論したいテーマを、これまで通りリストに登録します。その後、スプリントの終盤に登録されたトピックをもとに、生成 AI が関連情報を調査し、要点を整理します。

これにより、チームメンバーの調査負担を抑えながら、毎週の勉強会で新しい技術やアーキテクチャ上の論点を継続的に議論できるような仕組みを試してみたので紹介しようと思います。 

Missing alt text value

勉強会資料まとめるくんのアーキテクチャ

アーキテクチャとしてはシンプルで、AWSサービスは AWS Lambda durable functions、Amazon EventBridge、Amazon Bedrock AgentCore Runtime の 3 つのみを組み合わせて作成しました。

ロジックの部分はすべて Lambda durable functions に寄せています。これにより、AWS Step Functions を利用した場合に関数が散らばり、似たような処理が重複してしまうようなことを避けられ、処理コードの再利用もしやすくなりました。そのため、開発体験が良かった点があります。

また、エージェントの構成としては Agent as Tool パターンを用いたマルチエージェント構成でタスクを実行しています。

シングルエージェントに調査・整理・資料化といった複数のタスクをまとめて担わせると、各工程での中間出力や特に調査の工程で発生する情報収集の際に発生する不要な情報が 1 つのコンテキストに積み上がってしまい、精度低下につながる “コンテキスト汚染(context pollution)” が発生しやすくなります。

Agent as Tool パターンは、オーケストレータとなるエージェントが各タスクのサブエージェントを「ツール」として呼び出すことで、役割の境界がコンテキストの境界になるため、タスクごとにコンテキストをクリーンに保つことができます。その結果、複数のタスクを扱う場合でもタスクの成功率を高く保ちやすくなります。

さらに、Strands Agents SDK を使うことで、エージェント開発の期間も短縮できました。

アーキテクチャ図

Lambda durable functions とは

Lambda durable functions は、2025 年の AWS re:Invent で発表された AWS Lambda の新機能です。

従来の Lambda は最大15分で処理を終える必要がありました。そのため、たとえば AI Agent を呼び出して応答を待つ処理や、注文処理において決済後に人間の承認を待ってから出荷するといった「途中で長時間待つワークフロー」は、Step Functions やキューを組み合わせて、状態管理を自前で設計する必要がありました。

Lambda durable functions では、処理を複数のステップに分割し、各ステップの結果を自動でチェックポイントとして保存します。AI Agent の応答待ちや人間の承認待ちといった待機中はリソースが解放され、実行時間課金が発生しません。再開時にはチェックポイントから続きを再実行するため、全体として最大1年間の長期ワークフローを実現できます。

また、途中で処理が失敗した場合も、完了済みのステップはスキップし、失敗箇所から自動で再開されます。そのため、ワークフローの進行状態を管理する仕組みを自前で実装する必要がありません。

専用の定義言語を新たに学ぶ必要はなく、Lambda 単体で TypeScript や Python の普段のコードのままワークフローを組める点も大きな魅力です。

アーキテクチャ決定までの流れ

Phase 1: AWS Lambda を中心とした検討

まず初めに、簡単に実装する方法として、シンプルな Lambda だけの構成を検討しました。Slack API から Slack List の情報を取得し、その情報をそのまま Lambda 上の Agent に渡し、文章の生成と Slack Canvas の作成を行う構成です。

試行錯誤の段階ではうまく動作していました。
しかし、エージェントにWeb情報を収集させる際に、トピックの内容によっては調査内容の集約粒度がエージェントの判断によって変わります。また、求める成果物の精度のために文章を書き起こすだけでなく情報の整形のタスクを追加すると、平均 20 分・最大で 30 分の実行時間が必要になっていき、 AWS Lambda の最大タイムアウトである 15 分を超えて失敗するようになりました。

Phase 2: AWS Lambda durable functions の採用

次に、Lambda のタイムアウト問題を解決するために、ワークフローを構成し、処理を分散することを考えました。

最初は AWS Step Functions を使う構成を検討していましたが、せっかくなので新しく発表されたサービスを使ってみようと思い、Lambda durable functions と AgentCore Runtime を用いた構成に置き換えてみました。

先ほども書いた通り、Lambda durable functions では待機を含む長期ワークフローを全体として最大1年間実行できます。そのため、Agent の処理完了を Lambda が実行状態のまま待ち続ける必要がなくなり、単一実行の 15 分タイムアウトに引っかかりにくい構成にできました。

一方で、Lambda durable functions 自体に関する知識がまだ十分ではなかったため、実行単位である Job のステータスやAgent が失敗してリトライする場合の状態管理を別サービスでやろうとしてしまい、構成が複雑になっていました。そこで、弊社をサポートいただいている AWS の長友さんに、アーキテクチャについて相談しました。

分散処理のための構成

Phase 3 : Callback 機能による状態管理の簡素化

長友さんに教えていただいたことは、AWS が公式に提供している Durable Execution SDK と Lambda durable functions 自体のチェックポイントとリプレイの仕組みによって「再開時に状態を復元するためのロジック」をアプリ側で書かなくてもよくなる点でした。

具体的には、各 Step の処理が完了するとその結果がチェックポイントに記録され、関数の再開時はコードを先頭からリプレイしつつ、完了済みの処理は再実行せずに記録済みの結果がそのまま返ります。この「完了した処理を飛ばして続きから進める」挙動を SDK が肩代わりしてくれるため、状態管理を自前で書く必要がなくなります。

今回の記事生成ワークフローに当てはめると、waitForCallback() を使った流れは次のようになります。

  1. タスクを投げて一時停止 — waitForCallback() を呼ぶとトークンが発行され、結果が返ってくるまで一時停止をする。
  2. AI Agent が処理 — 処理中は Lambda がリソースを解放するので待機コストはゼロ。
  3. トークンで結果を返す — 完了したら AI Agent がトークンを添えて SendDurableExecutionCallbackSuccess を呼ぶ。
  4. リプレイで再開 — Lambda が先頭からリプレイして完了済み Step を飛ばし、結果を持って次へ進む。


ポイントは、待っている間は完全にリソースが解放されているので、AI Agent が何時間かかっても実行時間課金がされないことです。
従来はポーリングやキューで自前実装が必要だった部分が、SDK 一行で済みました。

簡素化された構成

全体のワークフロー

全体のワークフローは以下のようになります。

オーケストレーター側の実装

オーケストレーター側 (Durable Function) は、以下のように実装できます。

typescript
// ── オーケストレーター側(Durable Function)──
import {
  BedrockAgentCoreClient,
  InvokeAgentRuntimeCommand,
} from "@aws-sdk/client-bedrock-agentcore";
import { withDurableExecution, DurableContext } from "@aws/durable-execution-sdk-js";
import { randomUUID } from "crypto";
import { fetchSlackListTopic, createSlackCanvas } from "./helper";

const agentCoreClient = new BedrockAgentCoreClient({});

// AgentCore Runtime を起動するだけ(agent側が即returnするので結果は待たない)
async function invokeAgentCore(topic: string, itemId: string, callbackId: string) {
  await agentCoreClient.send(
    new InvokeAgentRuntimeCommand({
      agentRuntimeArn: process.env.AGENT_RUNTIME_ARN,
      runtimeSessionId: randomUUID(),
      payload: JSON.stringify({ topic, item_id: itemId, callback_id: callbackId }),
    }),
  );
}

export const handler = withDurableExecution(async (_: unknown, ctx: DurableContext) => {
  const item = await ctx.step(
    "fetchSlackTopic",
    async () => await fetchSlackListTopic(),
  );

  const agentResult = await ctx.waitForCallback(
    "runAgentCore",
    // callback 生成時に1回だけ実行(リプレイ時は再実行されない)
    async (callbackId: string) => {
      // callbackId を渡して Agent を非同期起動 → ここでサスペンド(待機中課金ゼロ)
      await invokeAgentCore(item.topic, item.id, callbackId);
    },
    { timeout: { minutes: 60 } },
  );

  // callback で結果が返ると、完了済み Step を飛ばしてここから再開
  const canvasId = await ctx.step(
    "createSlackCanvas",
    async () => await createSlackCanvas(agentResult),
  );

});

エージェント実行側の実装

また、エージェントを実行する側は、調査・整理した結果を callback_id とともに send_durable_execution_callback_success で返すだけです。

python
# ── AI Agent側(AgentCore Runtime)── 
import json
import threading
import boto3
from bedrock_agentcore import BedrockAgentCoreApp

lambda_client = boto3.client("lambda")
app = BedrockAgentCoreApp()

def run_orchestrator_agent(topic):
    ...  # Strands Agent の実行(省略)


def run_research_pipeline(topic, item_id, callback_id, app, task_id):
    try:
        result = run_orchestrator_agent(topic)

        # callback_id を添えて結果を返す → Durable Function がリプレイ再開
        lambda_client.send_durable_execution_callback_success(
            CallbackId=callback_id,
            Result=json.dumps(
                {"item_id": item_id, "title": ..., "result": result},
                ensure_ascii=False,
            ).encode("utf-8"),
        )
    except Exception as e:
        lambda_client.send_durable_execution_callback_failure(
            CallbackId=callback_id,
            Error={"ErrorType": "AgentPipelineError", "ErrorMessage": str(e)},
        )
    finally:
        app.complete_async_task(task_id)  # セッション解放


@app.entrypoint
def invoke(payload: dict) -> dict:
    topic, item_id, callback_id = payload["topic"], payload["item_id"], payload["callback_id"]

    # 非同期タスクを登録してセッションを維持(待機中も課金ゼロ)
    task_id = app.add_async_task("study_material_research", {"topic": topic, "item_id": item_id})
    threading.Thread(
        target=run_research_pipeline,
        args=(topic, item_id, callback_id, app, task_id), daemon=True,
    ).start()
    return {"status": "accepted"}

ポイントは、待機中は durable functions 側のリソースが解放されるため、AI エージェントの処理に時間がかかっても、その待機時間に対する実行時間課金が発生しない点です。

従来はポーリングやキューで自前実装が必要だった部分が、SDK の waitForCallback() を使うことで、アプリ側の状態管理を大きく簡素化できました。

まとめ

今回は、AWS Lambda durable functions と Amazon Bedrock AgentCore Runtime を組み合わせ、AI エージェントを使って勉強会資料を自動作成するワークフローを構築しました。今回のアーキテクチャ判断を振り返ると、まずは単一エージェント + Lambda のシンプルな構成から始め、実際に動かす中で見えてきた課題に応じて構成を見直していく流れが良かったと思います。

一方で、AI エージェントを使った仕組みをこれから試し始めていく場合、最初から Lambda durable functions やマルチエージェント構成を前提にする必要はないと思います。まずは単一 Agent + Lambda のようなシンプルな構成で小さく作り、実際に動かしながら制約を確認するのがおすすめです。

たとえば、「処理時間が読みづらい」「Lambda のタイムアウトに近づく」「外部処理の完了を待つ必要がある」「失敗時にどこから再開すべきかを管理したくなる」といった課題が見えてきた場合は、Lambda durable functions が有効な選択肢になります。

また、今回の調査・整理・資料化のように、役割ごとにコンテキストを分けたい場合や 1 つのエージェントに複数の責務を持たせることで出力品質が不安定になる場合は、マルチエージェント構成を検討するとよいと思います。

AI エージェントを使ったワークフローでは、最初から完成形のアーキテクチャを決めきるよりも、まず小さく作って動かし、処理時間・状態管理・出力品質のどこに制約が出るかを見極めながら、構成を段階的に育てていくのがよいと感じました。

今回のアーキテクチャ判断や構成例が、これから AI エージェントを使った仕組みを作る方の参考になればと思います。

7/16 (木) 開催 : AWS Lambda Durable Functions によるコード型ワークフロー

  • 開催日時 : 2026 年 7 月 16 日 (木) 10:00 am - 12:00 pm
  • 開催場所 : オンライン開催
  • 主催 : アマゾン ウェブ サービス ジャパン合同会社

本ハンズオンワークショップでは、AWS Lambda Durable Functions を活用し、使い慣れた Lambda 環境と好みのプログラミング言語でシンプルな逐次コードを記述するだけで、信頼性の高いマルチステップワークフローを構築する方法を学びます。障害時の自動リトライ、最大1年間の実行一時停止、アイドル時間の課金なしといった特長を体験しながら、長時間実行プロセスの実装手法を習得できます。

参加登録はこちら »

筆者プロフィール

Missing alt text value

廣嶋 聡史(Satoshi Hiroshima)

株式会社ウェザーニューズ陸上気象事業部
Social Infra開発チーム

スクラムマスターとしてチームマネジメントを行いながら、テックリードとしてプロダクト開発の技術面をリードし、社内の技術コミュニティの活性化にも取り組んでいます。趣味は写真撮影で、風景や街並みを撮ることが好きです。

Missing alt text value

長友 健人 (Kento Nagatomo)

アマゾン ウェブ サービス ジャパン合同会社. ソリューションアーキテクト

AWS のソリューションアーキテクトとして Web 系のお客様を中心にアーキテクチャ設計支援を担当。
友人が飼っている犬のキリちゃんの可愛さを伝える活動をしています。