47
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amplify & AgentCoreのAIエージェントをAWS CDKでデプロイしよう!

Last updated at Posted at 2026-01-06

1/14更新: AgentCoreランタイムの名前に利用不可な文字が入ってしまい、デプロイ失敗する可能性があったため、 resource.ts を修正しました🙏

先日投稿したこちらの記事が好評だったため、AWS CDKを使ってフルIaCでデプロイする手順も解説します!

フルサーバーレスで維持費激安なのが嬉しいポイントです。

スクリーンショット 2026-01-06 18.02.56.png

モダンな汎用AIエージェントWebアプリをすぐデプロイできるので、画面デザインやAIエージェントの設定を少しいじるだけで、色んなバリエーションを簡単に量産することができます。

見飽きたStreamlitの画面は、もう卒業!

スクリーンショット 2026-01-02 1.54.49.png

以下のコードをフォークすれば秒でデプロイできるのですが、初心者は一から自分で開発した方が理解がグッと進みますので、以下手順で一緒にハンズオンしてみましょう。

事前準備

アカウント作成

  • AWSアカウントを作成

  • GitHubアカウントを作成

Claudeの利用申請

  • AWSアカウントにサインイン(https://console.aws.amazon.com
    • リージョンを東京に変更
  • Claudeモデルの利用申請
    • Amazon Bedrockを検索 > チャット/テキストのプレイグラウンド
    • モデルを選択 > Anthropic > Claude Haiku 4.5 > 適用
    • フォームが出てきたら記入して送信(数分待つ)
    • プレイグラウンドでHaikuとチャットできたらOK

このあとのAWS CLI認証で使うので、AWSマネコンにはサインインしたままにしておいてください。

1. ベースプロジェクトの作成

この部分がAmplifyの公式テンプレートとして用意されています。

スクリーンショット 2026-01-06 18.09.01.png

テンプレートから環境作成

  • Amplifyのクイックスタートにアクセス

  • テンプレからGitHubリポジトリを作成
    • クイックスタート内「Create repositry from template」をクリック
    • Repository name: cdk-agent
    • Choose visibility: Private
  • 開発環境を起動
    • Code > Codespaces > Create codespace on main

スクリーンショット 2026-01-01 23.12.44.png

AWS認証設定

起動したコードスペースのターミナルで以下を実行します。

  • AWS CLIをインストール
# ダウンロード
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

# 解答
unzip awscliv2.zip

# インストール
sudo ./aws/install

# ゴミ掃除
rm -rf aws awscliv2.zip
  • AWS認証を行う
aws login --remote
  • リージョンを聞かれたら ap-northeast-1 と入力
    • URLにアクセスして既存セッションを選択
    • 検証コードをコピーして、ターミナルに貼り付ける

不要ファイルの削除

フロントエンドはとにかくファイルが大量生成されるのでとっつきにくいですよね。
極限まで不要なファイル・コードを削りながら、認知負荷削減を工夫します。

  • 不要なファイルとディレクトリの削除
# ルート階層の不要ファイルを削除
rm -rf .eslintrc.cjs *.md LICENSE

# 不要なディレクトリや、各階層のファイルを削除
rm -rf amplify/data public src/assets

現状のディレクトリ構成は以下です。

/cdk-agent
├── amplify #バックエンドとインフラ
├── src #フロントエンド
└── ファイルいろいろ #各種設定ファイルなど

ややこしいですが、Amplify用語で出てくる「バックエンド」という表現は、アプリケーションのバックエンドコードだけでなく、それらの稼働に必要な各種AWSインフラサービス(LambdaやDB系など)も含んでいます。

2. フロントエンドの開発

ここを作ります。

スクリーンショット 2026-01-06 18.06.30.png

フロントエンドのメインコードは src 配下にあります。

/cdk-agent
├── amplify
├── src
│   ├── App.css # CSS(メインアプリ用)
│   ├── App.tsx # Reactのメインアプリ
│   ├── index.css # CSS(共通)
│   ├── main.tsx # Reactのエントリーポイント
│   └── vite-env.d.ts
└── ファイルいろいろ
  • 以下ファイルをこの内容で上書きします(Reactのエントリーポイント)
src/main.tsx
// 必要なパッケージをインポート
import React from "react";
import ReactDOM from "react-dom/client";
import { Amplify } from "aws-amplify";
import { Authenticator } from '@aws-amplify/ui-react';
import { I18n } from 'aws-amplify/utils';
import { translations } from '@aws-amplify/ui-react';
import App from "./App.tsx";
import outputs from "../amplify_outputs.json";
import '@aws-amplify/ui-react/styles.css';
import "./index.css";

// Amplifyの初期化
Amplify.configure(outputs);

// 認証画面を日本語化
I18n.putVocabularies(translations);
I18n.setLanguage('ja');

// アプリケーションのエントリーポイント(認証付きでレンダリング)
ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <Authenticator>
      <App />
    </Authenticator>
  </React.StrictMode>
);

  • 以下ファイルをこの内容で上書きします(共通CSS)
