OpenAIConverseConverter crashes with "Object of type bytes is not JSON serializable" on redacted reasoning (found with OpenAI GPT-6 Sol/Luna/Astra on Bedrock)
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 70/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- python
- Lĩnh vực
- backend-api-design
Hướng nghiên cứu
Lỗi nằm trong src/bedrock_agentcore/memory/integrations/strands/converters/openai.py. Hãy xem xét các hàm _bedrock_to_openai và _openai_to_bedrock, nơi reasoningContent với redactedContent (bytes) không được mã hóa cho JSON. Sử dụng các hàm trợ giúp encode_bytes_values và decode_bytes_values từ strands.types.session. Tệp kiểm tra tests/bedrock_agentcore/memory/integrations/strands/test_openai_converter.py có một bài kiểm tra đang thất bại cho thấy hành vi mong đợi. Chạy bài kiểm tra để xác minh bản sửa lỗi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Thanks for the OpenAI-format Memory converter, and for #199, which already fixed this same TypeError for image bytes in AgentCoreMemoryConverter.
Describe the bug
With AgentCoreMemorySessionManager(converter=OpenAIConverseConverter), the agent call fails as soon as an assistant turn contains reasoningContent.redactedContent. That value is bytes, and message_to_payload passes it to json.dumps:
EventLoopException: Object of type bytes is not JSON serializable
src/bedrock_agentcore/memory/integrations/strands/session_manager.py, line 837, in append_message
src/bedrock_agentcore/memory/integrations/strands/session_manager.py, line 570, in create_message
src/bedrock_agentcore/memory/integrations/strands/converters/openai.py, line 152, in message_to_payload
OpenAI GPT-6 Sol, Luna and Astra on Bedrock Converse (us.openai.gpt-6-sol, us.openai.gpt-6-luna, us.openai.gpt-6-astra) return reasoning only as redactedContent. With the math prompt below, every run failed on us. and global. profiles, with or without a reasoning effort. The default converter handles the same turns.
In converters/openai.py, line 48 stores the raw block in _strands_reasoning_content and line 123 restores it as-is. bedrock_converter.py:39 goes through session_message.to_dict() / SessionMessage.from_dict, which base64-encode and decode bytes. The OpenAI converter skips that step.
To Reproduce
Offline, no credentials:
from strands.types.session import SessionMessage
from bedrock_agentcore.memory.integrations.strands.bedrock_converter import AgentCoreMemoryConverter
from bedrock_agentcore.memory.integrations.strands.converters import OpenAIConverseConverter
msg = SessionMessage(
message={"role": "assistant", "content": [{"reasoningContent": {"redactedContent": b"rsn_abc"}}, {"text": "208"}]},
message_id=1,
)
for conv in (AgentCoreMemoryConverter, OpenAIConverseConverter):
try:
print(conv.__name__, "OK", len(conv.message_to_payload(msg)[0][0]))
except Exception as e:
print(conv.__name__, type(e).__name__, e)
AgentCoreMemoryConverter OK 301
OpenAIConverseConverter TypeError Object of type bytes is not JSON serializable
Expected behavior
The converter stores the block and restores it as bytes, which is what the default converter does. GPT-6 accepts the returned redactedContent block on the next turn.
| Case (Strands Agent + session manager, us-east-1) | main c7423e5 |
With the patch below |
|---|---|---|
| OpenAI converter, GPT-6 Sol, effort default / high | ❌ turn 1 fails with the error above | ✅ turn 1 208, turn 2 209 after restore |
| OpenAI converter, GPT-6 Luna, effort default / high | ❌ same | ✅ same |
| OpenAI converter, GPT-6 Astra, effort default / high | ❌ same | ✅ same |
OpenAI converter, global. Sol / Luna / Astra, effort default / high |
❌ same | ✅ same |
| Turn 2 request after restore | not reached | ✅ redactedContent restored as bytes, replayed with text |
OpenAI converter, openai.gpt-oss-120b-1:0 (reasoningText) |
✅ | ✅ unchanged |
Default AgentCoreMemoryConverter, GPT-6 Sol / Luna / Astra |
✅ | ✅ unchanged |
Unit tests (uv run pytest tests/) |
3569 passed | ✅ 3570 passed (+1 new) |
Screenshots
N/A
Desktop (please complete the following information):
- OS: macOS, Python 3.10
- Version: bedrock-agentcore 1.23.1 (main
c7423e5), strands-agents 1.56.0 (also seen on 1.57.0), boto3 1.43.73
Smartphone (please complete the following information):
- N/A
Additional context
Proposed fix: encode the block with Strands' encode_bytes_values and decode it on restore with decode_bytes_values, the helpers to_dict() / from_dict() already use. #659 / #679 (Runtime SSE) is a separate path. CONTRIBUTING says external PRs aren't being accepted, so I've put the patch here. I'm happy to open a PR if you'd like one.
Proposed patch + regression test
--- a/src/bedrock_agentcore/memory/integrations/strands/converters/openai.py
+++ b/src/bedrock_agentcore/memory/integrations/strands/converters/openai.py
@@ -8,7 +8,7 @@ import json
import logging
from typing import Any, Tuple
-from strands.types.session import SessionMessage
+from strands.types.session import SessionMessage, decode_bytes_values, encode_bytes_values
from .protocol import exceeds_conversational_limit
@@ -45,7 +45,7 @@ def _bedrock_to_openai(message: dict) -> dict:
elif "reasoningContent" in item:
# OpenAI message shape does not have a stable multi-turn reasoning block field.
# Preserve original block(s) in storage-only extension field for lossless restore.
- reasoning_blocks.append(item)
+ reasoning_blocks.append(encode_bytes_values(item))
elif "toolUse" in item:
tu = item["toolUse"]
tool_calls.append(
@@ -120,7 +120,7 @@ def _openai_to_bedrock(openai_msg: dict) -> dict:
for rc in openai_msg.get("_strands_reasoning_content", []):
if isinstance(rc, dict) and "reasoningContent" in rc:
- reasoning_items.append(rc)
+ reasoning_items.append(decode_bytes_values(rc))
bedrock_role = "assistant" if role == "assistant" else "user"
Test added to tests/bedrock_agentcore/memory/integrations/strands/test_openai_converter.py, next to test_reasoning_content_round_trips_in_openai_converter:
def test_redacted_reasoning_bytes_round_trip_in_openai_converter():
"""redactedContent bytes must not break json.dumps and must restore as bytes."""
msg = SessionMessage(
message={
"role": "assistant",
"content": [
{"reasoningContent": {"redactedContent": b"rsn_abc"}},
{"text": "answer"},
],
},
message_id=10,
)
payload_json, _ = OpenAIConverseConverter.message_to_payload(msg)[0]
events = [{"payload": [{"conversational": {"content": {"text": payload_json}}}]}]
restored = OpenAIConverseConverter.events_to_messages(events)
assert restored[0].message["content"][0] == {"reasoningContent": {"redactedContent": b"rsn_abc"}}
On main the test fails:
src/bedrock_agentcore/memory/integrations/strands/converters/openai.py:152: in message_to_payload
return [(json.dumps(openai_msg), role)]
E TypeError: Object of type bytes is not JSON serializable
FAILED tests/.../test_openai_converter.py::test_redacted_reasoning_bytes_round_trip_in_openai_converter
1 failed, 6 passed
When only the encode half is applied, it still fails, on the restore check ({'__bytes_encoded__': True, 'data': 'cnNuX2FiYw=='} != b'rsn_abc'). With the full patch:
$ uv run pytest tests/bedrock_agentcore/memory/integrations/strands/test_openai_converter.py -q
7 passed
$ uv run pytest tests/bedrock_agentcore/memory -q
781 passed
$ uv run pytest tests/ -q
3570 passed, 10 skipped, 4 xpassed
$ uv run ruff check src tests && uv run ruff format --check src tests
All checks passed!
277 files already formatted
Live run: Strands Agent + BedrockModel + AgentCoreMemorySessionManager. Turn 1 (the small math prompt) asks "How many positive integers below 1000 are divisible by 7 or 11 but not both?". A new agent then restores the session and turn 2 asks "Add 1 to that". The AgentCore data plane was an in-memory stub passed as boto_session, but the error is raised in message_to_payload, before the CreateEvent call for that message. After the patch:
== us.openai.gpt-6-sol converter=openai effort=default
turn1: 208 | blocks: ['reasoningContent:redactedContent', 'text']
restored messages: 2 [('user', ['text']), ('assistant', ['reasoningContent:redactedContent', 'text'])]
redactedContent turn1: bytes | restored: bytes | equal: True
turn2: 209
turn2 request assistant blocks: [['reasoningContent', 'text']]
== us.openai.gpt-6-luna converter=openai effort=default
turn1: 208 | blocks: ['reasoningContent:redactedContent', 'text']
turn2: 209
== us.openai.gpt-6-astra converter=openai effort=default
turn1: 208 | blocks: ['reasoningContent:redactedContent', 'text']
restored messages: 2 [('user', ['text']), ('assistant', ['reasoningContent:redactedContent', 'text'])]
redactedContent turn1: bytes | restored: bytes | equal: True
turn2: 209
turn2 request assistant blocks: [['reasoningContent', 'text']]
== openai.gpt-oss-120b-1:0 converter=openai effort=high
turn1: 208 | blocks: ['reasoningContent:reasoningText', 'text']
turn2: 209
- Ngôn ngữ chính
- Python
- Star
- 776
- Fork
- 153
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 15
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của aws/bedrock-agentcore-sdk-python
-
bug high-severity
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
aws/bedrock-agentcore-sdk-python#698 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
AgentCoreMemorySessionManager discards the two boto3 clients MemoryClient builds; boto_session and boto_client_config are not passed throughCó thể đã có người làm @avneetbansal-aws đã nhận 10 ngày trước. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
aws/bedrock-agentcore-sdk-python#681 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug] update_message fails with parameter validation error when SessionMessage.message_id is a Strands positional integer indexCó thể đã có người làm @citizen204 đã nhận 100 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
aws/bedrock-agentcore-sdk-python#556 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
CodeInterpreter should not require a region argumentCó thể đã có người làm @citizen204 đã nhận 114 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
aws/bedrock-agentcore-sdk-python#511 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
aws/bedrock-agentcore-sdk-python#496 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của aws/bedrock-agentcore-sdk-python
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
RedHatQE/mtv-api-tests#721 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 85/100
pytest-dev/pluggy#757 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 85/100
NousResearch/hermes-agent#134960 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
HTML backend: `<br>` leaks the internal sentinel U+E000 into list items, headings and captionsCó thể đã có người làm @morten-lagabote đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
docling-project/docling#4671 ·
Maintainer thường phản hồi trong vòng 1 ngày