AgentCore Gateway 是一个托管的 MCP 兼容代理,使多个 agent 能够通过统一端点发现、认证和调用工具。
我们将从直接在 agent 代码中定义工具迁移到通过 Gateway 管理的集中式企业级工具。

优秀的 agent 需要能够充分利用专有和第三方 API 及数据的工具。然而,构建、保护和扩展 agent 工具非常困难,成为客户从原型转向生产的重大障碍。
在大多数组织中,有价值的业务逻辑已经存在——作为 Lambda 函数、REST API 或内部服务——但它们并非为 AI agent 而构建。AgentCore Gateway 让我们可以将这些现有资源"MCPify”,将其转变为任何 agent 都可以通过标准 MCP 协议发现和使用的工具,而无需修改原始代码。
AgentCore Gateway 支持多种目标类型:
AgentCore Gateway 提供:
原先(本地工具):
Agent → [get_return_policy(), get_product_info()](在代码中)
Agent → [Exa AI MCP](直接连接)
目标(Gateway + 本地):
Agent → Gateway → [Lambda: check_warranty]
Agent → [get_return_policy(), get_product_info()](保留本地)
Agent → [Exa AI MCP](保留为直接 MCP 客户端)

我们使用一个 Lambda 函数(workshop-warranty-check),它模拟由我们组织中另一个团队维护的企业级 warranty check API。这是一个常见的现实场景:有用的业务逻辑已经作为 Lambda 函数存在,但它并非为 AI agent 设计。AgentCore Gateway 让我们可以对这些现有函数进行 MCPify,使其可被任何 agent 发现和调用, 而无需修改原始 Lambda 代码。
函数代码如下,这是一个针对硬编码 warranty 数据库的简单查询:
import json
WARRANTIES = {
"PROD-001": {"product": "Wireless Headphones", "warranty_months": 12, "status": "active", "expires": "2027-03-01"},
"PROD-002": {"product": "Smart Watch", "warranty_months": 24, "status": "active", "expires": "2028-01-15"},
"PROD-003": {"product": "Laptop Stand", "warranty_months": 6, "status": "expired", "expires": "2026-01-01"},
"PROD-004": {"product": "USB-C Hub", "warranty_months": 12, "status": "active", "expires": "2027-06-20"},
}
def handler(event, context):
product_id = event.get("product_id", "").upper()
if product_id in WARRANTIES:
return {"statusCode": 200, "body": json.dumps(WARRANTIES[product_id])}
return {"statusCode": 404, "body": json.dumps({"error": f"No warranty found for {product_id}"})}
Gateway 如何调用 Lambda: AgentCore Gateway 直接在 Lambda
event中传递工具参数(而不是在event["body"]中)。工具名称可在context.client_context.custom["bedrockAgentCoreToolName"]中获取,格式为<TargetName>___<tool_name>。由于每个 Lambda 只有一个工具,我们只需从event中读取参数。
现在从 Parameter Store 获取 Lambda ARN(cloudformation stack创建的):
WARRANTY_LAMBDA_ARN=$(aws ssm get-parameter \
--name /app/customersupport/agentcore/warranty_check_lambda_arn \
--query 'Parameter.Value' --output text)
echo "Lambda ARN: $WARRANTY_LAMBDA_ARN"

