2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Bedrock AgentCoreにLangChainで作成したLLMをデプロイして、Lambdaから呼び出すアプリを作ってみた

Last updated at Posted at 2025-09-04

はじめに

AWSの新サービス「Amazon Bedrock AgentCore」を使って、週刊AWSの記事を自動で要約・解説して、読者のレベル(初級者・中級者)ごとにコンテンツをWebサイトで公開するシステムを構築してみました。
この記事では、AgentCoreの概要から実際の開発で遭遇した課題、そして最終的な実装まで詳しく解説します。

Strandsエージェントを使った同じようなアプリ開発に興味がある方は、こちらを参照ください。
Bedrock AgentCoreにStrandsで作成したAIエージェントをデプロイして、Lambdaから呼び出すアプリを作ってみた

完成したWebサイト

生成されたトップページと実際の記事は以下です。
気が向いたら公開しようと思います・・・
コードは整理したらGitHubを載せます。

トップページ:

image1.png

実際の記事:

image2.png

Amazon Bedrock AgentCoreとは

Amazon Bedrock AgentCoreは、エンタープライズレベルのAIエージェントを構築・デプロイするためのフルマネージドサービスです。従来のエージェント開発では、スケーリング、セキュリティ、メモリ管理、オブザーバビリティなどの運用面を個別に実装する必要がありましたが、AgentCoreはこれらの機能を統合的に提供します。

なかでも、注目すべき機能として、短期・長期メモリの管理、ID・アクセス制御の統合、MCP(Model Context Protocol)を通じたツール連携、オブザーバビリティが挙げられます。

参考:Amazon Bedrock AgentCore の紹介 – あらゆる規模で AI エージェントを安全にデプロイし、運用する

Strandsエージェントとは

Strandsは、AWSが開発したオープンソースのAIエージェントSDKです。わずか数行のコードでAIエージェントを構築・実行するモデル駆動型アプローチを採用しています。Amazon Q Developer、AWS Glue、VPC Reachability Analyzerなど、AWSの複数チームが既に本番環境で使用している実績があります。

最初はStrandsエージェントを利用しようと思っていましたが、今回の開発では後述するCPUアーキテクチャの問題により、最終的にLangChainエージェントを選択することになりました。

参考:Strands Agents – オープンソース AI エージェント SDK の紹介

LangChainエージェントとは

LangChainは、大規模言語モデルを活用したアプリケーション開発のためのフレームワークです。エージェント機能では、LLMが自律的にツールを選択・実行し、複雑なタスクを段階的に解決できます。豊富なツール連携機能と柔軟なカスタマイズ性が特徴で、今回のプロジェクトでは記事の取得から要約生成まで一連の処理を自動化するために活用しました。

今回は処理として、推論、ツール利用が必要ではないので、実際はただのLLM呼び出しのコードになっています。

システム構成

構築したシステムは以下の構成になっています。
Lambda関数が週刊AWSのRSSフィードを取得し、AgentCoreにデプロイしたLangChainエージェントを呼び出して記事を要約します。生成された要約は初心者・中級者向けに分けられ、HTMLページとしてS3に保存されます。EventBridgeによる定期実行とDynamoDBでの既読管理により、新しい記事のみを自動処理します。最終的にCloudFrontを通じて静的サイトとして配信されます。

AgentCore Memoryについては、Short-term Memory と Long-term Memoryの二つがあり、その特徴は以下のようです。

今回のユースケースとして、Short-term が利用できるかと思いましたが、Short term memoryでは、実際、同一セッション/アクターの会話履歴が保存されるため、合わないと思い、DynamoDBを利用しました。

  • Short:Short-term Memoryは、セッション中の会話履歴を保持する機能
  • Long:Long-term Memoryは、Short-term Memoryから自動的に重要な情報を抽出・統合する機能

参考:[Amazon Bedrock AgentCore]Memory機能で会話履歴を記憶するエージェントを実装してみた

アーキテクチャ図

  • Lambda: RSS取得・要約・HTML生成・S3アップロード
  • EventBridge: 毎週月曜・火曜12時に実行
  • DynamoDB: 既読記事管理
  • S3: 静的サイトホスティング
  • CloudFront: CDN配信
  • AgentCore + LangChain Agent: 記事要約生成(対象読者別カスタマイズ機能付き)

