every Tech Blog

株式会社エブリーのTech Blogです。

AgentCore CLIを本番運用する上で詰まったポイントと対策

はじめに

今回はAgentCore CLIを使ったエージェント開発を本番運用できるかを検討した際に、複数環境のデプロイについて詰まったポイントがあったので、ご紹介させていただきます。
AgentCore CLIは2026年4月17日現在では、GA前段階のため、本記事で紹介する内容が今後変更される可能性があります。

検証に使用したエージェント構成

今回検証のために使用したエージェントの構成を簡単に紹介します。
今回はAgentCore CLIの使い方の説明が主題ではないため、使い方についての詳細は省かせていただきます。

AgentCore CLIのagentcore createコマンドで以下のようなエージェントを作成したという前提で話を進めさせていただきます。
- Project name: MyProject
- Agent name: analysis
- Type: Create new agent
- Language: Python
- Build: Direct Code Deploy
- Protocol: HTTP
- Framework: OpenAI Agents
- Advanced: defaults

コマンドを実行すると以下のような構成でファイルが生成されます。
主要なものに絞って記載していますが、実際には CDK の設定ファイルや LLM コンテキストファイルなども生成されます。

MyProject/                       # プロジェクトルート
├── AGENTS.md                    # エージェントの概要・設計ドキュメント
├── README.md                    # プロジェクトのREADME
├── agentcore/
│   ├── agentcore.json           # エージェント定義(ランタイム、Gateway、Credential等)
│   ├── aws-targets.json         # デプロイ先のAWSアカウント・リージョン
│   ├── tool-schema.json         # Gatewayターゲットのツール定義
│   ├── .env.local               # APIキー等のシークレット
│   ├── .cli/
│   │   └── deployed-state.json  # デプロイ済みリソースの状態
│   └── cdk/
│       ├── bin/cdk.ts           # CDKエントリポイント
│       └── lib/cdk-stack.ts     # CDKスタック定義
└── app/                         # エージェントのアプリケーションコード
    └── analysis/
        ├── main.py
        └── pyproject.toml

また、上記構成に含まれていませんが、今回の構成では、AgentCore CLIで作成したエージェントが Gateway 経由で、lambroll でデプロイした Lambda 関数をツールとして呼び出します。

デプロイの仕組み

agentcore deploy を実行すると、内部では以下が行われます:

  1. デプロイターゲット(aws-targets.json)の読み込み
  2. agentcore.json のバリデーション
  3. CDKプロジェクトのビルド
  4. Credential(APIキー等)のセットアップ
  5. CloudFormationテンプレートの合成(synth)
  6. CloudFormationスタックのデプロイ

CloudFormationスタックには、ランタイム、Gateway、IAMロール等のリソースがまとめて含まれます。

詰まったポイント

1. --target オプションでデプロイ先が絞り込めない

問題

AgentCore CLIでは、デプロイ先のAWSアカウント・リージョンを aws-targets.json に定義します。
dev/prodを分離するために、以下のように2つのターゲットを定義しました。

// aws-targets.json
[
  { "name": "dev", "account": "111111111111", "region": "ap-northeast-1" },
  { "name": "prod", "account": "999999999999", "region": "ap-northeast-1" }
]

agentcore deploy コマンドには --target オプションがあり、デプロイ先を指定できます。
--target dev を指定すればdev環境のみにデプロイされると期待しましたが、実際には以下のようにprodのCloudFormationスタックもdevアカウントに作成されてしまいました。

# targetをdevに指定してデプロイ
AWS_PROFILE=dev-profile agentcore deploy --target dev

実際にはdevアカウントに以下の2つのスタックが作成される
- AgentCore-MyProject-dev(意図通り)
- AgentCore-MyProject-prod(意図しない)

原因

この問題は、CLIとCDKの間でターゲット情報が連携されていないことが原因のようです。

CLIの --target オプションは、aws-targets.json からターゲット情報(account, region)を取得してIdentityのセットアップやデプロイ後の状態記録に使われますが、CDKのsynth(CloudFormationテンプレートの合成)やdeploy処理にはターゲット名が伝わりません。

agentcore create で生成される cdk.ts のデフォルトコードでは、aws-targets.json に定義された全ターゲットに対してスタックを生成するforループになっています。

// cdk.ts(デフォルト生成コード)
for (const target of targets) {
  // --target の指定に関係なく、全ターゲット分のスタックが生成される
  new AgentCoreStack(app, stackName, { ... });
}

CDKのsynthはローカルで実行されるため、アカウントIDが異なっていてもテンプレート生成自体は成功します。その結果、devアカウントのクレデンシャルで実行しているにもかかわらず、prod用のスタック定義もdevアカウントにデプロイされてしまいます。

対策

対策1:cdk.ts を修正して環境変数でフィルタ

cdk.ts に環境変数 AGENTCORE_TARGET でターゲットをフィルタするコードを追加しました。

// cdk.ts
const app = new App();

// 環境変数でターゲットをフィルタ
const targetFilter = process.env.AGENTCORE_TARGET;
const filteredTargets = targetFilter
  ? targets.filter(t => t.name === targetFilter)
  : targets;

