Chào mừng bạn đến với phần 3 cực kỳ hấp dẫn của series bài viết về Amazon Bedrock AgentCore Gateway! Trong những phần trước, chúng ta đã cùng nhau khám phá AgentCore Gateway – một "cánh cổng thần kỳ" giúp biến các API và hàm Lambda hiện có thành những công cụ sẵn sàng cho Agent AI, mở ra khả năng truy cập thống nhất qua nhiều giao thức, bao gồm cả Model Context Protocol (MCP), và khả năng tự động khám phá công cụ trong thời gian chạy. Ở phần 2, chúng ta đã biến một REST API Gateway thành công cụ tương thích MCP. Hôm nay, chúng ta sẽ "độ" tiếp các hàm Lambda của mình để chúng cũng trở thành những "trợ thủ đắc lực" cho các AI Agent thông qua AgentCore Target! Chúng ta sẽ tiếp tục sử dụng hai hàm Lambda quen thuộc: `GetOrderByID` và `GetOrdersByCreatedDates`. Hãy cùng bắt đầu hành trình biến hóa này nhé!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/gVj3Y7o.png' alt='Sơ đồ tổng quan AgentCore Gateway và Lambda'>Bạn muốn "hô biến" các hàm AWS Lambda hiện có của mình thành công cụ MCP qua Bedrock AgentCore Gateway? Nghe có vẻ phức tạp nhưng thực ra chỉ là vài bước cấu hình thôi! Để minh họa, chúng ta sẽ tái sử dụng ứng dụng mẫu và API Gateway đã được mô tả chi tiết trong bài viết "Serverless applications with Java and Aurora DSQL - Part 1". Bạn có thể tìm thấy toàn bộ mã nguồn tại đây.Chúng ta sẽ dùng một Jupyter Notebook Python có sẵn từ kho lưu trữ GitHub chính thức của AWS (amazon-bedrock-agentcore-samples) và tùy chỉnh nó để phù hợp với yêu cầu của mình. Tôi cũng đã chia sẻ phiên bản cuối cùng của playbook này trên GitHub cá nhân của mình.Đây là kiến trúc tổng quan về cách chúng ta sẽ biến đổi các hàm AWS Lambda hiện có thành công cụ MCP sử dụng Bedrock AgentCore Gateway:<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/tY7g8Y4.png' alt='Kiến trúc biến Lambda thành công cụ MCP'>Quy trình hoạt động của Gateway để kết nối các agent của bạn với các công cụ bên ngoài bao gồm các bước sau:<ul><li><b>Tạo công cụ cho Gateway của bạn:</b> Định nghĩa các công cụ bằng schemas, bao gồm ARN của hàm Lambda, các tham số công cụ và kiểu dữ liệu của chúng.</li><li><b>Tạo một Gateway endpoint:</b> Xây dựng cổng gateway sẽ là điểm truy cập MCP với xác thực đầu vào.</li><li><b>Thêm target vào Gateway của bạn:</b> Cấu hình các target là hàm Lambda, xác định cách gateway định tuyến yêu cầu đến các công cụ cụ thể. Tất cả các hàm Lambda này sẽ trở thành một công cụ tương thích MCP và sẽ được cung cấp thông qua URL của Gateway endpoint của bạn. Cấu hình ủy quyền IAM đầu ra cho mỗi target Lambda.</li><li><b>Cập nhật mã agent của bạn:</b> Kết nối agent của bạn với Gateway endpoint để truy cập tất cả các công cụ đã cấu hình thông qua giao diện MCP thống nhất.</li></ul>Để thực hiện hướng dẫn này, bạn cần chuẩn bị:<ul><li>Jupyter Notebook (với kernel Python)</li><li>`uv` (một công cụ quản lý package Python siêu nhanh)</li><li>Thông tin đăng nhập AWS (đã cấu hình trong `.aws\credentials` là đủ)</li><li>Amazon Cognito</li></ul>Bây giờ, chúng ta sẽ cùng nhau đi từng bước qua các phần quan trọng của Python Jupyter Notebook. Để chạy được nó, bạn cũng cần tải file `agent_core_utils.py` và đặt nó cùng thư mục với notebook. Tôi đã copy file này từ kho mẫu của AWS để tiện tùy chỉnh sau này.<h3>1. Cài đặt các thư viện cần thiết</h3>Bước đầu tiên luôn là kiểm tra và cài đặt các 'nguyên liệu' cơ bản! Chúng ta sẽ kiểm tra xem `uv` đã có chưa, sau đó dùng nó để cài `botocore` và `boto3`. Đơn giản phải không nào?<h3>2. Cấu hình Môi trường</h3>Tiếp theo, chúng ta đặt biến môi trường `AWS_DEFAULT_REGION` là 'us-east-1' (tất nhiên bạn có thể chọn một region khác mà AgentCore được hỗ trợ). Nếu bạn đã cấu hình `AWS_ACCESS_KEY_ID` và `AWS_SECRET_ACCESS_KEY` trong `.aws\credentials` thì khỏi cần đặt lại nhé, các client của AWS sẽ tự động nhận diện từ đó!```pythonimport osimport agent_core_utilsos.environ['AWS_DEFAULT_REGION'] = 'us-east-1'```<h3>3. Tạo hoặc Tái sử dụng IAM Role cho AgentCore Gateway</h3>Đây là bước quan trọng để cấp quyền cho Gateway. Chúng ta sẽ dùng `agent_core_utils` để tạo một IAM role cho AgentCore Gateway, hoặc tái sử dụng role đã tạo ở phần 2. Role này sẽ cho phép Gateway thực hiện các thao tác cần thiết.<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47m71a784rxwk1frqgyg.png' alt='IAM role và policy cho AgentCore Gateway'>```pythonimport agent_core_utilsagentcore_gateway_iam_role = agent_core_utils.create_agentcore_gateway_role("sample-lambdagateway")print("Agentcore gateway role ARN: ", agentcore_gateway_iam_role['Role']['Arn'])```Sau khi chạy bước này, IAM role và policy của bạn sẽ trông như thế này trong AWS.<h3>4. Cấu hình Amazon Cognito User Pool</h3>Để đảm bảo an toàn, chúng ta cần một cơ chế xác thực. Bước này sẽ tạo một Cognito User Pool (nếu chưa có, hoặc tái sử dụng nếu bạn đã tạo ở phần 2). Chúng ta cũng sẽ tạo hoặc lấy lại client ID và client secret cho ứng dụng machine-to-machine (M2M) của Cognito. Các thông tin này cực kỳ quan trọng để tạo ra token xác thực khi Agent muốn "nói chuyện" với Gateway.<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7is538yqn95ue5c7lo4u.png' alt='Cognito User Pool đã cấu hình'>```pythonimport osimport boto3import requestsimport timefrom botocore.exceptions import ClientErrorREGION = os.environ['AWS_DEFAULT_REGION']USER_POOL_NAME = "sample-agentcore-gateway-pool"RESOURCE_SERVER_ID = "sample-agentcore-gateway-id"RESOURCE_SERVER_NAME = "sample-agentcore-gateway-name"CLIENT_NAME = "sample-agentcore-gateway-client"SCOPES = [ {"ScopeName": "gateway:read", "ScopeDescription": "Read access"}, {"ScopeName": "gateway:write", "ScopeDescription": "Write access"}]scopeString = f"{RESOURCE_SERVER_ID}/gateway:read {RESOURCE_SERVER_ID}/gateway:write"cognito = boto3.client("cognito-idp", region_name=REGION)print("Creating or retrieving Cognito resources...")user_pool_id = agent_core_utils.get_or_create_user_pool(cognito, USER_POOL_NAME)print(f"User Pool ID: {user_pool_id}")agent_core_utils.get_or_create_resource_server(cognito, user_pool_id, RESOURCE_SERVER_ID, RESOURCE_SERVER_NAME, SCOPES)print("Resource server ensured.")client_id, client_secret = agent_core_utils.get_or_create_m2m_client(cognito, user_pool_id, CLIENT_NAME, RESOURCE_SERVER_ID)print(f"Client ID: {client_id}")# Get discovery URLcognito_discovery_url = f'https://cognito-idp.{REGION}.amazonaws.com/{user_pool_id}/.well-known/openid-configuration'print(cognito_discovery_url)```Sau khi thực hiện, Cognito Pool của chúng ta sẽ hiển thị như hình trên trong AWS (các thông tin nhạy cảm như ARN và URL khóa ký token đã được ẩn đi).<h3>5. Tạo AgentCore Gateway</h3>Đây là trái tim của hệ thống! Chúng ta sẽ tạo một Gateway với tên `LambdaOrderGateway`, sử dụng Cognito Authorizer (không dùng CMK) dựa trên user pool đã tạo ở bước trước. Giao thức sẽ là MCP. Gateway này sẽ là điểm kết nối cho các Lambda của chúng ta.<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frod0lhly9nuzc5ki20n0.png' alt='AgentCore Gateway đã tạo'>```pythonimport boto3gateway_client = boto3.client('bedrock-agentcore-control', region_name = os.environ['AWS_DEFAULT_REGION'])auth_config = { "customJWTAuthorizer": { "allowedClients": [client_id], # Client MUST match with the ClientId configured in Cognito. Example: 7rfbikfsm51j2fpaggacgng84g "discoveryUrl": cognito_discovery_url }}create_response = gateway_client.create_gateway(name='LambdaOrderGateway', roleArn = agentcore_gateway_iam_role['Role']['Arn'], # The IAM Role must have permissions to create/list/get/delete Gateway protocolType='MCP', authorizerType='CUSTOM_JWT', authorizerConfiguration=auth_config, description='AgentCore Gateway with AWS Lambda target type')print(create_response)gatewayID = create_response["gatewayId"]gatewayURL = create_response["gatewayUrl"]print(gatewayID)```Sau khi thực hiện bước này, AgentCore Gateway đã tạo sẽ xuất hiện như hình trên trong AWS.<h3>6. Tạo AgentCore Gateway Targets (cho từng hàm Lambda)</h3>Bây giờ là lúc kết nối các "trợ thủ" Lambda của chúng ta! Chúng ta sẽ tạo hai AgentCore Gateway Targets, mỗi target cho một hàm Lambda hiện có. Công việc này gồm hai phần chính: cấu hình target Lambda và cấu hình xác thực.<h4>6.1. Cấu hình Target Lambda cho `GetOrderByIdWithJava21Lambda`</h4>Chúng ta cần cung cấp ARN của hàm Lambda (nhớ thay bằng ARN của bạn nhé!), sau đó định nghĩa tên và mô tả của công cụ MCP. Quan trọng nhất là `inputSchema` – nơi chúng ta chỉ định các tham số đầu vào (ở đây là `id` cho order id) và đánh dấu chúng là `required` (bắt buộc).```pythonorder_by_id_lambda_target_config = { "mcp": { "lambda": { "lambdaArn": '${YourGetOrderByIdLambdaFunctionARN}', # Thay thế bằng ARN Lambda của bạn "toolSchema": { "inlinePayload": [ { "name": "get_order_by_id_tool", "description": "tool to get the order by id", "inputSchema": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] } } ] } } }}```<h4>6.2. Cấu hình Target Lambda cho `GetOrdersByCreatedDatesLambda`</h4>Tương tự, với hàm `GetOrdersByCreatedDatesLambda`, chúng ta có hai tham số bắt buộc là `startDate` và `endDate`.<h4>6.3. Cấu hình Xác thực</h4>Phần này khá đơn giản, chúng ta chỉ cần đặt kiểu nhà cung cấp thông tin xác thực là `GATEWAY_IAM_ROLE`.```jsoncredential_config = [ { "credentialProviderType" : "GATEWAY_IAM_ROLE" }]```<h4>6.4. Tạo các AgentCore Targets</h4>Cuối cùng, chúng ta tạo hai AgentCore Targets bằng cách truyền cấu hình target Lambda và cấu hình xác thực đã chuẩn bị.Ví dụ cho target `GetOrderByIdLambda`:```pythonorder_by_id_targetname='GetOrderByIdLambda'response = gateway_client.create_gateway_target( gatewayIdentifier=gatewayID, name=order_by_id_targetname, description='Order by id Lambda Target', targetConfiguration=order_by_id_lambda_target_config, credentialProviderConfigurations=credential_config)```Đây là toàn bộ đoạn mã để thực thi hai target:```pythonorder_by_id_lambda_target_config = { "mcp": { "lambda": { "lambdaArn": '${YourGetOrderByIdLambdaFunctionARN}', # Thay thế bằng ARN Lambda của bạn "toolSchema": { "inlinePayload": [ { "name": "get_order_by_id_tool", "description": "tool to get the order by id", "inputSchema": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] } } ] } } }}order_by_created_dates_lambda_target_config = { "mcp": { "lambda": { "lambdaArn": '${YourGetOrdersByCreatedDatesLambdaFunctionARN}', # Thay thế bằng ARN Lambda của bạn "toolSchema": { "inlinePayload": [ { "name": "get_orders_by_created_dates_tool", "description": "tool to get the order by created dates", "inputSchema": { "type": "object", "properties": { "startDate": { "type": "string" }, "endDate": { "type": "string" } }, "required": ["startDate","endDate"] } } ] } } }}credential_config = [ { "credentialProviderType" : "GATEWAY_IAM_ROLE" }]order_by_id_targetname='GetOrderByIdLambda'response = gateway_client.create_gateway_target( gatewayIdentifier=gatewayID, name=order_by_id_targetname, description='Order by id Lambda Target', targetConfiguration=order_by_id_lambda_target_config, credentialProviderConfigurations=credential_config)order_by_id_targetname='GetOrderByCreatedDatesLambda'response = gateway_client.create_gateway_target( gatewayIdentifier=gatewayID, name=order_by_id_targetname, description='Orders by created dates Lambda Target', targetConfiguration=order_by_created_dates_lambda_target_config, credentialProviderConfigurations=credential_config)```Sau khi chạy bước này, các AgentCore Gateway Targets của bạn sẽ được tạo ra như thế này:<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqv5n5huvkxi0s4pjwjl.png' alt='AgentCore Gateway Targets'>Và chi tiết hơn cho từng target:<ul><li>**`GetOrderByIdLambda`:**<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzzkc4ar46u8mna22m65.png' alt='Cấu hình GetOrderByIdLambda Target'></li><li>**`GetOrderByCreatedDatesLambda`:**<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp0nwfg5qgaaw10cgdt9.png' alt='Cấu hình GetOrderByCreatedDatesLambda Target'></li></ul><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvw6ng37bi60q4vz9j27.png' alt='Chi tiết Target 1'><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2rjjkisqa55jr05wg90.png' alt='Chi tiết Target 2'>Vậy là chúng ta đã hoàn tất việc tạo và cấu hình AgentCore Gateway! Bây giờ, hãy cùng "trò chuyện" với agent xem sao nhé.<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5x6q57pyxz4yaptd6rs.png' alt='Giao diện View invocation code'>Bạn có thể sao chép mã cho "Python with Requests", "MCP Python SDK", hoặc "Strands MCP Client" từ phần "View invocation code" của AgentCore Gateway.Trong trường hợp chúng ta sử dụng notebook này, nơi chúng ta dùng Strands MCP Client, bạn cần lặp lại các bước 2 (đặt AWS Region mặc định và import `agent_core_utils`) và bước 4 (lấy lại Cognito Pool hiện có để đặt các biến `client_id`, `client_secret` và `cognito_discovery_url`).Chúng ta sẽ chạy agent cục bộ và khám phá AgentCore Runtime trong một series bài viết khác. Amazon Bedrock AgentCore Runtime cung cấp một môi trường lưu trữ an toàn, không máy chủ và được xây dựng chuyên biệt để triển khai và chạy các agent hoặc công cụ AI. Đây là một ví dụ về cách triển khai Strands Agents lên Amazon Bedrock AgentCore Runtime.<h4>Lấy Token Xác thực</h4>Đầu tiên, chúng ta cần lấy token xác thực. Đây là chìa khóa để agent có thể "trò chuyện" với Gateway.```pythonimport agent_core_utilsprint("Requesting the access token from Amazon Cognito authorizer...May fail for some time till the domain name propagation completes")token_response = agent_core_utils.get_token(user_pool_id, client_id, client_secret,scopeString,REGION)token = token_response["access_token"]print("Token response:", token)```<h4>Tạo MCP Client và Agent</h4>Tiếp theo, chúng ta tạo một MCP client và một agent. Agent này sẽ sử dụng mô hình Amazon Bedrock (`us.amazon.nova-pro-v1:0` với `temperature=0.7`). Bạn có thể thử nghiệm với các cài đặt này. Strands Agent hỗ trợ tất cả các mô hình, kể cả những mô hình chạy cục bộ như Ollama. Nhưng nhớ đảm bảo rằng nếu dùng Amazon Bedrock, mô hình đó phải được kích hoạt trong Model Access nhé.Sau đó, chúng ta yêu cầu client liệt kê tất cả các công cụ (qua lệnh `client.list_tools_sync`). Đừng quên đặt `gateway_url` của AgentCore Gateway đã tạo trước đó.```pythonfrom strands import Agentimport loggingfrom strands.models import BedrockModelfrom strands.tools.mcp.mcp_client import MCPClientfrom mcp.client.streamable_http import streamablehttp_clientimport osimport requestsimport jsondef fetch_access_token(): return token;def create_streamable_http_transport(mcp_url: str, access_token: str): return streamablehttp_client(mcp_url, headers={"Authorization": f"Bearer {token}"})def get_full_tools_list(client): """ List tools w/ support for pagination """ more_tools = True tools = [] pagination_token = None while more_tools: tmp_tools = client.list_tools_sync(pagination_token=pagination_token) tools.extend(tmp_tools) if tmp_tools.pagination_token is None: more_tools = False else: more_tools = True pagination_token = tmp_tools.pagination_token return toolsdef run_agent(mcp_url: str, access_token: str): model = BedrockModel( model_id="us.amazon.nova-pro-v1:0", temperature=0.7) mcp_client = MCPClient(lambda: create_streamable_http_transport(mcp_url, access_token)) with mcp_client: tools = get_full_tools_list(mcp_client) print(f"Found the following tools: {[tool.tool_name for tool in tools]}")gateway_url = "${YOUR_Gateway_resource_URL}"run_agent(gateway_url, fetch_access_token())```Khi chạy đoạn mã này, kết quả sẽ hiển thị danh sách các công cụ mà agent đã tìm thấy:```textFound the following tools: ['GetOrderByCreatedDatesLambda_get_orders_by_created_dates_tool', 'GetOrderByIdLambda_get_order_by_id_tool']```Tuyệt vời! Agent đã nhận diện được hai hàm Lambda của chúng ta là các công cụ hợp lệ. Bây giờ, chúng ta sẽ làm tương tự như ở phần 2: "trò chuyện" với cùng hàm Lambda, nhưng lần này là trực tiếp qua AgentCore Gateway chứ không phải qua Open API.Tôi đã tạo sẵn một số đơn hàng và sản phẩm trong cơ sở dữ liệu. Giờ thì hãy tạo Strands Agent và hỏi về đơn hàng có ID là `12345` nhé!Dưới đây là đoạn mã bổ sung liên quan. Chúng ta truyền thông tin về mô hình Bedrock đã tạo và các công cụ MCP đã lấy được cho Strands Agent:```pythonwith mcp_client: tools = get_full_tools_list(mcp_client) print(f"Found the following tools: {[tool.tool_name for tool in tools]}") agent = Agent(model=model, tools=tools) agent("Give me the information about order with id 12345")```Khi chạy đoạn mã này, bạn sẽ thấy... không có gì cả! Agent bị "treo". Hãy cùng kiểm tra CloudWatch xem có chuyện gì nhé. Hàm Lambda (viết bằng Java) đã được thực thi (nghĩa là mapping hoạt động), nhưng một ngoại lệ đã được ném ra:<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbt022npm8mhj2fxnhx9.png' alt='Lỗi NullPointerException trong Lambda'>Lý do là `requestEvent.getPathParameters()` bị `null`, trong khi chúng ta mong đợi nó chứa tham số "id":```java@Overridepublic APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent requestEvent, Context context) { String id = requestEvent.getPathParameters().get("id");...```Mặc dù đối tượng `APIGatewayProxyRequestEvent requestEvent` được tạo, nó lại hoàn toàn rỗng (không có thuộc tính nào được đặt: không có tham số đường dẫn, không có chuỗi truy vấn, v.v.). Vậy chuyện gì đã xảy ra? Hàm Lambda hiện có của chúng ta được kích hoạt bởi sự kiện HTTP GET của API Gateway, nhưng AgentCore Gateway không thể biết trigger nào được cấu hình (nó có thể là tất cả các trigger có thể như SQSEvent) và không thể đặt các tham số một cách chính xác.Với mong muốn tái sử dụng hoàn toàn hàm Lambda mà không cần sửa đổi, tôi đã hy vọng có một cấu hình nào đó để truyền vào trong trường hợp này (loại sự kiện là gì và đặt các thuộc tính công cụ ở đâu: dưới dạng HTTP path, query parameters, hay trong HTTP body...). Vì AgentCore hiện đang ở bản preview, tôi sẽ đề xuất loại thay đổi này trước khi ra mắt chính thức. Nhưng hiện tại, thật tiếc là tôi chưa tìm thấy cách nào để tái sử dụng hàm Lambda với một trigger cụ thể làm tham số.Điều tôi tìm thấy là định dạng đầu vào của hàm Lambda, trong đó nói rằng các tham số đầu vào sẽ được truyền vào hàm Lambda dưới dạng cặp khóa-giá trị trong một map/dictionary. Tôi cho rằng vấn đề này có thể chỉ liên quan đến một số runtime Lambda được quản lý nhất định như Java, và không liên quan đến các runtime khác như Python, nơi hàm Lambda đã nhận đối tượng sự kiện kiểu map hoặc dictionary.Vì vậy, tôi đã viết 2 hàm Lambda mới: `GetOrderById2Handler` và `GetOrdersByCreatedDates2Handler` để sử dụng `Map` trong Java làm kiểu sự kiện đầu vào cho Lambda. Các điều chỉnh cần thực hiện cho các hàm Lambda ban đầu là khá nhỏ. Đây là một ví dụ về cách nó hoạt động:```java@Overridepublic APIGatewayProxyResponseEvent handleRequest(Map<String, String> params, Context context) { String id = params.get("id"); .....```Vì vậy, hãy nhớ thay đổi ARN của các hàm Lambda sang các hàm mới này khi bạn tạo AgentCore Gateway Lambda Targets ở bước 6 nhé!Bây giờ, hãy "trò chuyện" lại với agent:```pythonwith mcp_client: tools = get_full_tools_list(mcp_client) print(f"Found the following tools: {[tool.tool_name for tool in tools]}") agent = Agent(model=model, tools=tools) agent("Give me the information about order with id 12345")```Và đây là kết quả!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q00quick84qtkmhgl7e.png' alt='Agent phản hồi về đơn hàng theo ID'>Tuyệt vời! Công cụ `getOrderById` đã được xác định chính xác và chúng ta đã nhận được thông tin chính xác về đơn hàng từ đầu ra của hàm Lambda.Hãy tiếp tục hỏi agent những câu hỏi khác như chúng ta đã làm ở phần 2:```pythonagent('Can you list orders created between 1 of August 2025 5am and 5 of August 2025 3am. ''Please use the following date format, for example: 2025-08-02T19:50:55')```Ở đây, chúng ta muốn lấy danh sách đơn hàng được tạo trong một khoảng thời gian cụ thể và gợi ý cho agent về định dạng ngày tháng. Hãy cùng xem kết quả:<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcq89m2ebyt12njyw5ss.png' alt='Agent phản hồi về đơn hàng theo ngày tạo'>Lại một lần nữa, công cụ `getOrdersByCreatedDates` đã được nhận diện chính xác và các ngày tháng đã được định dạng đúng (tôi đã kiểm tra trong log). Chúng ta đã nhận được thông tin chính xác về các đơn hàng. Tôi đã giới hạn số lượng đơn hàng trả về là 10 trong câu lệnh SQL để tiết kiệm token đầu ra. Và tôi cũng đã đặt lại timestamp tạo cho đơn hàng thành một giá trị nhất định. Nhưng câu trả lời hoàn toàn chính xác!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt8f9cbrz1ok9q55sirt.png' alt='Kết quả chi tiết đơn hàng theo ngày tạo'>Hãy hỏi agent thêm một câu hỏi nữa:```pythonagent('What is the total value of all these orders together?')```Câu trả lời hoàn toàn chính xác!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbgwuquh4ewuflgbpvlc0.png' alt='Agent tính tổng giá trị đơn hàng'>Đúng vậy, agent đã tự động tính tổng giá trị của tất cả 10 đơn hàng (10*350) một cách chính xác.Thử hỏi về một đơn hàng không tồn tại xem agent xử lý thế nào nhé:```pythonagent("Give me the information about order with id 1234589090")```Chúng ta nhận được kết quả chính xác, vì hàm Lambda đã xử lý loại yêu cầu này mà không ném ra lỗi nào:<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5rxitmowm2gx7v7vnr3.png' alt='Agent phản hồi về đơn hàng không tồn tại'>Có một điều tôi nhận thấy, tương tự như phần I đã mô tả khi expose Open API làm target cho AgentCore Gateway, đó là trường hợp hàm Lambda gặp lỗi (ví dụ như Nullpointer exception). Trong trường hợp đó, Agent không trả về bất cứ điều gì và tiếp tục "suy nghĩ" trong nhiều phút, buộc tôi phải dừng nó. Chắc chắn vẫn còn rất nhiều điều để thử nghiệm và khám phá. Tôi sẽ dành phần này cho bạn đọc. Nhưng đây là một cái nhìn đầu tiên về chức năng của AgentCore Gateway với hàm Lambda là Target.Cuối cùng, hãy cùng xem xét một số chỉ số CloudWatch hữu ích được cung cấp cho Amazon Bedrock AgentCore Gateway:<h4>Đối với các hoạt động `ListMemory` và `InitializeMcp`:</h4><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23volrpjkdkakkosuvcn.png' alt='CloudWatch Metrics cho ListMemory và InitializeMcp'><h4>Đối với hoạt động `ListToolsMcp`:</h4><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuffj66ct5q6x6y22dcva.png' alt='CloudWatch Metrics cho ListToolsMcp'><h4>Đối với hoạt động `CallToolMcp`:</h4><img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wnv1ybjxe2foxa69qej.png' alt='CloudWatch Metrics cho CallToolMcp'>Trong phần này của series bài viết, chúng ta đã cùng nhau tìm hiểu cách "biến hình" hàm Lambda thành một AgentCore Target. Chúng ta đã sử dụng lại các hàm Lambda quen thuộc (`GetOrderByID` và `GetOrdersByCreatedDates`) mà ở phần 2 đã expose qua Open API thông qua API Gateway. Và đặc biệt, chúng ta đã dùng Strands MCP Client để "giao tiếp" với AgentCore Gateway endpoint này. Hy vọng bạn đã có một cái nhìn rõ nét và thú vị về cách "mở khóa" tiềm năng của Lambda với AI Agent!
Khám phá cách nâng cấp công cụ AI đa tác tử với 'vòng mục tiêu' thông minh, khả năng truy cập tệp tin (Ref Files) và tích hợp hệ thống RAG (Retrieval-Augmented Generation) cùng Qdrant, OpenAI embeddings. Bài viết đi sâu vào thiết kế persona linh hoạt, quy trình RAG chi tiết và trình diễn ứng dụng thực tế trong thẩm định bảo hiểm, lập kế hoạch chăm sóc, giúp AI trở nên 'thông minh' và 'trợ lý' đắc lực hơn bao giờ hết.