はじめに
「エージェントが残高照会もせずいきなり送金してしまわないか」
「同じセッションで送金を連打されたら」
こうした実行順序やリクエスト回数を縛りたい場面は多いのに、これまでの AgentCore Policy(Cedarベースの認可)は今来たリクエスト単体しか見られず、制御はエージェント側の実装任せでした。
2026年8月6日、Amazon Bedrock AgentCore に
Temporal Policies(セッションの行動履歴を条件にできる認可ポリシー)とRate Limiting(Gatewayレベルのトラフィック制御)
が追加されました。
Temporal Policies / Rate Limiting
Temporal Policies
Temporal Policies は「このセッションで過去に何をしたか」を条件にできる認可ルールです。
これまでの AgentCore Policy は、今来たリクエストの中身だけを見て許可・拒否を決めていました。
「残高照会した後でなければ送金できない」のようなルールはポリシー側では表現できず、エージェント自身のコードで「照会済みフラグ」を管理するしかありませんでした。
Temporal Policies を使うと、こうしたルールをエージェントのコードを一切変更せずにポリシーとして宣言できます。
Rate Limiting
Rate Limiting は Gateway を通るトラフィックの量そのものを制限するインフラ的な防御です。
呼び出し元・ツール・モデルといった単位でリクエスト数やトークン消費量に上限を設定でき、超えたリクエストは弾かれます。
やってみた
CLI
- agentcore CLI(v0.26.0)
- AWS CLI(2.36 系)
Lambda 関数
検証用に送金の擬似 API を持つ Lambda 関数「FundsTarget」を用意します。
def lambda_handler(event, context):
# ツール名は "ターゲット名___ツール名" 形式で context.client_context.custom に渡ってくる
tool_name = context.client_context.custom["bedrockAgentCoreToolName"].split("___")[-1]
if tool_name == "get_account_balance":
return {"status": "ok", "customerId": event.get("customerId"), "accountId": "acct-1001", "balance": 5000}
if tool_name == "transfer_funds":
return {"status": "ok", "fromAccount": event.get("fromAccount"),
"toAccount": event.get("toAccount"), "amount": event.get("amount")}
手順1: Gateway・Lambda Target・Policy Engine の構築
# AgentCore プロジェクト作成
agentcore create --project-name TemporalDemo --no-agent
cd TemporalDemo/agentcore
# Gateway
agentcore add gateway --name FundsGateway --authorizer-type AWS_IAM
# Lambda Target
agentcore add gateway-target \
--name FundsTarget --gateway FundsGateway --type lambda-function-arn \
--lambda-arn arn:aws:lambda:ap-northeast-1:<account-id>:function:temporal-policy-demo-funds-target \
--tool-schema-file tools.json
# Policy Engine
agentcore add policy-engine --name FundsPolicyEngine \
--attach-to-gateways FundsGateway --attach-mode LOG_ONLY
# デプロイ
agentcore deploy -y
数分で Gateway の URL と ARN が出力されます。
次に、Temporal Policy を使うには、Gateway の Execution Role に GetWorkloadAccessToken 権限を付与する必要があるので、AWS CLI で付与しておきます。
# IAM Role にポリシーを付与
aws iam put-role-policy --role-name <GatewayのExecution Role名> \
--policy-name PolicySessionWorkloadIdentity \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{"Effect": "Allow", "Action": "bedrock-agentcore:GetWorkloadAccessToken",
"Resource": ["arn:aws:bedrock-agentcore:ap-northeast-1:<account-id>:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:ap-northeast-1:<account-id>:workload-identity-directory/default/workload-identity/temporaldemo-fundsgateway-xxxxxxxxxx*"]}]
}'
手順2: Temporal Policy の作成と ENFORCE 化
Temporal Policy(Dogwood)は create-policy の definition で cedar ではなく policy キーを使います。
次の通り 「残高照会したアカウントにしか送金できない」ポリシーを作成 しました。
GW_ARN="arn:aws:bedrock-agentcore:ap-northeast-1:<account-id>:gateway/temporaldemo-fundsgateway-xxxxxxxxxx"
ENGINE_ID="TemporalDemo_FundsPolicyEngine-xxxxxxxxxx"
# get_account_balance ツールは無条件で許可
aws bedrock-agentcore-control create-policy --policy-engine-id "$ENGINE_ID" \
--name AllowGetBalance --validation-mode IGNORE_ALL_FINDINGS \
--definition '{"cedar": {"statement":
"permit (principal, action == AgentCore::Action::\"FundsTarget___get_account_balance\", resource == AgentCore::Gateway::\"'"$GW_ARN"'\");"
}}'
# transfer_funds ツールは「1 時間以内に同じ口座への残高照会があった場合のみ」許可
aws bedrock-agentcore-control create-policy --policy-engine-id "$ENGINE_ID" \
--name TransferRequiresLookup --validation-mode FAIL_ON_ANY_FINDINGS \
--definition '{"policy": {"statement":
"permit (principal, action == AgentCore::Action::\"FundsTarget___transfer_funds\", resource == AgentCore::Gateway::\"'"$GW_ARN"'\") when temporal { formerly within 1h AgentCore::Action::\"FundsTarget___get_account_balance\"::response{ eventResource: resource, output.accountId: context.input.toAccount } };"
}}'
LOG_ONLY のままだと拒否されないので、update-gatewayでpolicyEngineConfiguration.modeをENFORCEに切り替えてから、IAM SigV4 署名付きで Gateway の MCP エンドポイントに直接 POST して検証します。
検証結果は以下のとおりです。
検証結果
実際のレスポンス(Case A / C はどちらも同じエラー):
{"jsonrpc":"2.0","id":2,"error":{"code":-32002,"message":"Tool Execution Denied: Tool call not allowed due to policy enforcement [No policy applies to the request (denied by default).]"}}
Case B(照会→同口座送金):
{"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"status\":\"ok\",\"fromAccount\":\"acct-9999\",\"toAccount\":\"acct-1001\",\"amount\":100}"}]}}
手順3: Rate Limiting の検証
FundsTarget 向けに「1 分あたり 2 リクエストまで」を設定します。
# Gateway に Rate Limit を追加
aws bedrock-agentcore-control create-gateway-rate-limit \
--gateway-identifier temporaldemo-fundsgateway-xxxxxxxxxx \
--dimension-keys '["targetName"]' \
--entries '[
{"dimensions": {"targetName": "FundsTarget"}, "requests": [{"rate": 2, "period": "minute"}]},
{"dimensions": {"targetName": "*"}, "requests": [{"rate": 1000, "period": "minute"}]}
]'
検証結果:伝播待ち(最大 30 秒)の後、get_account_balanceを10 回連続で呼ぶと断続的に弾かれました。
call 1〜7: ok
call 8: {"error":{"code":-32003,"message":"Rate limit exceeded","data":{"retryAfter":30.0,"limitKey":"z2oj6aodur"}}}
call 9: ok
call 10: {"error":{"code":-32003,"message":"Rate limit exceeded", ...}}
「3 回目以降は必ず拒否」ではなく、トークンバケット的に時間経過で枠が回復していく挙動でした。
retryAfterとlimitKeyがエラーに含まれるので、クライアント側でリトライ制御を組みやすい設計です。
なお Rate Limiting は fail-open(ディメンションが解決できない場合などはリクエストを通す)仕様なので、単独のセキュリティ境界にはしない方がよさそうです。
今回は挙動の確認だけですが、Rate Limiting はトークン消費量などでも制限をかけられるようなのでまた別の記事で深掘りしたいですね。