AWS 官方博客展示如何用 Bedrock AgentCore Gateway + MCP 协议构建多账号 AI Agent,保持各团队数据隔离的同时实现跨账号统一查询。
企业越来越需要能够跨多个 AWS 账号对数据进行推理的 AI 智能体,而无需复制或集中数据。每个团队将数据保存在自己的账号中有充分的理由:明确的所有权、范围隔离和独立的部署生命周期。但只能访问一个账号数据的智能体价值有限,将其连接到分布式数据源通常意味着复制数据或纠缠于跨账号 AWS Identity and Access Management (IAM) 配置。我们的目标是让数据留在它们原本所在的位置——各业务线(LOB)账号中。只有请求所需的特定数据在查询时才流出,因此底层数据集不会离开其所属账号。
在这篇文章中,您将构建一个多账号架构,该架构让每个团队的数据保留在自己的账号中,同时通过 Amazon Bedrock AgentCore Gateway 和 Model Context Protocol (MCP) 为智能体提供统一的跨账号查询方式。Amazon Bedrock AgentCore 是一个用于大规模构建、部署和安全运营高效智能体的智能体服务。中心平台账号托管智能体层和大语言模型(LLM)推理服务(通过 Amazon Bedrock)。业务线团队将其数据和工具作为 MCP 服务器暴露出来,平台账号的 AgentCore Gateway 为智能体提供单一端点,用于跨注册业务线的工具发现和调用。在此过程中,您将设置跨账号 MCP 集成、通过 AgentCore Identity(Amazon Bedrock AgentCore 的一项功能)和 Okta 进行身份验证、通过 Amazon Bedrock AgentCore 中的 Policy 进行细粒度授权,以及支持生产就绪的治理控制。
该架构遵循多账号模型,包含三层:中心平台账号、分布式 LOB 账号,以及作为连接它们的集成层的 AgentCore Gateway。
平台账号——智能体控制平面
平台团队拥有平台账号,在 AgentCore Runtime(Amazon Bedrock AgentCore 的一项功能)上运行智能体。AgentCore Runtime 是一个无服务器、框架无关的环境,具有专用 microVM 中的会话隔离、按使用量计费以及内置身份验证。为了保持讲解清晰,本文使用单个智能体,但相同模式支持平台账号中的多个智能体。智能体连接到平台账号的 Gateway,而不是连接各个 LOB MCP 服务器。
LLM 推理通过 Amazon Bedrock 在平台账号中运行。平台团队控制可用的基础模型(FMs),应用 Amazon Bedrock Guardrails,并通过单一计费边界跟踪成本,避免了跨数十个 LOB 账号管理模型配额的 overhead。随着需求增长,一些组织将推理分布到多个专用推理账号,在前面放置 AgentCore Gateway 作为推理网关,根据请求路由流量并在各团队应用速率限制。
平台账号中的 AgentCore Gateway 作为智能体的单一 MCP 端点。它将每个 LOB 账号的 MCP 服务器注册为目标,并从该单一端点提供语义搜索的统一工具发现、通过 AgentCore Identity 的集中身份验证、通过 Policy in AgentCore 的细粒度授权,以及可观测性。
除了聚合 MCP 服务器和充当推理网格外,AgentCore Gateway 还支持额外的目标类型,使其成为中心集成点。HTTP 目标将 AgentCore Runtime 智能体、agent-to-agent (A2A) 服务和其他 HTTP 端点纳入同一个受治理的端点,每个通过其自己的子路径寻址。平台团队还可以应用 Amazon Bedrock Guardrails 进行内容安全,并通过 Policy in AgentCore (Cedar) 配置细粒度访问控制,两者均在 Gateway 层强制执行,不在智能体代码中。
LOB 账号——数据和工具
每个业务线团队不直接暴露原始 AWS 资源(Amazon Simple Storage Service (Amazon S3) 存储桶、数据库、Amazon Bedrock Knowledge Bases),而是将其数据和工具打包为 MCP 服务器。零售银行团队暴露 get_balance 和 get_profile 等工具。贷款团队提供 get_credit_score 和 search_lending_policies,后者查询 Amazon Bedrock Knowledge Bases 中银行政策 PDF 的完全托管检索增强生成(RAG)功能。此参考架构将独立的 Amazon Bedrock Knowledge Base 包装在 MCP 服务器内,以对检索管道进行细粒度控制。对于新实现,您可以改为将 Amazon Bedrock Managed Knowledge Base 直接作为原生连接器附加到 Gateway,这样智能体使用标准 MCP 调用进行查询,且无需运维检索基础设施。
MCP 服务器在 LOB 账号的 AgentCore Runtime 上运行,这是一个无服务器、框架无关的环境,具有专用 microVM 中的会话隔离、按使用量计费、通过 AgentCore Identity 的内置身份验证以及智能体特定的可观测性。这让业务线团队完全拥有其工具表面:他们决定暴露什么以及每个工具背后运行什么业务逻辑,只要 MCP 工具接口保持一致,就可以更改实现而不影响平台智能体。
跨账号集成:Gateway 和 Identity 连接各层
此架构遵循中心辐射(hub-and-spoke)模式:每个 LOB 使用 MCP over Streamable HTTP 部署独立 MCP 服务器(辐射端),而 AgentCore Gateway(中心端)在单一端点后面聚合它们。智能体将 Gateway 作为一个 MCP 服务器连接,Gateway 跨注册的业务线目标联邦工具调用。当智能体调用工具时,Gateway 从 AgentCore Identity 获取 OAuth 2.0 机器对机器 (M2M) 凭证,将其附加到出站请求,并路由到正确的 LOB MCP 服务器,后者根据 Okta 的 OpenID Connect (OIDC) 端点验证令牌后再在本地处理请求。
LOB 的数据保留在其自己的账号中:MCP 服务器只返回工具产生的特定结果,而非原始数据集,该结果作为推理上下文流向平台账号。源数据不会被复制或迁移。
图 1:使用 AgentCore Gateway 和 MCP 的多账号 AI 智能体架构
以下讲解追踪用户问题如何跨账号边界、调用分布式工具并返回统一答案:
allowedWorkloadConfiguration 以将运行时调用限制为身份链包含 Gateway 的请求,降低绕过 Gateway 策略和 Cedar 授权直接访问的风险。以下各节将深入介绍架构的每一层:LOB 团队如何构建和部署 MCP 服务器,平台团队如何配置 AgentCore Gateway 的 OAuth 出站认证和 Policy in AgentCore 授权,以及持续评估如何帮助保持智能体的可靠性——随着工具和模型的演进。完整实现请克隆配套代码库并运行部署脚本,该脚本跨四个账户引导 AWS Cloud Development Kit(AWS CDK),配置平台和 LOB 资源,部署 MCP 服务器和 Gateway 目标,并在 CloudFront 背后的 Amazon ECS 上启动一个 React Web 应用。
配套代码库假设以下前提条件:
每个 LOB 团队使用 FastMCP 构建一个 MCP 服务器,并使用 AgentCore CLI 将其部署到 AgentCore Runtime,将团队的数据暴露为带类型输入和输出的结构化工具。每个 LOB 团队为其服务器配置一个 customJWTAuthorizer,对传入的 OAuth 令牌在 Okta 的 OIDC 发现端点进行身份验证,因此请求必须提供有效令牌才能调用 LOB 的工具。为了生产环境加固,在 Runtime 上设置 allowedWorkloadConfiguration 为 Gateway 的 Amazon Resource Name(ARN),将其配置为仅当身份链包含该 Gateway 时才接受请求。此示例依赖 OAuth audience 验证作为主要访问控制。添加 allowedWorkloadConfiguration 有助于将调用限制为仅来自经由 Gateway 的请求,降低绕过 Gateway 策略直接访问的风险。
以下代码片段展示了 Lending & Wealth LOB 的 MCP 服务器,将 Amazon DynamoDB 查询与 Amazon Bedrock Knowledge Bases 检索相结合。
REGION = os.environ.get("AWS_REGION", "us-east-1")
dynamodb = boto3.resource("dynamodb", region_name=REGION)
bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name=REGION)
KNOWLEDGE_BASE_ID = os.environ.get("KNOWLEDGE_BASE_ID", "")
mcp = FastMCP("lending-wealth", host="0.0.0.0", stateless_http=True)
@mcp.tool()
def get_credit_score(customer_id: str) -> dict:
"""Get credit score and contributing factors for a customer."""
table = dynamodb.Table("CreditScores")
resp = table.get_item(Key={"customer_id": customer_id})
item = resp.get("Item")
if not item:
return {"error": f"No credit score found for customer {customer_id}"}
return item
@mcp.tool()
def search_lending_policies(query: str) -> str:
"""Search the bank's lending policy documents for guidelines,
eligibility criteria, and regulatory requirements."""
if not KNOWLEDGE_BASE_ID:
return json.dumps({"error": "KNOWLEDGE_BASE_ID not configured"})
resp = bedrock_agent_runtime.retrieve(
knowledgeBaseId=KNOWLEDGE_BASE_ID,
retrievalQuery={"text": query},
retrievalConfiguration={"vectorSearchConfiguration": {"numberOfResults": 5}},
)
chunks = []
for r in resp.get("retrievalResults", []):
text = r.get("content", {}).get("text", "")
source = r.get("location", {}).get("s3Location", {}).get("uri", "")
if text:
chunks.append({"text": text, "source": os.path.basename(source)})
return json.dumps({"results": chunks}, default=str)
if __name__ == "__main__":
mcp.run(transport="streamable-http")
使用 AgentCore CLI 将 MCP 服务器部署到 AgentCore Runtime。configure 步骤设置入口点和协议。deploy 步骤打包并推送:
# Configure the MCP server
agentcore configure \
--entrypoint server.py \
--name lending_wealth_mcp \
--protocol MCP \
--disable-memory \
--non-interactive \
--authorizer-config '{
"customJWTAuthorizer": {
"discoveryUrl": "<OKTA_DISCOVERY_URL>",
"allowedAudience": ["lobfederation"]
}
}'
# Deploy to AgentCore Runtime
agentcore deploy --auto-update-on-conflict \
--env KNOWLEDGE_BASE_ID=<your-knowledge-base-id>
部署后,CLI 返回一个 runtime ARN,平台团队使用它将 MCP 服务器注册为 Gateway 目标。
在平台账户中创建 Gateway,使用指向 Okta OIDC 发现 URL 的 Custom JWT authorizer,并验证 audience(aud)声明以限制哪些应用程序可以连接:
ctrl.update_gateway(
gatewayIdentifier=gateway_id,
name="lobfederation-gateway",
protocolType="MCP",
protocolConfiguration={
"mcp": {
"searchType": "SEMANTIC",
"supportedVersions": ["2025-03-26"],
}
},
authorizerType="CUSTOM_JWT",
authorizerConfiguration={
"customJWTAuthorizer": {
"discoveryUrl": "https://<your-okta-domain>/oauth2/<auth-server-id>/.well-known/openid-configuration",
"allowedAudience": ["lobfederation"],
}
},
)
对于到 LOB MCP 服务器的出站认证,Gateway 使用 OAuth 2.0 客户端凭证授权(M2M)。平台团队在 AgentCore Identity 中注册一个 OAuth 凭证提供商,存储 Okta M2M 客户端凭证。当 Gateway 调用 LOB MCP 服务器时,AgentCore Identity 从 Okta 获取一个新的访问令牌,并通过 Authorization 头传递它。注册凭证提供商并将其附加到每个 Gateway 目标:
# Register an OAuth credential provider (M2M / client_credentials)
resp = ctrl.create_oauth2_credential_provider(
name="lobfederation-okta-m2m",
credentialProviderVendor="CustomOauth2",
oauth2ProviderConfigInput={
"customOauth2ProviderConfig": {
"oauthDiscovery": {
"discoveryUrl": "https://<your-okta-domain>/oauth2/<auth-server-id>/.well-known/openid-configuration"
},
"clientId": "<M2M_CLIENT_ID>",
"clientSecret": "<M2M_CLIENT_SECRET>",
"clientAuthenticationMethod": "CLIENT_SECRET_BASIC",
}
},
)
cred_arn = resp["credentialProviderArn"]
# Create a Gateway target for the LOB MCP server with OAuth outbound auth
ctrl.create_gateway_target(
gatewayIdentifier=gateway_id,
name="lending-wealth",
description="Lending & Wealth --- loans, credit scores, eligibility, policy search",
targetConfiguration={
"mcp": {
"mcpServer": {
"endpoint": f"https://bedrock-agentcore.{REGION}.amazonaws.com/runtimes/{encoded_runtime_arn}/invocations",
}
}
},
credentialProviderConfigurations=[
{
"credentialProviderType": "OAUTH",
"credentialProvider": {
"oauthCredentialProvider": {
"providerArn": cred_arn,
"scopes": ["lobfederation.invoke"],
"grantType": "CLIENT_CREDENTIALS",
}
},
}
],
)
当 LOB 工具必须自行强制执行按用户级别的访问控制时(例如行级安全),AgentCore Identity 还提供 on-behalf-of(OBO)令牌交换,Gateway 在其中将传入的用户令牌交换为下游作用域令牌,同时携带智能体和用户的身份。本实现使用 M2M,因为用于示例的 Okta 开发者账户不支持 OBO 流程。AgentCore Gateway 还支持授权码授权和 API 密钥。具体示例请参阅 AgentCore Gateway 出站认证示例。
将 Strands 智能体部署到 AgentCore Runtime,并使用 Custom JWT authorizer 进行入站认证。部署脚本在初始部署后通过 AgentCore 控制平面 API 应用 authorizer 配置。在请求时,智能体将用户的 JWT 转发到 Gateway,以便 Policy in AgentCore 在路由每个工具调用之前评估用户的声明:
部署后,智能体从入站请求头中读取用户的 JWT,并将其传递给 AgentCore Gateway。这样无需智能体解析或修改令牌,即可将终端用户身份传播到 Cedar 策略引擎:
@app.entrypoint
def invoke(payload, context=None):
prompt = payload.get("prompt", "Hello")
# 从入站请求头中读取用户的 JWT(由 Runtime 透传)
request_headers = context.request_headers if context else {}
user_jwt = request_headers.get("Authorization", "")
# 使用用户的 JWT 连接 Gateway --- Cedar 评估每个用户的策略
mcp_client = MCPClient(
lambda: streamablehttp_client(
url=GATEWAY_URL,
headers={"Authorization": user_jwt},
)
)
with mcp_client:
tools = mcp_client.list_tools_sync()
agent = Agent(model=MODEL_ID, system_prompt=SYSTEM_PROMPT, tools=tools)
result = agent(prompt)
智能体部署后,平台团队通过持续评估、安全版本发布和可观测性来保持其稳定运行。
在智能体跨多个业务线编排工具的多账户架构中,平台团队需要确保在工具、模型和提示词不断演进的过程中,智能体始终保持正确运行。AgentCore Evaluations 提供了一个托管框架,有助于在问题影响客户之前捕获回归。
在线评估对实时生产流量(例如 10% 的会话)进行持续评分,使用内置评估器,如工具选择准确性、正确性和目标成功率。评分在 AgentCore 可观测性仪表板(由 Amazon CloudWatch 驱动的 Amazon Bedrock AgentCore 功能)中展示,当质量下降时会触发告警;如果智能体已发送 OpenTelemetry 追踪,则无需修改代码。这可以发现延迟和错误率监控无法捕捉的静默降级,例如智能体将贷款查询路由到错误的业务线。
按需评估是面向开发和 CI/CD 的实时 API。团队只需定义一次评估数据集(场景与预期响应、工具轨迹和目标断言配对),AgentCore Evaluations 便会通过数据集评估在每次变更时回放。由于两种模式共享相同的评估器,团队在部署前作为门控的条件与在生产中监控的条件完全一致。为了闭环,AgentCore Optimization 分析生产追踪并推荐提示词和工具描述改进,在发布前经过验证。
团队通过指向特定版本的端点(prod、staging、dev)在 AgentCore Runtime 上部署智能体。当平台团队更新智能体的提示词或模型时,会发布新版本并更新端点,业务线 MCP 服务器不受影响,因为工具接口未发生变化。在提升变更之前,团队可以通过 AgentCore Gateway 运行 A/B 测试,在当前版本和候选版本之间分割实时流量。平台团队 затем 在结果达到统计显著性后提升获胜配置。
AgentCore 通过 Amazon CloudWatch 和 OpenTelemetry 提供内置可观测性。平台团队监控调用延迟、错误率和 Token 使用量,并通过 CloudWatch 跨账户可观测性查看来自业务线 MCP 服务器的指标和日志,无需切换账户。
将智能体集中化同时分布式数据会产生特定的治理要求:控制谁可以调用哪些工具、审计跨账户调用、执行负责任 AI 策略,以及将成本归属到触发它的业务线。
业务线团队通过其 AgentCore Runtime 部署上的 JWT 授权器配置来控制谁可以调用其 MCP 服务器。来自平台账户 Gateway 的请求只有在业务线团队已将其 MCP 服务器配置为接受来自平台身份提供商的令牌后才能到达业务线的工具。此批准独立于平台团队。即使 Gateway 添加了新目标,业务线 MCP 服务器也会拒绝未认证的请求。
Gateway 在 ENFORCE 模式下运行 AgentCore 授权,在将每个工具调用路由之前,根据用户 JWT 声明(由智能体转发的令牌)评估规则。AgentCore 授权使用 Cedar 策略语言,因此规则是明确的 permit 和 forbid 语句。例如,策略可以允许所有已认证用户调用只读工具(如 get_balance),同时将写入操作(如 transfer_funds)限制为特定角色,或完全阻止破坏性操作(如 delete_customer):
// 允许所有已认证用户调用只读工具
permit(
principal is AgentCore::OAuthUser,
action in [
AgentCore::Action::"retail-banking___get_customer",
AgentCore::Action::"retail-banking___get_accounts",
AgentCore::Action::"retail-banking___get_balance",
AgentCore::Action::"tools/list",
AgentCore::Action::"initialize"
],
resource
);
// 无论用户如何都阻止破坏性操作
forbid(
principal,
action == AgentCore::Action::"retail-banking___delete_customer",
resource
);
由于 AgentCore 授权使用默认拒绝模式,只有具有明确 permit 的操作才会成功。这使平台团队能够集中控制智能体在已注册业务线中的行为,同时各业务线团队在其 MCP 服务器级别保留自己的授权。
此参考实现对 AgentCore Runtime 使用默认公共网络模式,其中流量通过 HTTPS 上的公共互联网传输,并使用 OAuth。这适用于开发但不适用于生产环境(原文在此处截断)。