src/index.css
/* ボックスモデルの統一 */
* { box-sizing: border-box; }

/* ボディの基本設定 */
body {
  margin: 0;
  background: #fafbfc;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ルート要素(フルスクリーン) */
#root {
  height: 100vh;
  width: 100vw;
}

  • 以下ファイルをこの内容で上書きします(Reactのメインアプリ)
src/App.tsx(長いので折りたたみ)
src/App.tsx
// 必要なパッケージをインポート
import { useState, useRef, useEffect, type FormEvent } from 'react';
import { fetchAuthSession } from 'aws-amplify/auth';
import ReactMarkdown from 'react-markdown';
import './App.css';
import outputs from '../amplify_outputs.json';

// Amplify outputs から設定を取得
const AGENT_ARN = outputs.custom?.agentRuntimeArn;

// チャットメッセージの型定義
interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  isToolUsing?: boolean;
  toolCompleted?: boolean;
  toolName?: string;
}

// メインのアプリケーションコンポーネント
function App() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);
  const messagesEndRef = useRef<HTMLDivElement>(null);

  // メッセージ追加時に自動スクロール
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  // フォーム送信処理
  const handleSubmit = async (e: FormEvent) => {
    e.preventDefault();
    if (!input.trim() || loading) return;

    // ユーザーメッセージを作成
    const userMessage: Message = { id: crypto.randomUUID(), role: 'user', content: input.trim() };

    // メッセージ配列に追加(ユーザー発言 + 空のAI応答)
    setMessages(prev => [...prev, userMessage, { id: crypto.randomUUID(), role: 'assistant', content: '' }]);
    setInput('');
    setLoading(true);

    // Cognito認証トークンを取得
    const session = await fetchAuthSession();
    const accessToken = session.tokens?.accessToken?.toString();

    // AgentCore Runtime APIを呼び出し
    const url = `https://bedrock-agentcore.ap-northeast-1.amazonaws.com/runtimes/${encodeURIComponent(AGENT_ARN)}/invocations?qualifier=DEFAULT`;
    const res = await fetch(url, {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({ prompt: userMessage.content }),
    });

    // SSEストリーミングを処理
    const reader = res.body!.getReader();
    const decoder = new TextDecoder();
    let buffer = '';
    let isInToolUse = false;
    let toolIdx = -1;

    // ストリームを読み続ける
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      // 受信データを行ごとに処理
      for (const line of decoder.decode(value, { stream: true }).split('\n')) {
        if (!line.startsWith('data: ')) continue;
        const data = line.slice(6);
        if (data === '[DONE]') continue;
        const event = JSON.parse(data);

        // ツール使用開始イベント
        if (event.type === 'tool_use') {
          isInToolUse = true;
          const savedBuffer = buffer;
          setMessages(prev => {
            const msgs = [...prev];
            if (savedBuffer) {
              msgs[msgs.length - 1] = { ...msgs[msgs.length - 1], content: savedBuffer };
              toolIdx = msgs.length;
              msgs.push({ id: crypto.randomUUID(), role: 'assistant', content: '', isToolUsing: true, toolName: event.tool_name });
            } else {
              toolIdx = msgs.length - 1;
              msgs[msgs.length - 1] = { ...msgs[msgs.length - 1], isToolUsing: true, toolName: event.tool_name };
            }
            return msgs;
          });
          buffer = '';
          continue;
        }

        // テキストイベント(AI応答本文)
        if (event.type === 'text' && event.data) {
          if (isInToolUse && !buffer) {
            // ツール実行後の最初のテキスト → ツールを完了状態に
            const savedIdx = toolIdx;
            setMessages(prev => {
              const msgs = [...prev];
              if (savedIdx >= 0 && savedIdx < msgs.length) msgs[savedIdx] = { ...msgs[savedIdx], toolCompleted: true };
              msgs.push({ id: crypto.randomUUID(), role: 'assistant', content: event.data });
              return msgs;
            });
            buffer = event.data;
            isInToolUse = false;
            toolIdx = -1;
          } else {
            // 通常のテキスト蓄積(ストリーミング表示)
            buffer += event.data;
            setMessages(prev => {
              const msgs = [...prev];
              msgs[msgs.length - 1] = { ...msgs[msgs.length - 1], content: buffer, isToolUsing: false };
              return msgs;
            });
          }
        }
      }
    }
    setLoading(false);
  };

  // チャットUI(ヘッダー+チャットエリア+入力フォーム)
  return (
    <div className="container">
      <header className="header">
        <h1 className="title">フルサーバーレスなAIエージェントアプリ</h1>
        <p className="subtitle">AmplifyとAgentCoreで構築しています</p>
      </header>

      <div className="message-area">
        <div className="message-container">
          {messages.map(msg => (
            <div key={msg.id} className={`message-row ${msg.role}`}>
              <div className={`bubble ${msg.role}`}>
                {msg.role === 'assistant' && !msg.content && !msg.isToolUsing && (
                  <span className="thinking">考え中…</span>
                )}
                {msg.isToolUsing && (
                  <span className={`tool-status ${msg.toolCompleted ? 'completed' : 'active'}`}>
                    {msg.toolCompleted ? '' : ''} {msg.toolName}
                    {msg.toolCompleted ? 'ツールを利用しました' : 'を利用中...'}
                  </span>
                )}
                {msg.content && !msg.isToolUsing && <ReactMarkdown>{msg.content}</ReactMarkdown>}
              </div>
            </div>
          ))}
          <div ref={messagesEndRef} />
        </div>
      </div>

      <div className="form-wrapper">
        <form onSubmit={handleSubmit} className="form">
          <input value={input} onChange={e => setInput(e.target.value)} placeholder="メッセージを入力..." disabled={loading} className="input" />
          <button type="submit" disabled={loading || !input.trim()} className="button">
            {loading ? '⌛️' : '送信'}
          </button>
        </form>
      </div>
    </div>
  );
}