開発でハマった課題

CPUアーキテクチャの違いによる問題

開発はCloudShellで進めていましたが、CPUアーキテクチャの違いが問題でした。CloudShellはx86_64アーキテクチャで実行されていますが、AgentCoreはコンテナをARM64アーキテクチャで実行することを要求します。

⚠️ [WARNING] Platform mismatch: Current system is 'linux/amd64' but Bedrock AgentCore requires 'linux/arm64'.

StrandsからLangChainへの変更

当初はStrandsエージェントを使用する予定で、上記の問題を解決するためDocker Buildxを使用してクロスビルドを実行しましたが、ARM64環境でのビルドに失敗しました。CodeBuildのログを確認すると、Strandsライブラリ自体がARM64アーキテクチャに対応していないことが判明しました。そこで、LangChainエージェントに切り替えることにしました。

CodeBuildでのエラー確認

AgentCoreのデプロイはCodeBuildで実行されるため、上記のようなエラーが発生した際はCodeBuildコンソールでログを確認することができます。

要約が途中で切れる問題の調査と解決

テスト中、生成された記事が途中で切れてしまう問題が発生しました。原因を特定するため、Bedrockが何をインプット・アウトプットしているのか、エージェントの処理内容を詳しく確認するため、Bedrockコンソールの設定からモデル呼び出しログを有効化しました。

※AgentCoreのObservavlity機能では、上記も確認できます。(構築後に気づきました)
※そのため、Bedrockをモデルに利用していなくても、確認できるので便利です。

ログを確認した結果、問題の原因は出力トークンの上限設定であることが判明しました。モデルの設定を調整して十分なトークン数を確保することで、この問題を解決しました。

タイムアウト問題

他にもboto3、botocoreでタイムアウトが発生しました。boto3、botocoreはデフォルトで60秒のタイムアウトが設定されていて、長い記事の要約処理が完了前に中断されてしまいました。

Read timeout on endpoint URL: "https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/arn%3Aaws%3Abedrock-agentcore%3Aus-west-2%3A622632352793%3Aruntime%2Fweekly_aws_summary_agent-aeU9lkEVOl/invocations"

そのため、Configオブジェクトでread_timeoutパラメーターを1800秒(30分)に延長することで解決しました。このタイムアウト設定は、以下の二つで必要でした:

  1. LambdaからAgentCoreへの呼び出し(AgentCoreタイムアウト)
  2. AgentCore内でBedrockへの呼び出し(Bedrockタイムアウト)

再ローンチの必要性

開発中、エージェントの設定変更後に期待通りの動作をしない場合がありました。このような場合は、agentcore launchコマンドで再デプロイすることで問題が解決することが多くありました。

AgentCoreにデプロイするLangChainエージェントの実装

AgentCoreにデプロイするLangChainエージェントは、BedrockAgentCoreAppを使用してエントリポイントを定義し、ChatBedrockでClaude 3.7 Sonnetを呼び出します。

from bedrock_agentcore.runtime import BedrockAgentCoreApp
from langchain_aws import ChatBedrock
from langchain.schema import HumanMessage
from botocore.config import Config

app = BedrockAgentCoreApp()

@app.entrypoint
def invoke(payload):
    # ペイロードからプロンプトと対象読者を取得
    content = payload.get("prompt", "Hello")
    audience = payload.get("audience", "初心者")
    
    # AgentCore内でのBedrock呼び出しタイムアウトを1800秒(30分)に延長
    config = Config(read_timeout=1800)
    
    # Claude 3.7 Sonnetを使用してLLMクライアントを作成
    llm = ChatBedrock(
        model_id="us.anthropic.claude-3-7-sonnet-20250219-v1:0",
        region_name="us-west-2",
        model_kwargs={"max_tokens": 8192},  # 出力トークン上限を8192に設定
        config=config
    )
    
    # 対象読者別のスタイル定義
    prompts = {
        "初心者": "専門用語を避け、基本概念から丁寧に説明",
        "中級者": "実用的な観点で、導入方法や注意点を重視"
    }
    
    style = prompts.get(audience, prompts["初心者"])
    
    # 要約用プロンプトを作成
    prompt = f"""AWS記事を{audience}向けに要約してください。
スタイル: {style}

記事内容: {content}"""
    
    # LLMを呼び出して要約を生成
    message = HumanMessage(content=prompt)
    result = llm.invoke([message])
    
    return {"result": result.content}

