From bf7ea3d25177e0af2e052eb092a5225f39ba744e Mon Sep 17 00:00:00 2001 From: kimnamu Date: Sat, 13 Jun 2026 23:10:30 +0900 Subject: [PATCH] feat(event_handler): allow custom serializer on BedrockAgentResolver BedrockAgentResolver did not expose the `serializer` parameter that its parent ApiGatewayResolver and its sibling BedrockAgentFunctionResolver already accept, so there was no way to override the default `ensure_ascii=True` serialization. Non-ASCII agent responses (e.g. Korean/Japanese/emoji) were therefore always \uXXXX-escaped in responseBody.body. Expose the existing parent `serializer` argument and pass it through to super().__init__, matching the sibling resolver. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../event_handler/bedrock_agent.py | 9 +++-- .../_pydantic/test_bedrock_agent.py | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/bedrock_agent.py b/aws_lambda_powertools/event_handler/bedrock_agent.py index a49ba38c214..6fef1044b97 100644 --- a/aws_lambda_powertools/event_handler/bedrock_agent.py +++ b/aws_lambda_powertools/event_handler/bedrock_agent.py @@ -99,12 +99,17 @@ def lambda_handler(event, context): current_event: BedrockAgentEvent - def __init__(self, debug: bool = False, enable_validation: bool = True): + def __init__( + self, + debug: bool = False, + enable_validation: bool = True, + serializer: Callable[[dict], str] | None = None, + ): super().__init__( proxy_type=ProxyEventType.BedrockAgentEvent, cors=None, debug=debug, - serializer=None, + serializer=serializer, strip_prefixes=None, enable_validation=enable_validation, json_body_deserializer=None, diff --git a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py index 9c46fe24eb7..4367a94f49d 100644 --- a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py +++ b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py @@ -1,4 +1,5 @@ import json +from functools import partial from typing import Any, Dict, Optional import pytest @@ -383,3 +384,37 @@ def run_sql_query(query: Annotated[str, Query()]): # THEN the parameter with commas should be correctly passed to the handler body = json.loads(result["response"]["responseBody"]["application/json"]["body"]) assert body["result"] == "SELECT a.source_name, b.thing FROM table" + + +def test_bedrock_agent_with_default_serializer_escapes_non_ascii(): + # GIVEN a Bedrock Agent resolver using the default serializer + app = BedrockAgentResolver() + + @app.get("/claims", description="Gets claims") + def claims() -> Dict[str, Any]: + return {"output": "잔액은 1,000원입니다 💰"} + + # WHEN calling the event handler + result = app(load_event("bedrockAgentEvent.json"), {}) + + # THEN the body is valid JSON and non-ASCII characters are escaped (default json.dumps behavior) + body = result["response"]["responseBody"]["application/json"]["body"] + assert "\\uc794" in body # "잔" escaped + assert json.loads(body) == {"output": "잔액은 1,000원입니다 💰"} + + +def test_bedrock_agent_with_custom_serializer_preserves_non_ascii(): + # GIVEN a Bedrock Agent resolver initialized with a custom serializer that keeps non-ASCII characters + app = BedrockAgentResolver(serializer=partial(json.dumps, ensure_ascii=False)) + + @app.get("/claims", description="Gets claims") + def claims() -> Dict[str, Any]: + return {"output": "잔액은 1,000원입니다 💰"} + + # WHEN calling the event handler + result = app(load_event("bedrockAgentEvent.json"), {}) + + # THEN the non-ASCII characters are preserved verbatim in the response body + body = result["response"]["responseBody"]["application/json"]["body"] + assert "잔액은 1,000원입니다 💰" in body + assert json.loads(body) == {"output": "잔액은 1,000원입니다 💰"}