aws / aws/bedrock-agentcore-sdk-python

Streaming responses silently turn unserialisable events into JSON strings of their Python repr

Aperta
#659 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug
Lingua principale
Python
Stelle
761
Fork
147
Merge medio
1g 23h
PR unite (30g)
7

Descrizione

**Describe the bug**

When an entrypoint generator yields an object that `json.dumps` cannot serialise, `BedrockAgentCoreApp._safe_serialize_to_json_string` (`runtime/app.py` line 898 in 1.22.0) tries `convert_complex_objects` and then falls back to `json.dumps(str(obj))`. `convert_complex_objects` (`runtime/utils.py`) handles Pydantic models, dataclasses, dicts, lists, tuples and sets but not `bytes`, so any event that contains binary data anywhere in its tree reaches the third fallback. The SSE `data:` line then carries a JSON *string* holding the Python repr of the dictionary, for example `"{'result': {'type': 'agent_result', 'message': {... b'rsn_...'}}}"`, rather than a JSON object or an error.

The client cannot tell this apart from a legitimate string event, and it cannot recover the original payload from the repr. In our case a supervisor agent consuming a sub-agent's stream did `event.get("error")` on what was now a `str` and failed with `AttributeError: 'str' object has no attribute 'get'`, turning every affected turn into a user-facing failure. Nothing was logged on the producing side, because the fallback succeeds.

**To Reproduce**

1. Write a streaming entrypoint whose generator yields a dictionary containing a `bytes` value somewhere inside it. A real-world source is the `AgentResult.to_dict()` from Strands when the model returns a `reasoningContent.redactedContent` block, which OpenAI GPT-5.6 Luna on Bedrock does after tool calls. Any other `bytes` value in a yielded event, such as image or document `source.bytes` from a tool result, takes the same path.
2. Invoke the runtime and read the SSE stream.
3. Observe that the event arrives as `data: "{'result': ...}"` (a JSON string) instead of `data: {"result": ...}`.

**Expected behavior**

One of:

- binary values are converted to something JSON can carry (for example base64), or
- the event is replaced by an explicit error event, as `_stream_with_error_handling` already does for exceptions, and a warning is logged.

Either way the consumer should never receive a Python repr as the payload.

**Additional context**

- Versions: bedrock-agentcore 1.22.0 (latest on PyPI), Python 3.13, Strands 1.54.0, runtime container on Bedrock AgentCore.
- The final fallback that logs a warning only fires if `json.dumps(str(obj))` itself fails, which it never does for a dictionary.
- Related: #198 (closed) reported bytes-in-message failing in the memory converter; this is the same class of input on the response-streaming path.
- Companion report about `AgentResult.to_dict()` not being JSON-serialisable: strands-agents/harness-sdk#4167.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia in runtime/app.py da _safe_serialize_to_json_string e segui il suo utilizzo in _stream_with_error_handling, quindi esamina convert_complex_objects in runtime/utils.py. Riproduci un generatore di entrypoint che restituisca un dizionario contenente bytes e leggi la riga di dati SSE; il lavoro è completato quando gli eventi contenenti dati binari non vengono emessi come stringhe repr di Python, ma seguono invece uno dei comportamenti JSON-safe o di errore esplicito indicati.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
api, backend
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Attiva
Chiarezza
Specificata chiaramente
Idoneità per principianti
76/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.