AWS Builder Workshop

使用 AgentCore 與 Strands 建構:閘道廠務工程 MCP 工具架構開發者工作坊

工作坊摘要: 開發人員將建構一個託管的 Gateway MCP 工具架構,連結本機 MCP 原型設計、Lambda 支援的工具、語意搜尋以及 Strands Agent 的調用。本工作坊將逐步引導完成綱要(Schema)設計、本機發現測試(Local discovery tests)、雲端目標註冊、JSON-RPC 偵錯以及 SigV4 傳輸整合。團隊最終將建立一個可擴展的工具治理模式,在複雜的多團隊平台工程環境中,為 AWS 上的 Agent 提供可發現、安全且具備實證導向(Evidence-oriented)的工具集。

使用 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. 開發者學習目標

開發人員將學會如何:

  1. 設計物件導向的 Agent 工具名稱與綱要(Schema)。
  2. 建構本機可串流的 HTTP MCP 工具伺服器。
  3. 在部署到雲端前測試 MCP 工具發現(Discovery)。
  4. 實作以 Lambda 為後端的工具商業邏輯。
  5. 在 Amazon Bedrock AgentCore Gateway 中註冊 Lambda 工具。
  6. 啟用語意工具搜尋。
  7. 使用 SigV4 傳輸從 Strands Agent 呼叫 Gateway 工具。
  8. 新增直接的 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–80Lambda 目標打包並部署或準備工具後端
80–100Gateway 目標建立 MCP Gateway 與 Lambda 目標
100–110語意搜尋搜尋工具並回傳相關工具
110–120Strands AgentAgent 呼叫 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 讀取 toolNamearguments,驗證工具,並回傳 JSON。打包腳本會建立一個 zip 構件(Artifact)。

預期結果

lambda_function.zip 已準備就緒,可用於部署或用於預先準備好的工作坊啟動腳本。

系統設計決策

  • Lambda 作為後端邊界: Gateway 負責公開工具,而 Lambda 擁有確定性的商業邏輯。這將模型推理與後端執行分離,使工具行為可測試且可觀察。
  • 共享的 Handler 對應表: 基於字典的路由保持了工作坊範例的精簡,同時展示 historical 如何將多個工具對應到單一 Lambda 目標。生產系統隨後可將這些 Handler 拆分。
  • 結構化的回應內文: 回傳 toolquerysignalssummary 可為 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 目標從工作坊移至共享開發或生產環境之前,此檢查清單可作為發佈要求。