export default App;

  • 以下ファイルをこの内容で上書きします(メインアプリ用CSS)
src/App.css(長いので折りたたみ)
src/App.css
/* タイトルバー(フォームと同じテイスト) */
.header {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  text-align: center;
  padding: 16px 24px;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
}
.title { font-size: 1.25rem; font-weight: 600; margin: 0; }
.subtitle { font-size: 0.85rem; opacity: 0.9; margin: 4px 0 0; }

/* コンテナ */
.container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100%;
  background: #fafbfc;
}

/* メッセージ表示エリア */
.message-area {
  flex: 1;
  overflow: auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
}

.message-container {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

/* メッセージ行 */
.message-row {
  display: flex;
  margin-bottom: 12px;
}
.message-row.user { justify-content: flex-end; }
.message-row.assistant { justify-content: flex-start; }

/* メッセージバブル */
.bubble {
  max-width: 80%;
  padding: 12px 16px;
  border-radius: 16px;
  line-height: 1.5;
  font-size: 0.95rem;
}
.bubble.user {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.25);
}
.bubble.assistant {
  background: #fff;
  color: #374151;
  border: 1px solid #e5e7eb;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

/* 思考中・ツール使用中 */
.thinking { color: #9ca3af; font-style: italic; }
.tool-status { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; }
.tool-status.active { color: #667eea; }
.tool-status.completed { color: #10b981; }

/* 入力フォーム */
.form-wrapper {
  background: white;
  border-top: 1px solid #e5e7eb;
  padding: 16px 24px;
}
.form {
  display: flex;
  gap: 12px;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}
.input {
  flex: 1;
  padding: 12px 16px;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  font-size: 0.95rem;
  outline: none;
}
.input:focus {
  border-color: #667eea;
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.button {
  padding: 12px 28px;
  border-radius: 12px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  border: none;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
}
.button:hover { transform: translateY(-1px); }
.button:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }

実務では src ディレクトリ内を階層化して、コードをさらに分割することが多いと思います。今回は初学者でもコードを読みやすいよう、一つのメインスクリプトにReactコンポーネントをまとめています。

3. バックエンドとインフラの開発

ここを作ります。

スクリーンショット 2026-01-06 18.07.56.png

バックエンドとインフラのコードは amplify 配下にあります。

デフォルトでは、Amplifyの標準バックエンドを使って認証機能が組み込まれています。

/cdk-agent
├── src
├── amplify
│   ├── auth
│   │   └── resource.ts # 認証機能のコード
│   ├── backend.ts # Amplifyバックエンドのエントリーポイント
│   ├── package.json # Amplify用のNode.jsパッケージ定義
│   └── tsconfig.json # Amplify用のTypeScript設定
└── ファイルいろいろ

今回はAIエージェント用のカスタムリソースをAmplifyバックエンドに追加していきます。
バックエンドアプリ(Python)とインフラ(CDK)を同じディレクトリ内にまとめます。

バックエンドの開発(Python)

  • Amplifyバックエンド内に agent ディレクトリを作成
# ディレクトリを作成
mkdir amplify/agent

# 新規ファイルを作成
touch amplify/agent/app.py
touch amplify/agent/Dockerfile
touch amplify/agent/requirements.txt
  • AIエージェント本体のコードを作成
amplify/agent/app.py
# 必要なライブラリをインポート
from strands import Agent
from strands_tools.rss import rss
from bedrock_agentcore.runtime import BedrockAgentCoreApp

# AgentCoreランタイム用のAPIサーバーを作成
app = BedrockAgentCoreApp()


def convert_event(event) -> dict | None:
    """Strandsのイベントをフロントエンド向けJSON形式に変換"""
    try:
        if not hasattr(event, 'get'):
            return None

        inner_event = event.get('event')
        if not inner_event:
            return None

        # テキスト差分を検知
        content_block_delta = inner_event.get('contentBlockDelta')
        if content_block_delta:
            delta = content_block_delta.get('delta', {})
            text = delta.get('text')
            if text:
                return {'type': 'text', 'data': text}

        # ツール使用開始を検知
        content_block_start = inner_event.get('contentBlockStart')
        if content_block_start:
            start = content_block_start.get('start', {})
            tool_use = start.get('toolUse')
            if tool_use:
                tool_name = tool_use.get('name', 'unknown')
                return {'type': 'tool_use', 'tool_name': tool_name}

        return None
    except Exception:
        return None


# エージェント呼び出し関数を、APIサーバーのエントリーポイントに設定
@app.entrypoint
async def invoke_agent(payload, context):

    # フロントエンドで入力されたプロンプトを取得
    prompt = payload.get("prompt")

    # AIエージェントを作成
    agent = Agent(
        model="jp.anthropic.claude-haiku-4-5-20251001-v1:0",
        system_prompt="aws.amazon.com/about-aws/whats-new/recent/feed からRSSを取得して",
        tools=[rss]
    )

    # エージェントの応答をストリーミングで取得
    async for event in agent.stream_async(prompt):
        converted = convert_event(event)
        if converted:
            yield converted


# APIサーバーを起動
if __name__ == "__main__":
    app.run()

Strands Agentsを使った基本的なAIエージェントです。
モデルやシステムプロンプト、ツールを変更すれば、あなたの好きな機能を追加することができます。

  • AIエージェントのコンテナ定義を作成
amplify/agent/Dockerfile
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
WORKDIR /app

# 環境変数
ENV UV_SYSTEM_PYTHON=1 \
    UV_COMPILE_BYTECODE=1 \
    UV_NO_PROGRESS=1 \
    PYTHONUNBUFFERED=1 \
    DOCKER_CONTAINER=1 \
    AWS_REGION=ap-northeast-1 \
    AWS_DEFAULT_REGION=ap-northeast-1

# 依存関係のインストール
COPY requirements.txt requirements.txt
RUN uv pip install -r requirements.txt
RUN uv pip install aws-opentelemetry-distro==0.12.2

# 非rootユーザー作成
RUN useradd -m -u 1000 bedrock_agentcore
USER bedrock_agentcore

EXPOSE 8080
EXPOSE 8000

# アプリケーションコードをコピー
COPY . .

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/ping || exit 1

CMD ["opentelemetry-instrument", "python", "-m", "app"]
  • AIエージェントに必要なPythonライブラリを定義
amplify/agent/requirements.txt
botocore
bedrock-agentcore

strands-agents
strands-agents[otel]
strands-agents-tools[rss]

インフラの開発(AWS CDK)

残るはインフラです。AWS CDK(TypeScript)を使います。

agent ディレクトリ内にAgentCore用のCDKコードを作成し、それを amplify ディレクトリ直下のバックエンド定義ファイル(CDKベース)にも反映します。

/cdk-agent
├── src
├── amplify
│   ├── agent
│   │   ├── Dockerfile
│   │   ├── app.py
│   │   ├── requirements.txt
│   │   └── resource.ts # AIエージェントのCDKコード
│   ├── auth
│   │   └── resource.ts
│   ├── backend.ts # Amplifyバックエンド全体のコード
│   ├── package.json
│   └── tsconfig.json
└── ファイルいろいろ
  • AgentCore用のCDKコードを作成
touch amplify/agent/resource.ts
  • AgentCoreランタイムと、必要な関連AWSリソースを作成
amplify/agent/resource.ts
import { Stack } from 'aws-cdk-lib';
import * as agentcore from '@aws-cdk/aws-bedrock-agentcore-alpha';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
import { ContainerImageBuild } from 'deploy-time-build';
import { IUserPool, IUserPoolClient } from 'aws-cdk-lib/aws-cognito';
import * as path from 'path';
import { fileURLToPath } from 'url';

// 指定されたCDKスタックに、AgentCoreランタイム関連のリソース一式を作成する関数
export function createAgentCoreRuntime(
  stack: Stack,
  userPool: IUserPool,
  userPoolClient: IUserPoolClient
) {
  // CodeBuildでARM64イメージをビルド(deploy-time-buildを利用)
  const agentImage = new ContainerImageBuild(stack, 'AgentImage', {
    directory: path.dirname(fileURLToPath(import.meta.url)),
    platform: Platform.LINUX_ARM64,
  });

  // スタック名から環境識別子を抽出(英数字とアンダースコアのみ許可)
  const stackNameParts = stack.stackName.split('-');
  const rawEnvId = stackNameParts.length >= 4 ? stackNameParts[3] : stack.stackName.slice(-10);
  const envId = rawEnvId.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();

  // AgentCoreランタイムを作成(L2コンストラクト利用)
  const runtime = new agentcore.Runtime(stack, 'UpdateCheckerRuntime', {
    runtimeName: `update_checker_${envId}`,
    agentRuntimeArtifact: agentcore.AgentRuntimeArtifact.fromEcrRepository(
      agentImage.repository,
      agentImage.imageTag
    ),
    // AgentCore Identityでインバウンド認証を設定
    authorizerConfiguration: agentcore.RuntimeAuthorizerConfiguration.usingCognito(
      userPool,
      [userPoolClient],
    ),
    networkConfiguration: agentcore.RuntimeNetworkConfiguration.usingPublicNetwork(),
  });

  // Bedrock APIの利用権限を追加
  runtime.addToRolePolicy(
    new iam.PolicyStatement({
      actions: [
        'bedrock:InvokeModel',
        'bedrock:InvokeModelWithResponseStream'
      ],
      resources: [
        'arn:aws:bedrock:*::foundation-model/*',
        'arn:aws:bedrock:*:*:inference-profile/*',
      ],
    })
  );

  return { runtime };
}

  • 以下ファイルをこの内容で上書きします(Amplifyバックエンド定義)
amplify/backend.ts
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { createAgentCoreRuntime } from './agent/resource';

// Amplify標準バックエンドのうち、認証機能を利用
const backend = defineBackend({
  auth,
});

// AgentCore(Amplify標準外)用のCDKスタックを作成
const agentCoreStack = backend.createStack('AgentCoreStack');

// AgentCoreランタイムのリソースを作成
const { runtime } = createAgentCoreRuntime(
  agentCoreStack,
  backend.auth.resources.userPool,
  backend.auth.resources.userPoolClient
);

// ランタイムARNを出力に追加
backend.addOutput({
  custom: {
    agentRuntimeArn: runtime.agentRuntimeArn,
  },
});

4. AWSへのデプロイ

作ったものをまとめてAmplifyにデプロイします。

スクリーンショット 2026-01-06 18.02.56.png

  • 追加で必要なパッケージを登録
npm install react-markdown
npm install aws-cdk@latest aws-cdk-lib@latest
npm install @aws-cdk/aws-bedrock-agentcore-alpha@latest
npm install deploy-time-build
npm install -D @types/node
npm pkg set "overrides.@aws-sdk/client-cloudformation"="3.936.0"
  • CDKのブートストラップ(初期設定)を実施
# AWSアカウントIDを確認
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

# CDKブートストラップ実行
npx cdk bootstrap aws://$ACCOUNT_ID/ap-northeast-1

GitHubリポジトリへプッシュ

  • コードスペース左側の「ソース管理」パネルを開く
    • コミットメッセージ「フロント開発完了」と入力して「コミット」
    • 「すべての変更をステージして、直接コミットしますか?」>「はい」
    • 「変更の同期」>「OK」

GitHubリポジトリへコードを置いておけば、この後の手順でそのリポジトリを指定するだけでAmplifyにデプロイできます。超便利!

Amplifyへデプロイ

  • AWSマネコンでAmplifyを検索してアクセス > 新しいアプリを作成
    • GitHubを選択して「次へ」
    • GitHubの認証ポップアップが出たら、画面に従って操作を行う
    • リポジトリ cdk-agentmain ブランチを選択して「次へ」
    • そのまま「次へ」>「保存してデプロイ」して8分ほど待つ

スクリーンショット 2026-01-02 1.34.49.png

今回作成したフロントエンド+バックエンド+インフラがすべて自動でデプロイされます。便利!

コードを更新してGitHubにプッシュすれば、自動で再デプロイされるCI/CD機能付きです。

AgentCoreランタイムのARNがフロントエンドにビルドされるため、アプリの利用者がブラウザで開発者ツールなどを使うとARNが見えてしまうことがあります。

ARNにはAWSアカウントIDが含まれるため、機密情報とまではいきませんがご留意のうえ利用ください。

5. 動作確認

  • Amplifyから発行された「ドメイン」URLにアクセスして、「Create Account」

スクリーンショット 2026-01-02 1.43.05.png

  • 「先週のAWSアップデートをサマリーして」などと頼んでみましょう!

スクリーンショット 2026-01-02 1.54.49.png

AIエージェントは、推論しながら何度もツールを使ったりして自律的に行動するため、途中経過をユーザーにリアルタイム表示することが重要です。

極力シンプルなコードで、ツール利用状況の表示やテキストのストリーミングに対応させています!

余裕があれば

Amplifyサンドボックスを使ってみよう

なんと、ローカル開発時に自分専用の一時バックエンドを作成できる機能があります!

スクリーンショット 2026-01-06 18.16.09.png

  • コードスペースのローカル環境に、必要なパッケージをインストール
# package.json の内容をインストール
npm install
  • Amplifyのローカル開発用バックエンドを起動
npx ampx sandbox
  • 4分ほど待ち、以下メッセージが表示されたらデプロイ完了
5:41:03 PM ✔ Deployment completed in 180.956 seconds
5:41:03 PM [Sandbox] Watching for file changes...
5:41:04 PM File written: amplify_outputs.json

自分専用のバックエンドAWSリソースが一時的に作成されます。ハイテク!

  • 新しいターミナルを開き、フロントエンドをローカル起動
npm run dev
  • コードスペース右下のポップアップから「ブラウザーで開く」

コードスペースのプレビュー機能がうまく開かずIDE画面に戻されてしまうときは、ターミナルに表示されているローカルURLを Crtl + クリック

ローカルで開発を行いながら、コードを編集するたびにバックエンドやインフラも自動更新されます。これは便利。

ブランチ連動で環境構築してみよう

なんと、新しいブランチを作るだけで環境も合わせて作ってくれます!

スクリーンショット 2026-01-06 18.20.26.png

  • Amplifyコンソールでブランチの自動検出を有効化
    • アプリケーションの設定 > ブランチ設定 > 編集
      • 「パターンセットに一致する Amplify にブランチを自動的に接続します。」にチェックして保存

スクリーンショット 2026-01-06 17.32.17.png

  • 好きな新規ブランチを作成してプッシュ
git switch -c dev
git push

自動で新環境がデプロイされます!便利!

おまけ

今回のサンプルコードはこちら

次のステップ

AgentCoreのメモリーやオブザーバビリティなど、他の機能をStrandsと組み合わせて活用してみたい方はこちら!

AIエージェント構築にちゃんと入門してみたくなった人は、こちらもぜひ!

image.png

47
29
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
47
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?