使用 AgentCore 與 Strands 建構:閘道廠務工程 MCP 工具架構開發者工作坊
目標受眾: 後端開發人員、AI 平台開發人員、AWS 整合工程師
時長: 2 小時
主要 AWS AI 服務: Amazon Bedrock AgentCore Gateway、Strands Agents、MCP、AWS Lambda
專案產出: 一個託管的 MCP 工具架構,包含本機 MCP 工具、Lambda 支援的閘道目標(Lambda-backed Gateway Target)、語意搜尋以及 Strands Agent 呼叫。
本工作坊僅供工程教學使用。範例中的蝕刻製程視窗(Etch-process-window)網域僅用於教學 Agent 工具架構,並非實際的製程發佈建議。
開發人員將建構一個託管的 Gateway MCP 工具架構,連結本機 MCP 原型設計、Lambda 支援的工具、語意搜尋以及 Strands Agent 的調用。本工作坊將逐步引導完成綱要(Schema)設計、本機發現測試(Local discovery tests)、雲端目標註冊、JSON-RPC 偵錯以及 SigV4 傳輸整合。團隊最終將建立一個可擴展的工具治理模式,在複雜的多團隊平台工程環境中,為 AWS 上的 Agent 提供可發現、安全且具備實證導向(Evidence-oriented)的工具集。
1. 開發者學習目標
開發人員將學會如何:
- 設計物件導向的 Agent 工具名稱與綱要(Schema)。
- 建構本機可串流的 HTTP MCP 工具伺服器。
- 在部署到雲端前測試 MCP 工具發現(Discovery)。
- 實作以 Lambda 為後端的工具商業邏輯。
- 在 Amazon Bedrock AgentCore Gateway 中註冊 Lambda 工具。
- 啟用語意工具搜尋。
- 使用 SigV4 傳輸從 Strands Agent 呼叫 Gateway 工具。
- 新增直接的 JSON-RPC 工具呼叫測試以進行偵錯。
2. 本工作坊建構的架構
本機開發環境
├─ mcp_server.py # 本機 MCP 伺服器
├─ mcp_client_local.py # 本機發現用戶端
├─ lambda_function.py # Lambda 目標邏輯
├─ package_lambda.sh # Lambda zip 打包腳本
├─ gateway_setup.py # Gateway 與目標建立腳本
├─ semantic_search.py # Gateway 語意搜尋呼叫
├─ direct_tool_call.py # JSON-RPC 工具/呼叫偵錯
├─ strands_gateway_agent.py # 使用 Gateway MCP 工具的 Strands Agent
└─ prompts/tool_selection.md
AWS
├─ Amazon Bedrock AgentCore Gateway
├─ AWS Lambda 目標
├─ Cognito / 自訂 JWT 授權方輸入
├─ IAM Gateway 角色
└─ 支援 SigV4 MCP 傳輸的 Strands Agent 用戶端
3. 2 小時實作議程
| 時間 | 模組 | 實作產出 |
|---|
| 0–10 | 工具架構概念 | 理解 MCP、Gateway、Lambda 目標流程 |
| 10–25 | 工具合約 | 規劃工具名稱、描述與綱要(Schema) |
| 25–45 | 本機 MCP 伺服器 | 執行可串流的 HTTP 工具伺服器 |
| 45–60 | 本機發現 | 驗證工具清單與中介資料(Metadata) |
| 60–80 | Lambda 目標 | 打包並部署或準備工具後端 |
| 80–100 | Gateway 目標 | 建立 MCP Gateway 與 Lambda 目標 |
| 100–110 | 語意搜尋 | 搜尋工具並回傳相關工具 |
| 110–120 | Strands Agent | Agent 呼叫 Gateway 工具 |
步驟 1 — 定義工具選擇提示詞與綱要策略
開發者動作
mkdir -p agentcore-strands-factory-gateway/prompts
cd agentcore-strands-factory-gateway
cat > prompts/tool_selection.md <<'EOF'
你是一個用於蝕刻製程視窗(Etch Process Window)工作流的工具選擇規劃器。
當工具庫數量龐大時,請使用語意搜尋。
選擇能夠回答使用者請求的最小工具集。
回傳選定的工具名稱、引數(Arguments)、預期實證(Evidence)以及選擇原因。
切勿呼叫執行或設備控制類工具。本系統僅用於工程分析。
EOF
建立 tool_schema.py。
TOOL_SCHEMA = [
{
"name": "throughput_throughput",
"description": "評估 WIP 佇列壓力、機台可用性壓力、晶圓(WAFERS)吞吐量以及 Hot-lot 急件偏好。",
"inputSchema": {
"type": "object",
"properties": {"query": {"type": "string", "description": "吞吐量穩定性分析請求。"}},
"required": ["query"],
},
},
{
"name": "metrology_drift_widening",
"description": "評估線上/批次級(inline/lot-level)漂移擴大、CD-SEM 壓力、良率損失風險以及產能溢價。",
"inputSchema": {
"type": "object",
"properties": {"query": {"type": "string", "description": "關鍵尺寸(Critical-dimension)漂移分析請求。"}},
"required": ["query"],
},
},
{
"name": "process_window_drift",
"description": "評估製程能力、疊對誤差(Overlay error)、配方(Recipe)偏差、貨批流向以及疊對漂移。",
"inputSchema": {
"type": "object",
"properties": {"query": {"type": "string", "description": "蝕刻製程漂移分析請求。"}},
"required": ["query"],
},
},
{
"name": "tool_to_tool_mismatch",
"description": "評估疊對機差、積壓壓力、保留量、基準偏移以及控制環境。",
"inputSchema": {
"type": "object",
"properties": {"query": {"type": "string", "description": "機台間機差(Tool-to-tool mismatch)請求。"}},
"required": ["query"],
},
},
]
商業邏輯
綱要(Schema)定義了向 Agent 公開的工具詞彙表,同時也定義了每個工具負責處理的使用者意圖。
程式碼邏輯
每個綱要項目包含工具名稱、描述、JSON 輸入綱要以及必填欄位。Gateway 設定也會重複使用此綱要。
預期結果
開發人員擁有單一的標準綱要來源,無需在多個腳本中重複定義綱要。
系統設計決策
- 標準綱要來源: 工具綱會影響發現、驗證與 Agent 的行為。將它們保存在
tool_schema.py 中可防止本機測試、Gateway 註冊與文件之間產生偏差。隨著工具目錄的增長,這一點至關重要。 - 針對搜尋最佳化的描述: 描述中包含諸如 WIP 佇列壓力、CD-SEM 壓力、疊對誤差和疊對漂移等業務術語。語意搜尋依賴於有意義的中介資料(Metadata),因此應將描述視為生產級的 API 文件。
- 最小工具集原則: 提示詞要求 Agent 選擇足夠回答問題的最精簡工具集。這能減少不必要的工具呼叫、降低延遲,並使稽核軌跡(Audit trails)更易於審查。
步驟 2 — 建構本機 MCP 伺服器
開發者動作
建立 mcp_server.py。
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(host="0.0.0.0", port=8000, stateless_http=True)
@mcp.tool()
def throughput_throughput(query: str) -> dict:
"""評估 WIP 佇列壓力、機台可用性壓力、晶圓(WAFERS)吞吐量以及 Hot-lot 急件偏好。"""
return {
"tool": "throughput_throughput",
"query": query,
"signals": ["佇列深度", "交換漂移", "晶圓吞吐量", "Hot-lot 急件偏好"],
"summary": "在將漂移運動解讀為純粹的計量風險之前,應先檢查吞吐量壓力。",
}
@mcp.tool()
def metrology_drift_widening(query: str) -> dict:
"""評估線上/批次級漂移擴大、CD-SEM 壓力、良率損失風險以及產能溢價。"""
return {
"tool": "metrology_drift_widening",
"query": query,
"signals": ["線上漂移", "批次級漂移", "CD-SEM 指標", "良率損失監控"],
"summary": "CD-SEM 漂移擴大可能反映了缺陷風險漂移與產能撤回。",
}
@mcp.tool()
def process_window_drift(query: str) -> dict:
"""評估製程能力、疊對誤差、配方偏差、貨批流向以及疊對漂移。"""
return {
"tool": "process_window_drift",
"query": query,
"signals": ["疊對誤差", "財政路徑", "設備控制器反應", "貨批流向"],
"summary": "蝕刻製程漂移應區分財政風險、配方偏差與貨批流向壓力。",
}
@mcp.tool()
def tool_to_tool_mismatch(query: str) -> dict:
"""評估疊對機差、積壓壓力、保留量、基準偏移以及控制環境。"""
return {
"tool": "tool_to_tool_mismatch",
"query": query,
"signals": ["疊對保留量", "外部製程視窗", "基準偏移", "預測偏移"],
"summary": "當外部吞吐量緊縮時,機台間機差可能會放大蝕刻製程的壓力。",
}
if __name__ == "__main__":
mcp.run(transport="streamable-http")
執行:
python mcp_server.py
商業邏輯
每個 MCP 工具都會回傳關於單一製程維度的結構化實證。
程式碼邏輯
FastMCP 透過可串流的 HTTP(Streamable HTTP)將 Python 函式公開為工具。每個函式接受一個 query 並回傳一個字典。
預期結果
本機 MCP 端點可在 http://localhost:8000/mcp 存取。
系統設計決策
- 結構化工具輸出: 回傳字典而非純文字字串,能為 Agent 和測試提供可檢查的欄位:工具名稱、查詢、訊號與摘要。這有助於提高實證接地性(Grounding)與未來的評估。
- 先建本機伺服器再建 Gateway: 本機 MCP 測試可降低雲端複雜性。開發人員先驗證工具行為與中介資料,然後再將工具發佈到託管的 AgentCore Gateway 後方。
- 無狀態工具設計: 工具不依賴隱藏的伺服器記憶體。這使得它們更容易擴展、測試並部署在託管基礎設施後方。
步驟 3 — 測試本機 MCP 發現與直接呼叫
開發者動作
建立 mcp_client_local.py。
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
async with streamablehttp_client(
"http://localhost:8000/mcp",
{},
timeout=120,
terminate_on_close=False,
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print("已發現的工具:")
for tool in tools.tools:
print("-", tool.name, "|", tool.description)
result = await session.call_tool(
"process_window_drift",
{"query": "Fab-A/Fab-B 良率漂移擴大與疊對漂移"},
)
print("直接呼叫結果:")
print(result)
if __name__ == "__main__":
asyncio.run(main())
商業邏輯
用戶端在引入 Gateway 之前,先驗證工具發現與直接執行。
程式碼邏輯
用戶端初始化一個 MCP 工作階段(Session),列出工具,然後使用引數呼叫其中一個工具。
預期結果
主控台印出工具中介資料與結構化的工具執行結果。
系統設計決策
- 發現加直接呼叫測試: 僅列出工具只能證明中介資料的可見性。直接呼叫才能證明工具可接受引數並回傳有效的回應。在發佈到雲端之前,兩者皆為必要測試。
- 無模型參與(No model in the loop): 此測試將 MCP 傳輸和工具行為與 LLM 推理隔離。這使得故障更容易偵錯。
- 具代表性的查詢: 直接呼叫使用包含良率漂移和疊對漂移的實際業務查詢。使用領域語言進行測試有助於驗證描述與輸出的實用性。
步驟 4 — 實作 Lambda 目標邏輯
開發者動作
建立 lambda_function.py。
import json
HANDLERS = {
"throughput_throughput": {
"signals": ["WIP 佇列壓力", "機台可用性差異", "晶圓吞吐量", "交換基準"],
"summary": "在將良率變動視為孤立的蝕刻製程漂移之前,請先檢查佇列壓力。",
},
"metrology_drift_widening": {
"signals": ["線上漂移", "批次級漂移", "CD-SEM 指標", "良率損失風險"],
"summary": "CD-SEM 漂移擴大可能代表缺陷風險漂移或產能溢價擴張。",
},
"process_window_drift": {
"signals": ["疊對誤差", "製程能力", "配方偏差", "貨批流向"],
"summary": "蝕刻製程漂移應分解為財政、策略、流程與疊對驅動因素。",
},
"tool_to_tool_mismatch": {
"signals": ["外部製程視窗", "疊對保留量", "基準偏移", "遠期避險成本"],
"summary": "當外部再融資條件緊縮時,機台間機差可能會放大壓力。",
},
}
def lambda_handler(event, context):
tool_name = event.get("toolName") or event.get("name")
arguments = event.get("arguments", {})
query = arguments.get("query", "")
if tool_name not in HANDLERS:
return {
"statusCode": 404,
"body": json.dumps({"error": f"未知的工具:{tool_name}"}),
}
output = {
"tool": tool_name,
"query": query,
"signals": HANDLERS[tool_name]["signals"],
"summary": HANDLERS[tool_name]["summary"],
}
return {"statusCode": 200, "body": json.dumps(output)}
建立打包輔助腳本:
cat > package_lambda.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
rm -f lambda_function.zip
zip lambda_function.zip lambda_function.py
ls -lh lambda_function.zip
EOF
chmod +x package_lambda.sh
./package_lambda.sh
商業邏輯
Lambda 成為受治理的 Gateway 工具呼叫後端。它將工具請求對應到結構化的訊號輸出。
程式碼邏輯
Handler 讀取 toolName 和 arguments,驗證工具,並回傳 JSON。打包腳本會建立一個 zip 構件(Artifact)。
預期結果
lambda_function.zip 已準備就緒,可用於部署或用於預先準備好的工作坊啟動腳本。
系統設計決策
- Lambda 作為後端邊界: Gateway 負責公開工具,而 Lambda 擁有確定性的商業邏輯。這將模型推理與後端執行分離,使工具行為可測試且可觀察。
- 共享的 Handler 對應表: 基於字典的路由保持了工作坊範例的精簡,同時展示 historical 如何將多個工具對應到單一 Lambda 目標。生產系統隨後可將這些 Handler 拆分。
- 結構化的回應內文: 回傳
tool、query、signals 和 summary 可為 Agent 提供在綜合回答前可引用的實證,同時也提高了可稽核性。
步驟 5 — 建立 AgentCore Gateway 並註冊目標
開發者動作
建立 gateway_setup.py。
import os
import boto3
from tool_schema import TOOL_SCHEMA
region = os.getenv("AWS_DEFAULT_REGION", "us-east-1")
client = boto3.client("bedrock-agentcore-control", region_name=region)
gateway = client.create_gateway(
name="gateway-etch-process-window-tools-hands-on",
roleArn=os.environ["AGENTCORE_GATEWAY_ROLE_ARN"],
protocolType="MCP",
authorizerType="CUSTOM_JWT",
authorizerConfiguration={
"customJWTAuthorizer": {
"allowedClients": [os.environ["COGNITO_CLIENT_ID"]],
"discoveryUrl": os.environ["COGNITO_DISCOVERY_URL"],
}
},
protocolConfiguration={
"mcp": {
"searchType": "SEMANTIC",
"supportedVersions": ["2025-03-26"],
}
},
description="用於蝕刻製程視窗工具的實作 MCP 閘道器",
)
target = client.create_gateway_target(
gatewayIdentifier=gateway["gatewayId"],
name="etch-process-window-lambda-target",
description="公開蝕刻製程視窗工具的 Lambda 目標",
targetConfiguration={
"mcp": {
"lambda": {
"lambdaArn": os.environ["FACTORY_TOOLS_LAMBDA_ARN"],
"toolSchema": {"inlinePayload": TOOL_SCHEMA},
}
}
},
credentialProviderConfigurations=[{"credentialProviderType": "GATEWAY_IAM_ROLE"}],
)
print("Gateway ID:", gateway["gatewayId"])
print("Gateway URL:", gateway["gatewayUrl"])
print("Target ID:", target["targetId"])
商業邏輯
Gateway 透過託管的 MCP 端點,發佈由 Lambda 支援的蝕刻製程視窗工具。
程式碼邏輯
該腳本建立 Gateway、設定 JWT 授權、啟用語意搜尋,並使用標準綱要註冊 Lambda 目標。
預期結果
開發人員會收到 Gateway URL 和目標 ID(Target ID)。
系統設計決策
- Gateway 集中化工具存取: AgentCore Gateway 成為 Agent 的託管 MCP 端點。這避免了每個 Agent 直接與 Lambda、驗證和傳輸邏輯進行整合。
- JWT 入口與 IAM 出口: 入站呼叫者使用 JWT 進行驗證,而 Gateway 使用 IAM 呼叫 Lambda。這將呼叫者授權與後端執行憑證分離。
- 啟用語意發現: 閘道器會為工具中介資料建立索引以進行語意搜尋。這為更龐大的工具目錄做好準備,避免因將所有綱要塞入 Agent 上下文(Context)而導致提示詞膨脹(Prompt-bloating)。
步驟 6 — 測試 Gateway 語意搜尋與直接 JSON-RPC 呼叫
開發者動作
建立 semantic_search.py。
import json
import os
import requests
def call_gateway(payload):
response = requests.post(
os.environ["AGENTCORE_GATEWAY_URL"],
json=payload,
headers={
"Authorization": f"Bearer {os.environ['AGENTCORE_GATEWAY_JWT']}",
"Content-Type": "application/json",
},
timeout=30,
)
response.raise_for_status()
return response.json()
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "x_amz_bedrock_agentcore_search",
"arguments": {"query": "疊對漂移與蝕刻製程製程視窗漂移"},
},
}
print(json.dumps(call_gateway(payload), indent=2))
建立 direct_tool_call.py。
import json
import os
import requests
payload = {
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "process_window_drift",
"arguments": {"query": "Fab-A/Fab-B 良率漂移擴大與貨批流向壓力"},
},
}
response = requests.post(
os.environ["AGENTCORE_GATEWAY_URL"],
json=payload,
headers={
"Authorization": f"Bearer {os.environ['AGENTCORE_GATEWAY_JWT']}",
"Content-Type": "application/json",
},
timeout=30,
)
print(json.dumps(response.json(), indent=2))
商業邏輯
語意搜尋根據意圖尋找相關工具。直接呼叫則驗證選定的工具是否能透過 Gateway 順利執行。
程式碼邏輯
這兩個腳本都發送 JSON-RPC tools/call 請求。一個呼叫內建的搜尋工具;另一個呼叫領域特定的工具。
預期結果
搜尋會回傳排名的工具,而直接呼叫會回傳由 Lambda 支援的結構化實證。
系統設計決策
- 搜尋與直接執行是獨立的測試: 語意搜尋驗證「發現」功能;直接呼叫驗證「執行」功能。將兩者分開有助於隔離驗證、綱要、路由或 Lambda 邏輯中的錯誤。
- JSON-RPC 偵錯路徑: 當 Agent 行為異常時,直接 HTTP 呼叫非常有用。開發人員可以重現精確的 Gateway 請求,而無需將模型推理引入流程。
- Bearer 權杖邊界: Gateway 呼叫包含授權標頭(Headers)。這強化了工具發現與執行是受保護的操作,而非匿名 API。
步驟 7 — 從 Strands Agent 呼叫 Gateway
開發者動作
建立 strands_gateway_agent.py。
import os
import boto3
from botocore.credentials import Credentials
from strands import Agent
from strands.models import BedrockModel
from strands.tools.mcp.mcp_client import MCPClient
from streamable_http_sigv4 import streamablehttp_client_with_sigv4
SERVICE = "bedrock-agentcore"
def assume_gateway_role(role_arn: str):
return boto3.client("sts").assume_role(
RoleArn=role_arn,
RoleSessionName="strands-gateway-agent-hands-on",
DurationSeconds=3600,
)["Credentials"]
def main():
region = os.getenv("AWS_DEFAULT_REGION", "us-east-1")
creds = assume_gateway_role(os.environ["AGENTCORE_GATEWAY_INVOKE_ROLE_ARN"])
mcp_client = MCPClient(lambda: streamablehttp_client_with_sigv4(
url=os.environ["AGENTCORE_GATEWAY_URL"],
credentials=Credentials(
creds["AccessKeyId"],
creds["SecretAccessKey"],
creds["SessionToken"],
),
service=SERVICE,
region=region,
))
with mcp_client:
tools = mcp_client.list_tools_sync()
print("載入的工具:", [tool.tool_name for tool in tools])
agent = Agent(
model=BedrockModel(model_id="amazon.nova-pro-v1:0", temperature=0.2),
tools=tools,
system_prompt=(
"你是一個使用工具的廠務工程自動化助理。 "
"請先使用 Gateway 工具獲取實證。接著綜合分析限制、確認訊號與失效觸發因素。 "
"切勿提供製程發佈建議或自主設備控制指令。"
),
)
result = agent(
"分析因較寬的 Fab-A/Fab-B 良率漂移所引起的疊對漂移、蝕刻製程製程視窗漂移以及 CD-SEM 漂移擴大。"
)
print(result)
if __name__ == "__main__":
main()
商業邏輯
Strands Agent 在撰寫最終綜合分析之前,將 Gateway 工具用作實證來源。
程式碼邏輯
該腳本會扮演(Assume)一個 IAM 角色、建立 SigV4 MCP 傳輸、列出 Gateway 工具、將它們載入到 Strands 中,並調用 Agent。
預期結果
Agent 印出載入的工具並回傳基於工具實證的分析報告。
系統設計決策
- Strands 取用託管的 MCP 工具: Agent 不會直接呼叫 Lambda。Gateway 擁有工具公開、驗證和轉換的所有權。這使得 Agent 獨立於後端實作細節。
- 臨時憑證: Agent 使用扮演角色(Assumed-role)的憑證,減少了長期金鑰的外洩風險。IAM 定義了 Agent 擁有哪些 Gateway 存取權限。
- 實證優先的 Agent 提示詞: 系統提示詞要求在綜合回答前先取得工具實證。這提高了可稽核性,並使輸出更易於評估。
最終開發者檢查清單
- [ ] 本機 MCP 伺服器正常執行。
- [ ] 本機 MCP 用戶端能列出並呼叫工具。
- [ ] 存在 Lambda zip 打包檔案。
- [ ] 已建立 Gateway 及其目標。
- [ ] 語意搜尋能回傳相關工具。
- [ ] 直接 JSON-RPC 工具呼叫成功。
- [ ] Strands Agent 成功載入 Gateway 工具並產生接地(Grounded)的輸出。
額外開發者實作實驗室
這些實驗室擴展了 Gateway MCP 工具架構工作坊,內容涵蓋更深層的偵錯、綱要治理、驗證實作以及 Agent 工具評估。它們刻意與核心建構流程不同,專注於讓工具生態系統具備生產就緒(Production-ready)的能力。
實驗室 A — 為 MCP 工具定義新增綱要語法檢查(Linting)
開發者目標
在向 AgentCore Gateway 註冊工具綱要之前對其進行驗證。
開發者動作
建立 lint_tool_schema.py:
from tool_schema import TOOL_SCHEMA
REQUIRED_TOP_LEVEL = {"name", "description", "inputSchema"}
def lint_tool_schema(schema: list[dict]) -> list[str]:
errors = []
names = set()
for index, tool in enumerate(schema):
missing = REQUIRED_TOP_LEVEL - set(tool.keys())
if missing:
errors.append(f"工具索引 {index} 缺少鍵:{sorted(missing)}")
name = tool.get("name")
if not name:
errors.append(f"工具索引 {index} 的名稱為空")
elif name in names:
errors.append(f"重複的工具名稱:{name}")
names.add(name)
description = tool.get("description", "")
if len(description.split()) < 6:
errors.append(f"工具 {name} 的描述過短,不利於語意搜尋")
input_schema = tool.get("inputSchema", {})
if input_schema.get("type") != "object":
errors.append(f"工具 {name} 的 inputSchema 必須是物件(object)")
if "required" not in input_schema:
errors.append(f"工具 {name} 的 inputSchema 應定義必填欄位")
return errors
if __name__ == "__main__":
errors = lint_tool_schema(TOOL_SCHEMA)
if errors:
print("綱要語法檢查失敗")
print("\n".join(errors))
raise SystemExit(1)
print(f"已驗證 {len(TOOL_SCHEMA)} 個工具綱要")
執行:
python lint_tool_schema.py
商業邏輯
工具綱要(Schema)是 Agent API 的一部分。不良的綱要會降低發現品質,並可能導致執行階段的調用失敗。
程式碼邏輯
語法檢查器會檢查必要欄位、重複的工具名稱、描述品質、物件綱要以及必要的輸入欄位。
預期結果
已驗證 4 个工具綱要
系統設計決策
- 註冊前的綱要品質控制: Gateway 註冊不應該是第一次檢查綱要的地方。本機語法檢查可在變更雲端資源之前,捕獲諸如重複名稱和過短描述等簡單問題。
- 語意搜尋依賴描述品質: 簡短或模糊的描述會降低搜尋索引的實用性。語法檢查器強制執行最低描述品質,因為中介資料對 Agent 而言就是維運行為。
- 對 CI 友善的快速檢查: 當驗證失敗時,腳本會以結束代碼
1 結束,這使得它很容易整合到 CI 流水線(Pipelines)或 pre-commit 勾子(Hooks)中。
實驗室 B — 建構適用於 Gateway 的直接 MCP tools/list 測試器
開發者目標
在涉及 Strands 之前,使用原始 JSON-RPC 偵錯 Gateway 工具發現功能。
開發者動作
建立 gateway_list_tools.py:
import json
import os
import requests
payload = {
"jsonrpc": "2.0",
"id": 100,
"method": "tools/list",
"params": {},
}
response = requests.post(
os.environ["AGENTCORE_GATEWAY_URL"],
json=payload,
headers={
"Authorization": f"Bearer {os.environ['AGENTCORE_GATEWAY_JWT']}",
"Content-Type": "application/json",
},
timeout=30,
)
print("HTTP", response.status_code)
print(json.dumps(response.json(), indent=2))
商業邏輯
在 Agent 能夠呼叫工具之前,工具發現功能必須正常運作。此實驗室可直接驗證 Gateway 的發現功能。
程式碼邏輯
該腳本帶有 Bearer 權杖(Token)向 Gateway 端點發送 JSON-RPC tools/list 請求。
預期結果
回應包含已註冊的 MCP 工具及其綱要。
系統設計決策
- 原始協定偵錯: 當 Strands Agent 的行為令人困惑時,開發人員需要一個更低階的測試。JSON-RPC 呼叫可以將 Gateway 發現功能與模型推理及 Strands 協調隔離。
- 驗證可見性: 該腳本使 Bearer 權杖的要求變得清晰明確。這有助於開發人員區分驗證失敗與工具註冊失敗。
- 維運冒煙測試(Smoke test):
tools/list 可以成為部署冒煙測試,以確認新註冊的 Gateway 目標在註冊後是否可見。
實驗室 C — 新增 Gateway 工具呼叫重放檔案(Replay File)
開發者目標
建立可在偵錯期間重複使用的 JSON-RPC 測試承載資料(Payloads)。
開發者動作
建立 requests/etch-process_drift_call.json:
{
"jsonrpc": "2.0",
"id": 201,
"method": "tools/call",
"params": {
"name": "process_window_drift",
"arguments": {
"query": "Fab-A/Fab-B 良率漂移擴大、疊對漂移以及貨批流向壓力"
}
}
}
建立 replay_gateway_request.py:
import json
import os
import sys
import requests
path = sys.argv[1]
payload = json.load(open(path, encoding="utf-8"))
response = requests.post(
os.environ["AGENTCORE_GATEWAY_URL"],
json=payload,
headers={
"Authorization": f"Bearer {os.environ['AGENTCORE_GATEWAY_JWT']}",
"Content-Type": "application/json",
},
timeout=30,
)
print(json.dumps(response.json(), indent=2))
執行:
mkdir -p requests
python replay_gateway_request.py requests/etch-process_drift_call.json
商業邏輯
重放檔案為偵錯工具行為和展示預期的 Gateway 回應提供了可重複的實證。
程式碼邏輯
重放腳本從磁碟載入 JSON 承載資料並將其傳送到 Gateway。
預期結果
相同的工具呼叫可以重複執行,而無需重寫 Python 程式碼。
系統設計決策
- 可重現的工具偵錯: 儲存的 JSON-RPC 承載資料使得重現錯誤和比較跨部署的回應變得容易。當工具綱要或 Lambda 邏輯變更時,這非常有用。
- 請求與執行器的分離: 請求檔案是資料,而 Python 腳本是通用的執行器。這允許許多測試案例重複使用同一個用戶端。
- 對文件有用: 重放檔案可兼作其他需要了解如何直接呼叫 Gateway 工具的開發人員的範例。
實驗室 D — 為 Strands 回應新增工具結果標準化
開發者目標
在 Agent 綜合最終答案之前,標準化工具輸出。
開發者動作
建立 tool_result_normalizer.py:
import json
def normalize_tool_result(raw_result) -> dict:
if isinstance(raw_result, dict):
return raw_result
if isinstance(raw_result, str):
try:
return json.loads(raw_result)
except json.JSONDecodeError:
return {"raw_text": raw_result}
if isinstance(raw_result, list):
return {"items": raw_result}
return {"repr": repr(raw_result)}
在偵錯程式碼中使用它:
from tool_result_normalizer import normalize_tool_result
# 假設 result 來自於之前的某個工具呼叫
normalized = normalize_tool_result(result)
print(normalized)
商業邏輯
Agent 可能會收到不同形狀的工具輸出。標準化使下游的實證處理變得可以預測。
程式碼邏輯
此輔助函式將字典、JSON 字串、清單和未知物件轉換為統一的字典形狀。
預期結果
工具輸出可以被一致地記錄、評估和轉譯。
系統設計決策
- 可預測的實證格式: 在可能的情況下,工具輸出應該是機器可讀的。標準化允許用戶端和評估流程檢查欄位,而不依賴於每個後端回傳完全相同的形狀。
- 防禦性整合: Gateway 目標可能會演進或回傳非預期的承載資料。標準化可防止脆弱的 Agent 包裝器(Wrappers)因微小的輸出形狀變更而失敗。
- 評估就緒性: 一致的工具實證使檢查最終 Agent 回應是否使用了預期的工具和訊號變得更加容易。
實驗室 E — 新增語意搜尋比較測試
開發者目標
比較不同使用者意圖的語意搜尋結果,並驗證預期工具是否出現在前幾名結果中。
開發者動作
建立 semantic_search_eval.py:
import json
import os
import requests
CASES = [
{"query": "儲存庫吞吐量壓力與 Hot-lot 急件偏好", "expected": "throughput_throughput"},
{"query": "CDS 擴大與良率損失風險", "expected": "metrology_drift_widening"},
{"query": "製程能力與疊對誤差漂移", "expected": "process_window_drift"},
{"query": "疊對保留量與跨廠 WIP", "expected": "tool_to_tool_mismatch"},
]
def search(query: str) -> list[str]:
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "x_amz_bedrock_agentcore_search",
"arguments": {"query": query},
},
}
response = requests.post(
os.environ["AGENTCORE_GATEWAY_URL"],
json=payload,
headers={"Authorization": f"Bearer {os.environ['AGENTCORE_GATEWAY_JWT']}"},
timeout=30,
).json()
tools = response.get("result", {}).get("structuredContent", {}).get("tools", [])
return [tool.get("name") for tool in tools]
for case in CASES:
names = search(case["query"])
passed = case["expected"] in names[:3]
print(case["query"], "通過" if passed else "失敗", names[:3])
商業邏輯
語意搜尋品質決定了 Agent 能否針對業務語言請求找到正確的工具。
程式碼邏輯
該腳本執行多個搜尋查詢,並檢查預期工具是否出現在前三個結果中。
預期結果
每個測試都會印出 通過 或 失敗 以及前三個匹配的工具。
系統設計決策
- 搜尋品質作為可測試行為: 語意搜尋應該像其他功能一樣進行驗證。如果描述或綱要發生變更,搜尋品質可能會退化。
- 基於意圖的測試案例: 測試案例使用業務語言而非精確的工具名稱。這測試了中介資料是否能支援真實的使用者提示詞。
- Top-K 容忍度: 檢查前三個結果比要求每次都精準命中第一個結果更符合實際。語意檢索對相似工具的排名可能略有不同,但預期的工具仍應保持可發現性。
實驗室 F — 新增最小權限環境檢查清單
開發者目標
在晉升到生產環境(Production promotion)之前,為 Gateway 工具架構建立一個運維檢查清單。
開發者動作
建立 docs/gateway_operational_checklist.md:
# Gateway 運維檢查清單
## 身分識別與授權
- [ ] Gateway 使用 CUSTOM_JWT 授權方。
- [ ] 允許的用戶端(Allowed clients)僅限於經核准的應用程式用戶端。
- [ ] 權杖(Token)生命週期與重新整理(Refresh)流程已記錄在案。
## IAM 與目標存取
- [ ] Gateway 角色只能呼叫經核准的 Lambda 目標。
- [ ] Lambda 資源策略不允許廣泛的公開調用。
- [ ] 開發人員憑證未嵌入程式碼中。
## 工具治理
- [ ] 工具綱要在註冊前皆經過語法檢查(Linted)。
- [ ] 工具描述長度足夠,可支援語意搜尋。
- [ ] 工具輸出為結構化且可稽核。
- [ ] 危險或執行類型的工具未在此分析閘道器中註冊。
## 可觀察性
- [ ] 監控 Gateway 目標調用錯誤。
- [ ] Lambda 日誌包含請求 ID(Request IDs)或工具名稱。
- [ ] 綱要變更後,語意搜尋測試皆能通過。
商業邏輯
檢查清單可幫助平台團隊在廣泛公開工具之前,審查安全性、治理與可觀察性。
程式碼邏輯
這是一份 Markdown 文件,但它會成為拉取請求(Pull requests)和生產環境審查的運維構件。
預期結果
團隊擁有一個針對 Gateway 工具架構的可重複整備度(Readiness)檢查清單。
系統設計決策
- 以文件作為控制手段: 運維檢查清單可防止重要的生產環境考量成為部落知識(Tribal knowledge)。當有多個團隊發佈工具時,這特別有用。
- 專注於最小權限: Gateway 集中了工具存取,因此必須仔細審查 IAM 和 JWT 邊界。檢查清單使這些邊界變得清晰明確。
- 晉升閘門(Promotion gate): 在 Gateway 目標從工作坊移至共享開發或生產環境之前,此檢查清單可作為發佈要求。