はじめに
Serverless Days 2025 キーノート Server Less Code More のセッションレポートです。
LLMの転換点
- 転換点はClaude 3.5 SonnetとToolUseの登場
- ToolUseによって、AIにファイルを書かせる・読ませるなどが可能になった
- 簡単な100行のスクリプト程度で、AIがコードを書く仕組み(Coding Agentの原型)が出来上がった
- LLMのできることが増えた=LLM活用の幅が大きく広がった
今でこそLLMが当たり前のように様々なツールを使えるようになっており、その恩恵を感じることがなくなりつつありますが、これがなければAI Agentなんて夢のまた夢だったと思います。
外部世界へ一切干渉できないAI Agentに、価値はほとんど無さそうですよね。
逆に言えば、ToolUseさえあれば最低限のAIエージェント的なものは作れる、というように私は認識しています。
そのくらいToolUseは重要な技術である、と言えるのではないでしょうか。
Bedrockとサーバーレス
- ネイティブアプリ(Bedrock Engineer)とBedrockがあればOK
- これこそまさにサーバーレス
個人的には「これでいいの!?」となる、印象的なアーキテクチャ図でした。
個人的にはサーバーレスアーキテクチャと言われると「API Gatewayがあって…」「LambdaからBedrockを呼んで…」という固定概念があったので、新たな世界の扉を開けるような感覚でした。
もちろんサービスの提供方法によるかもしれませんが、1つの引き出しとして持っておきたい、シンプルイズザベストな構成だと思います。
普遍的なサーバーレスデザイン
- 関数単位での設計
- どんな環境でも動く形にしておく
- ステートレス
- コンピューティングインスタンス自体にはデータを置かない、外部にデータを保存する
- イベントドリブン
- なにかのイベントをきっかけに動く
これがサーバーレスの本質。
個人的には正直あまり意識することなく使っている部分だったので、綺麗に言語化されていて勉強になりました。
そして何より重要なのが、このデザインはAI Agent開発においても変わらないということ。
LLMを組み込んだアプリケーション開発
- LLMの制約
- ナレッジカットオフがある
- 最新情報は知らない、自分が何を知らないのかも知らない
- 外部とのインタラクションがない
- システム操作不可能、言語モデルだもの
- ステートレス
- 会話履歴を保持しないため、前の会話を引き継げない
- ナレッジカットオフがある
- LLMの制約を前提に、ソフトウェアとして実装せよ
- コンテキストの注入
- システムプロンプト:LLMにどういうことをしてほしいか指示しておく
- 会話履歴の管理:裏側で会話のやり取りデータを持っておき、それと合わせてインプットする
- RAG:様々な外部データとの連携
- 上記だけでは、自律的な行動に限界がある
- 一方的なコンテキスト注入を超えて、外界とのインタラクティブなアクションを実現したい=AI Agent
- コンテキストの注入
単なるLLMだと様々な制約があるので、それを解消するような形でアプリケーションを構築していく必要がある。
ただ、これだと外界とマルチターンでやり取りをしてくれずワンショットでの実行に帰結しがち。
せっかくならもっと外界に溶け込むように、かつ自律的に動いてほしい!というのがモチベーションとしてあります。
そうなるとやはりAI Agentの開発へ移っていきます。
AI Agent開発
-
AI Agentはアプリケーション
- アプリケーションはプロンプトとツール情報をLLMに渡す
- LLMはどのツールを実行するかアプリケーションに返す
- アプリケーションはツールを実行する
- アプリケーションはツール実行結果をLLMにわたす
- LLMはその結果を踏まえてアプリケーションへレスポンスを返す
- 必要に応じて、ツール実行を繰り返す
この登壇の中で繰り返し強調されていたのが、AI Agentはアプリケーションであるということ。
これまでと違う、全く新しい特別なものを作るというわけではなく、これまでのアプリケーション開発の延長線上に存在するのがAI Agent開発。
ここの認識を改められたのが個人的にとても有益でした。
AIエージェントを実装する
前提として、最初の普遍的サーバーレスデザインを踏まえて、AIエージェントを実装します。
ここが本質なので、ここを常に忘れないことが重要です。
シンプルなAIエージェントを実装する
- ユーザー入力を受け付けるAIエージェント関数を用意し、その中で以下を設定
- システムプロンプト、RAGコンテキスト、ツール、コンポジットプロンプト
- 会話履歴を積み重ねる処理
- ツールを実行するループ処理
フレームワークに依存しない形で書くと、こんな形になるようです。
本質は、LLMが必要だと思った分だけToolを実行するということ。つまり、エージェントの思考→ツール実行→内容を受け継ぐ→エージェントの思考…
というループを繰り返す形がAI Agentの基本形です。
その思考の判断基準や流れをシステムプロンプトなどで実装しておく、という形になると思います。
余談:Strands Agents SDKのAgent Loopもこれと同じ思想で作られていると思います。
大規模なエージェントの実装
- より複雑になるのは避けられない
- ビジネスの差別化とならない重労働として色んなことを考慮する必要がある
- 認証認可、メモリ管理、オブザーバビリティ、エラーハンドリング…
先程のシンプルなエージェントだと気にしなくて良かった部分が、どんどんボトルネックになっていきます。
Strands Agents SDK on AWS
- コンテキストの保持
- Agent()を2回連続で呼び出しても、コンテキストが共有される
- ただし、実際にクラウドへデプロイすると、Lambdaなどはステートレスなので会話履歴を保持し続けることはできない
- 解決策:ステートを切り出して外部ストレージに保持する
- 認証認可
- 解決策:Cognitoなどを組み合わせていく
- 関数の設計
- エージェントの処理ロジックは、色んなところで使い回せるような関数としておく
- Lambdaのhandler関数内に直接エージェントロジックを書くと、ECSなどではそのまま使えない
- なので、handlerから呼び出す別関数としてエージェントの処理を切り出しておくことが重要
- ツールも、それぞれで関数に切り出しておくとGood
- エージェントの処理ロジックは、色んなところで使い回せるような関数としておく
- アーキテクチャ設計
- 基本的には従来のサーバーレスアーキテクチャにBedrockが追加されるだけ
- つまり、これまでのアプリケーション開発の延長線上に存在する
- Ambient Agent
- イベントドリブンで動くAIエージェント
- これまでのサーバーレスアプリケーションと同じ思想
ということで、最初に出てきた普遍的なサーバーレスデザインの3つの要素がここでも出てきました。
- 関数単位での設計
- ステートレス
- イベントドリブン
AI Agent開発とはアプリケーション開発と本質的には同じであり、サーバーレスデザインをベースに考えていくことで、実務でも使えるAI Agentが作れるようになっていくのではないでしょうか!
ここに追加で、LLMOpsなどをAI Agent開発特有の文脈として考える必要があると思います!
まとめ
- 普遍的なサーバーレスデザインを意識することで、Agentic AIの作成を促進できる
- GenAIの時代でもサーバーレスのデザインは生き続ける
- これから重要なのは業務ドメインをAgentに落とし込む力
- もっとコードを書こう、ソフトウェアを描こう
これからのAI Agentに活かせそうな、本質的な内容のキーノートで大変面白かったです!
付録:AgentCoreをアプリケーションに組み込むためには?
以下、淡路さんに直接ご質問させていただいた内容になります。
私の疑問:フロントエンドからAgentCoreをコールするための手法がよくわかっていません。
例えばよくあるAPI Gateway+Lambda+AgentCoreな構成にすると、
API GatewayとLambdaがAgentCoreの良さを無くしてしまう認識。
フロントエンド(Next.jsなど)からAgentCoreを直接呼ぶのも、
フロントエンドとバックエンドが分離できていない感じがして、なんとなく抵抗がある。
どうやってAgentCoreをコールするべきか?
淡路さん曰く、フロントエンドから直接呼ぶので全く問題ない、とのことでした。
従来のモバイルアプリにおいても、Cognitoでの認証+S3やDynamoDBへのデータ格納などを直接行っている。これはサーバーレスが出たときからの手法。
また、LambdaのInvokeWithResponseStream APIをフロントエンドから直接コールすることもあるそうです。
(Function URLのストリーミングレスポンスではなく、APIベースでコールするとのことでした。)
これらを踏まえて、フロントエンドからAgentCoreを直接コールする構成、というのも全く問題ないということでした。
具体的な手法としては以下資料が参考になると教えていただいたのでこちらで共有しておきます。