Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

OpenAIConverseConverter crashes with "Object of type bytes is not JSON serializable" on redacted reasoning (found with OpenAI GPT-6 Sol/Luna/Astra on Bedrock)

オープン 初心者向け
#680 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
70/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python

調査の方向性

バグは src/bedrock_agentcore/memory/integrations/strands/converters/openai.py にあります。_bedrock_to_openai 関数と _openai_to_bedrock 関数を確認してください。ここでは、redactedContent(バイト)を含む reasoningContent が JSON 用にエンコードされていません。strands.types.session のヘルパー関数 encode_bytes_values と decode_bytes_values を使用してください。テストファイル tests/bedrock_agentcore/memory/integrations/strands/test_openai_converter.py には、期待される動作を示す失敗するテストがあります。修正を確認するためにテストを実行してください。

索引モデルが issue の本文から書いたものです。

説明

bug high-severity

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
主要言語
Python
スター
776
フォーク
153
平均マージ
1日 8時間
マージ済み PR(30日)
15

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

aws/bedrock-agentcore-sdk-python のほかの issue

aws/bedrock-agentcore-sdk-python の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。