for (const target of filteredTargets) {
  // フィルタされたターゲットのみスタックを生成
  new AgentCoreStack(app, stackName, { ... });
}

デプロイ時に環境変数を指定して実行します:

# dev環境のみデプロイ
AGENTCORE_TARGET=dev AWS_PROFILE=dev-profile agentcore deploy --target dev

# prod環境のみデプロイ
AGENTCORE_TARGET=prod AWS_PROFILE=prod-profile agentcore deploy --target prod

注意点:

  • agentcore create で新規プロジェクトを作成するたびに cdk.ts が初期状態で生成されるため、毎回この修正を適用する必要があります。
  • CLIの --target オプションの値はCDKプロセスに自動的に引き渡されないため、環境変数 AGENTCORE_TARGET として別途指定する必要があります。--target はCLI内部でのターゲット情報取得に、AGENTCORE_TARGET はCDKのsynthでのスタック絞り込みに使われるため、両方に同じ値を指定する必要があり、冗長になってしまいます。将来のCLIバージョンで改善される可能性はありますが、現時点(v0.8.0)ではこの対応が必要です。
対策2:aws-targets.json を毎回リセットしてプロファイルから自動検出

aws-targets.json を空([])にしてからデプロイすると、CLIが AWS_PROFILE からアカウントIDとリージョンを自動検出し、"default" という名前のターゲットを自動生成します。

# dev環境(aws-targets.json が空の状態で実行)
AWS_PROFILE=dev-profile agentcore deploy

# prod環境(aws-targets.json をリセットしてから実行)
echo '[]' > agentcore/aws-targets.json
AWS_PROFILE=prod-profile agentcore deploy

一見シンプルですが、実用上は問題があります。devデプロイ後に aws-targets.json にはdevターゲットが追加された状態になっています。この状態でリセットせずにprodをデプロイすると、aws-targets.json に2つのターゲットが登録され、対策1で述べたのと同じ問題(全ターゲット分のスタックがsynthされる)が発生してしまいます。

そのため、デプロイのたびに aws-targets.json をリセットする運用が必要になりますが、CI/CDを使い、 echo '[]' > agentcore/aws-targets.json を実行してからデプロイする形にすれば、毎回クリーンなワークスペースから始まるためリセット忘れは防げると思います。

対策1は agentcore create で自動生成される cdk.ts を書き換える必要があり、CLIのバージョンアップで生成内容が変わった際に手動マージが必要になったり、修正漏れで予期せぬ挙動を起こすリスクがあります。そのため、基本的には自動生成ファイルには手を入れず、対策2をCI/CDで運用するのが望ましいと考えています。

2. Lambda ARNのハードコーディング

問題

GatewayにLambda関数をターゲットとして追加するには、以下のようにコマンドを実行します。

agentcore add gateway-target \
  --gateway Gateway \
  --name DataFetcher \
  --type lambda-function-arn \
  --lambda-arn arn:aws:lambda:ap-northeast-1:111111111111:function:get-data \
  --tool-schema-file ./agentcore/tool-schema.json

./agentcore/tool-schema.json にはLambda関数が提供するツールの定義を記述したJSONファイルを指定します。
Lambda ARNターゲットの場合、Gatewayがどのツールを公開しているか知る手段がないため、このファイルを自分で用意する必要があります。

// tool-schema.json の例
{
  "tools": {
    "get-data": {
      "name": "get-data",
      "description": "分析用のデータを取得する",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "取得対象の日付"
          }
        },
        "required": ["date"]
      }
    }
  }
}

このコマンドを実行すると、agentcore.json に以下のようなGatewayターゲットが追加されます。

// agentcore.json
"agentCoreGateways": [
  {
    "name": "Gateway",
    "targets": [
      {
        "name": "DataFetcher",
        "targetType": "lambdaFunctionArn",
        "lambdaFunctionArn": {
          "lambdaArn": "arn:aws:lambda:ap-northeast-1:111111111111:function:get-data",
          "toolSchemaFile": "./agentcore/tool-schema.json"
        }
      }
    ]
  }
]

ここで問題になるのが lambdaArn の値です。Lambda ARNにはAWSアカウントIDが含まれるため、dev/prodでアカウントが異なる場合、デプロイ前に毎回この値を対象環境のARNに書き換える必要があります。

devにデプロイする場合:  arn:aws:lambda:ap-northeast-1:111111111111:function:get-data
prodにデプロイする場合: arn:aws:lambda:ap-northeast-1:999999999999:function:get-data

agentcore.json はgit管理されるファイルのため、デプロイのたびにARNを書き換えてコミットするのは手間がかかりますし、書き換え忘れにより誤った環境のARNでデプロイしてしまうリスクもあります。

対策

agentcore.json にはdev用のARNを登録しておき、cdk.ts 側で関数名だけを取り出して、ターゲットのアカウント・リージョンからARNを動的に再構築するようにしました。