if __name__ == "__main__":
    app.run()

LambdaからAgentCoreを呼び出す実装

LambdaからAgentCoreのエージェントを呼び出す実装では、boto3クライアントを使用してエージェントランタイムAPIを呼び出します。

def call_agentcore_agent(content, audience):
    # タイムアウトをデフォルトの60秒から1800秒(30分)に延長
    config = Config(read_timeout=1800)
    bedrock_agentcore = boto3.client('bedrock-agentcore', config=config)
    
    # コンテンツと対象読者でユニークなセッションIDを生成
    session_id = f'session_{hashlib.md5(f"{content}_{audience}".encode()).hexdigest()}'
    
    # エージェントに送信するペイロードを作成
    payload = json.dumps({
        "prompt": content,
        "audience": audience
    }).encode()
    
    # AgentCoreエージェントを呼び出し
    response = bedrock_agentcore.invoke_agent_runtime(
        agentRuntimeArn=os.environ['AGENTCORE_ARN'],
        runtimeSessionId=session_id,
        payload=payload
    )
    
    # レスポンスをパースして結果を返却
    response_body = response['response'].read()
    response_data = json.loads(response_body)
    return response_data.get('result', '要約生成に失敗しました')

デプロイ手順

システムのデプロイは3つのステップで実行します。まずAgentCoreにエージェントをデプロイし、次にCloudFormationでAWSリソースを作成し、最後にLambda関数を更新します。

AgentCoreエージェントのデプロイ

CloudShellで以下のコマンドを実行し、LangChainエージェントをAgentCoreにデプロイします。

# Python 3.10以上が必要なため、CloudShellでPython 3.12をインストール
sudo yum install python3.12 -y
sudo ln -sf /usr/bin/python3.12 /usr/bin/python3
python3 --version

# 仮想環境の作成とツールキットのインストール
python3 -m venv agentcore-env
source agentcore-env/bin/activate
pip install --upgrade pip
pip install bedrock-agentcore-starter-toolkit

# エージェントの設定とデプロイ
agentcore configure --entrypoint agentcore.py --name <agent-name>
docker buildx create --use
agentcore launch

AWSリソースのデプロイ

AWSコンソールからCloudFormationテンプレート(infrastructure.yaml)をデプロイし、Lambda、S3、DynamoDBなどのリソースを作成します。

Lambda関数の更新

依存ライブラリを含めたLambdaパッケージを作成し、関数を更新します。

# パッケージの作成とデプロイ
mkdir lambda-package
cp lambda_function.py lambda-package/
cp lambda-requirements.txt lambda-package/requirements.txt
cd lambda-package
pip install -r requirements.txt -t .
zip -r ../lambda-package.zip .
cd ..

aws lambda update-function-code \
  --function-name <function-name> \
  --zip-file fileb://lambda-package.zip

動作確認

デプロイ完了後、以下のコマンドでシステムの動作を確認できます。EventBridgeスケジュールは毎週月曜・火曜12時に自動実行されますが、手動でもテスト可能です。

# エージェントの処理が長いため非同期実行(バックグラウンドで実行)
aws lambda invoke \
  --function-name <function-name> \
  --invocation-type Event \
  --payload '{}' \
  response.json

# ログのリアルタイム監視
aws logs tail /aws/lambda/<function-name> --follow

まとめ

Amazon Bedrock AgentCoreを使用したエージェントアプリケーションの開発は、今後AIエージェントを開発するにあたって、多くの学びがありました。特にCPUアーキテクチャの違いやタイムアウト時間、トークン数など、実際の開発でしか遭遇しない課題を通じて、AgentCore、Bedrcokの特性をより深く理解できました。

今回のエージェントは、実際にはLLM呼び出しであり、今後はもっとエージェントとなるものを実装し、メモリ機能やゲートウェイ機能の活用、より複雑なマルチエージェント構成の実装など、AgentCoreの高度な機能を実装していきたいと思います。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?