为了让 AI agent 使用工具,它需要了解工具的功能、期望的参数以及返回内容——所有这些都用自然语言描述。这正是 MCP 协议提供的:一种让工具宣传其功能的标准方式,使 agent 能够推理何时以及如何调用它们。
然而,Lambda 函数不携带这些元数据。Lambda 只是带有输入事件和输出的代码——没有内置方式让 agent 知道 workshop-warranty-check 的功能或需要传递什么参数。
这就是 AgentCore Gateway 弥合差距的地方。它将我们的 Lambda(或 API,或 MCP 服务器)包装在 MCP 兼容端点后面,但仍然需要我们提供工具描述——名称、自然语言描述和输入 schema。这就是我们在这里创建的内容。
创建 schema 文件:
mkdir -p app/CustomerSupport/tool
touch app/CustomerSupport/tool/__init__.py
touch app/CustomerSupport/tool/warranty_schema.json
在编辑器中打开 app/CustomerSupport/tool/warranty_schema.json 并添加以下内容:
[
{
"name": "check_warranty",
"description": "Check the warranty status of a product by its product ID (e.g. PROD-001). Returns warranty duration, status (active/expired), and expiration date.",
"inputSchema": {
"type": "object",
"properties": {
"product_id": {
"type": "string",
"description": "The product ID to check warranty for (e.g. PROD-001)"
}
},
"required": ["product_id"]
}
}
]
注意 description 字段如何使用自然语言——这是 agent 读取以决定是否调用工具以及如何填写参数的内容。没有这些,Gateway 将无法向 agent 呈现有意义的 Lambda 工具。
现在我们将所有内容连接在一起。我们将创建一个 Gateway(托管的 MCP 端点)并将 Lambda 函数注册为目标。Lambda 只是众多目标类型之一,我们同样可以轻松地将 API Gateway REST API stage、OpenAPI 端点、Smithy 模型、现有 MCP 服务器或内置提供商模板添加到同一个 Gateway。
在terminal中:
# 创建链接到现有 CustomerSupport agent 的 gateway
agentcore add gateway --name my-gateway --runtimes CustomerSupport
# 将 warranty check Lambda 添加为目标(使用之前从 Parameter Store 获取的 ARN)
agentcore add gateway-target \
--type lambda-function-arn \
--name WarrantyCheck \
--lambda-arn $WARRANTY_LAMBDA_ARN \
--tool-schema-file app/CustomerSupport/tool/warranty_schema.json \
--gateway my-gateway
我们应该看到:
Added gateway 'my-gateway'
Added gateway target 'WarrantyCheck'
首先,在编辑器中更新 app/CustomerSupport/mcp_client/client.py 以添加 gateway MCP 客户端:
这在现有 Exa AI 客户端旁边添加了一个新的 get_gateway_mcp_client() 函数。它从 AGENTCORE_GATEWAY_MY_GATEWAY_URL 环境变量(部署后由 AgentCore Runtime 注入)读取 gateway URL,并创建一个连接到我们的 gateway 端点的 MCP 客户端。如果 URL 未设置(例如,在本地开发期间),它会优雅地返回 None。
import os
import logging
from mcp.client.streamable_http import streamablehttp_client
from strands.tools.mcp.mcp_client import MCPClient
logger = logging.getLogger(__name__)
# ExaAI MCP endpoint for web search
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
def get_streamable_http_mcp_client() -> MCPClient:
"""Returns an MCP Client for Exa AI web search"""
return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))
def get_gateway_mcp_client() -> MCPClient | None:
"""Returns an MCP Client for AgentCore Gateway, if configured"""
url = os.environ.get("AGENTCORE_GATEWAY_MY_GATEWAY_URL")
if not url:
logger.warning("Gateway URL not set — gateway tools unavailable")
return None
return MCPClient(lambda: streamablehttp_client(url))
然后更新 app/CustomerSupport/main.py 以导入并使用 gateway 客户端。关键变化是将 get_gateway_mcp_client 添加到 MCP 客户端列表中:
唯一的变化是导入 get_gateway_mcp_client 并将其添加到 mcp_clients 列表中。这使我们的 agent 能够访问 gateway 工具(如 order lookup Lambda),同时保留现有的 Exa AI 网络搜索和本地工具。Agent 自动从两个 MCP 客户端发现所有可用工具。
from strands import Agent, tool
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from model.load import load_model
from mcp_client.client import get_streamable_http_mcp_client, get_gateway_mcp_client
from memory.session import get_memory_session_manager
app = BedrockAgentCoreApp()
log = app.logger
# MCP clients: Exa AI (web search) + AgentCore Gateway (Lambda tools)
mcp_clients = [get_streamable_http_mcp_client(), get_gateway_mcp_client()]
# --- Customer Support Tools ---
RETURN_POLICIES = {
"electronics": {"window": "30 days", "condition": "Original packaging required, must be unused or defective", "refund": "Full refund to original payment method"},
"accessories": {"window": "14 days", "condition": "Must be in original packaging, unused", "refund": "Store credit or exchange"},
"audio": {"window": "30 days", "condition": "Defective items only after 15 days", "refund": "Full refund within 15 days, replacement after"},
}
PRODUCTS = {
"PROD-001": {"name": "Wireless Headphones", "price": 79.99, "category": "audio", "description": "Noise-cancelling Bluetooth headphones with 30h battery life", "warranty_months": 12},
"PROD-002": {"name": "Smart Watch", "price": 249.99, "category": "electronics", "description": "Fitness tracker with heart rate monitor, GPS, and 5-day battery", "warranty_months": 24},
"PROD-003": {"name": "Laptop Stand", "price": 39.99, "category": "accessories", "description": "Adjustable aluminum laptop stand for ergonomic desk setup", "warranty_months": 6},
"PROD-004": {"name": "USB-C Hub", "price": 54.99, "category": "accessories", "description": "7-in-1 USB-C hub with HDMI, USB-A, SD card reader, and ethernet", "warranty_months": 12},
"PROD-005": {"name": "Mechanical Keyboard", "price": 129.99, "category": "electronics", "description": "RGB mechanical keyboard with Cherry MX switches", "warranty_months": 24},
}
@tool
def get_return_policy(product_category: str) -> str:
"""Get return policy information for a specific product category.
Args:
product_category: Product category (e.g., 'electronics', 'accessories', 'audio')
Returns:
Formatted return policy details including timeframes and conditions
"""
category = product_category.lower()
if category in RETURN_POLICIES:
policy = RETURN_POLICIES[category]
return f"Return policy for {category}: Window: {policy['window']}, Condition: {policy['condition']}, Refund: {policy['refund']}"
return f"No specific return policy found for '{product_category}'. Please contact support for details."
@tool
def get_product_info(query: str) -> str:
"""Search for product information by name, ID, or keyword.
Args:
query: Product name, ID (e.g., 'PROD-001'), or search keyword
Returns:
Product details including name, price, category, and description
"""
query_lower = query.lower()
# Search by ID
if query.upper() in PRODUCTS:
p = PRODUCTS[query.upper()]
return f"{p['name']} ({query.upper()}): ${p['price']}, Category: {p['category']}, {p['description']}, Warranty: {p['warranty_months']} months"
# Search by keyword
results = [f"{pid}: {p['name']} - ${p['price']} - {p['description']}" for pid, p in PRODUCTS.items()
if query_lower in p['name'].lower() or query_lower in p['description'].lower() or query_lower in p['category'].lower()]
if results:
return "Found products:\n" + "\n".join(results)
return f"No products found matching '{query}'."
tools = [get_return_policy, get_product_info]
# Add MCP client (Exa AI web search) to tools
for mcp_client in mcp_clients:
if mcp_client:
tools.append(mcp_client)
# Agent factory — creates one agent per session/user combination
def agent_factory():
cache = {}
def get_or_create_agent(session_id, user_id):
key = f"{session_id}/{user_id}"
if key not in cache:
cache[key] = Agent(
model=load_model(),
session_manager=get_memory_session_manager(session_id, user_id),
system_prompt="""You are a helpful and professional customer support assistant for an e-commerce company.
Your role is to:
- Provide accurate information using the tools available to you
- Be friendly, patient, and understanding with customers
- Always offer additional help after answering questions
- If you can't help with something, direct customers to the appropriate contact
You have access to the following tools:
1. get_return_policy() - For return policy questions
2. get_product_info() - To look up product information and specifications
3. Web search - To search the web for troubleshooting help
Always use the appropriate tool to get accurate, up-to-date information rather than guessing.""",
tools=tools
)
return cache[key]
return get_or_create_agent
get_or_create_agent = agent_factory()
@app.entrypoint
async def invoke(payload, context):
log.info("Invoking Agent.....")
session_id = getattr(context, 'session_id', 'default-session')
user_id = getattr(context, 'user_id', 'default-user')
agent = get_or_create_agent(session_id, user_id)
stream = agent.stream_async(payload.get("prompt"))
async for event in stream:
if "data" in event and isinstance(event["data"], str):
yield event["data"]
if __name__ == "__main__":
app.run()
本地工具(get_return_policy、get_product_info)保留在 agent 代码中。Gateway 工具(check_warranty)在运行时通过 MCP 客户端自动发现。
工作原理: 部署后,AgentCore Runtime 将 AGENTCORE_GATEWAY_MY_GATEWAY_URL 作为环境变量注入。get_gateway_mcp_client() 函数读取此 URL 并创建连接到 gateway 的 MCP 客户端。Gateway 将请求路由到 Lambda 函数。
agentcore deploy -y -v
注意: 首次 gateway 部署需要约 2 分钟。
测试 warranty check 工具:
agentcore invoke "Check the warranty for product PROD-003" --stream
预期响应:
The warranty for PROD-003 (Laptop Stand) is:
- Warranty Duration: 6 months
- Status: Expired
- Expiration Date: January 1, 2026

测试有效的 warranty:
agentcore invoke "Is the warranty still valid for PROD-002?" --stream
预期:Agent 通过 Gateway 调用 check_warranty 并返回 Smart Watch warranty 有效至 2028 年。

aws控制台查看gateway:


agentcore invoke "Check warranty for PROD-003"
↓
AgentCore Runtime(CustomerSupport)
↓
Agent 从环境变量读取 AGENTCORE_GATEWAY_MY_GATEWAY_URL
↓
MCP Client 连接到 Gateway
↓
Gateway 路由到 WarrantyCheck Lambda 目标
↓
Lambda 执行并返回结果
↓
Agent 综合响应