// agentcore.json(dev用のARNで登録しておく)
{
  "lambdaArn": "arn:aws:lambda:ap-northeast-1:111111111111:function:get-data",
  "toolSchemaFile": "./agentcore/tool-schema.json"
}
// cdk.ts
const resolvedMcpSpec = mcpSpec ? JSON.parse(JSON.stringify(mcpSpec)) : undefined;
if (resolvedMcpSpec?.agentCoreGateways) {
  for (const gw of resolvedMcpSpec.agentCoreGateways) {
    for (const t of gw.targets ?? []) {
      if (t.lambdaFunctionArn?.lambdaArn) {
        // 元のARNから関数名を抽出し、ターゲットのアカウント・リージョンで再構築
        const functionName = t.lambdaFunctionArn.lambdaArn.split(':').pop();
        t.lambdaFunctionArn.lambdaArn =
          `arn:aws:lambda:${target.region}:${target.account}:function:${functionName}`;
      }
    }
  }
}

注意点:
cdk.tsagentcore create で新規プロジェクトを作成するたびに初期状態で生成されるため、毎回この修正を適用する必要があります。
また、前述の通り自動生成ファイルを書き換えるのはCLIのバージョンアップ等でバグを生みやすいので、CI/CDのデプロイジョブ内で agentcore.json のARNを対象環境のアカウントIDに置換してからデプロイする方が安全かなと思います。

3. APIキーをdev/prodで分けたい

問題

エージェントが外部API(OpenAI等)を利用する場合、APIキーをCredentialとして登録します。登録されたAPIキーはAgentCore Identityサービスのアウトバウンド認証(エージェントから外部サービスへの認証情報)として管理されます。

agentcore add credential --name OpenAIApiKey --api-key sk-xxxxx

このコマンドを実行すると、以下の2箇所に情報が書き込まれます。

  • agentcore/agentcore.json — Credentialのメタ情報(名前・タイプ)
  • agentcore/.env.local — APIキーの実際の値
// agentcore.json
"credentials": [
  {
    "authorizerType": "ApiKeyCredentialProvider",
    "name": "OpenAIApiKey"
  }
]

agentcore/.env.local

AGENTCORE_CREDENTIAL_OPENAIAPIKEY=sk-xxxxx

環境変数名は Credential名から AGENTCORE_CREDENTIAL_{NAME} の形式で自動生成されます。デプロイ時にこの値が読み取られ、AWS側の Token Vault(AgentCore Identityサービスのシークレットストア)に登録されます。

dev/prodで同じAPIキーを使う場合は、.env.local の値をそのまま使えるので問題ありません。しかし、セキュリティや課金管理の観点からdev/prodでAPIキーを分けたい場合、.env.local は1ファイルしかないため、デプロイのたびに値を書き換える必要があります。

対策

デプロイ時に環境変数でAPIキーを上書きします。環境変数が設定されていれば .env.local の値より優先されます。

# dev環境
AGENTCORE_CREDENTIAL_OPENAIAPIKEY=sk-dev-xxxxx \
  AGENTCORE_TARGET=dev \
  AWS_PROFILE=dev-profile \
  agentcore deploy --target dev

# prod環境
AGENTCORE_CREDENTIAL_OPENAIAPIKEY=sk-prod-xxxxx \
  AGENTCORE_TARGET=prod \
  AWS_PROFILE=prod-profile \
  agentcore deploy --target prod

ただし、毎回デプロイコマンドにAPIキーを環境変数として渡すのであれば、.env.local を直接書き換える運用と手間は変わりません。今回はCI/CDを使わずローカルからデプロイする運用のため、デプロイ前に .env.local の値を対象環境のAPIキーに書き換える方法を採用しました。

別のアプローチ:dev/prodでプロジェクトを分ける

ここまで紹介した課題は、いずれも1つのプロジェクトでdev/prodを共有することに起因しています。

これらをすべて解消するシンプルなアプローチとして、dev用とprod用でそれぞれ別のAgentCoreプロジェクトを作成する方法があります。

MyAgent-dev/
├── agentcore/
│   ├── agentcore.json    ← dev用のLambda ARN、dev用のAPIキー
│   ├── aws-targets.json  ← devアカウントのみ
│   └── cdk/
└── app/
    └── analysis/

MyAgent-prod/
├── agentcore/
│   ├── agentcore.json    ← prod用のLambda ARN、prod用のAPIキー
│   ├── aws-targets.json  ← prodアカウントのみ
│   └── cdk/
└── app/
    └── analysis/

この方法なら cdk.ts のカスタマイズは不要で、aws-targets.json にはターゲットが1つだけなのでsynthの問題も発生せず、.env.local も環境ごとに独立しています。

ただし、app/ 配下のエージェントコードが2つのプロジェクトで重複するため、ロジックを変更するたびに両方を更新する必要があります。コードの同期忘れによる環境差異が生まれるリスクもあるため、この方法を積極的に採用することはできないなと思いました。

まとめ

AgentCore CLIを使用してみて、実際に本番運用できるのかを検討しました。
CLIで必要なリソースを簡単に素早く作成できるというメリットはありますが、環境を分離するには課題が多いという検証結果になりました。
最後まで読んでいただきありがとうございました!