[bot] Bedrock ConverseStream drops tool use and non-text content blocks in streaming spans
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 64/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Ruhig
- Tech-Stack
- aws, java
- Bereich
- cloud, observability
Rechercherichtung
Beginne mit TeeingSubscriber.onNext, parseDeltaText und buildConverseJson in braintrust-sdk/instrumentation/aws_bedrock_2_30_0/src/main/java/dev/braintrust/instrumentation/awsbedrock/v2_30_0/BraintrustBedrockInterceptor.java. Vergleiche die Verarbeitung von Streaming-Ereignissen mit normalizeBedrockMessage() in braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java und prüfe die vorhandenen Bedrock-Tests. Als abgeschlossen gilt die Aufgabe, wenn Inhalte der Tool-Nutzung im Streaming, Bezeichner, Namen und Eingaben in der Span-Ausgabe dargestellt werden und dies in BraintrustAWSBedrockTest.java abgedeckt ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
The Bedrock ConverseStream instrumentation in TeeingSubscriber only accumulates delta.text from contentBlockDelta events. When the model returns tool use content blocks during streaming (a documented and supported Bedrock feature), the tool call data is silently dropped from the span output.
Non-streaming Converse calls handle tool use correctly — normalizeBedrockMessage() in InstrumentationSemConv already recognizes toolUse, toolResult, and image content block types and adds appropriate type annotations. The gap is exclusively in the streaming path.
What is missing
1. TeeingSubscriber only parses text deltas (lines 273–289)
case "contentBlockDelta" -> {
String t = parseDeltaText(payload); // only looks for delta.text
if (t != null) {
text.append(t);
// ...
}
}
parseDeltaText() (lines 322–339) searches exclusively for delta.text. Bedrock ConverseStream sends delta.toolUse for tool use blocks (containing incremental input JSON), which is silently ignored.
2. contentBlockStart events are not handled
The TeeingSubscriber switch (lines 273–289) has no case for contentBlockStart. This event carries toolUse.toolUseId and toolUse.name — metadata needed to reconstruct the tool call. Without it, even if tool use deltas were captured, the tool name and ID would be lost.
3. buildConverseJson always produces a single text block (lines 385–410)
gen.writeArrayFieldStart("content");
gen.writeStartObject();
gen.writeStringField("text", text); // always one text block
gen.writeEndObject();
gen.writeEndArray();
The synthetic response JSON always contains exactly one {"text": "..."} content block, regardless of what the model actually returned. When the model requests a tool call, the span output will show empty text instead of the tool invocation.
Impact
When a streaming Bedrock call triggers tool use (common in agentic workflows):
- The span's
output_jsoncontains[{"role":"assistant","content":[{"text":"","type":"text"}]}]— as if the model returned nothing - The
stopReasonis captured as"tool_use", contradicting the empty output - Tool call names, IDs, and argument JSON are permanently lost from the trace
- Non-streaming
Conversecalls with tool use are correctly captured
Braintrust docs status
- Bedrock is listed as a supported cloud provider at https://www.braintrust.dev/docs/integrations/ai-providers: supported
- Tool calling in Bedrock streaming is not specifically documented on Braintrust docs: not_found
Upstream sources
- Bedrock ConverseStream API reference: https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseStream.html — documents
toolConfigparameter and streaming tool use events (contentBlockStartwithtoolUse,contentBlockDeltawithtoolUseinput) - Bedrock tool use examples: https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use-examples.html — shows ConverseStream with tool use
- Bedrock streaming event sequence: Events include
contentBlockStart(carriesstart.toolUsewithtoolUseIdandname),contentBlockDelta(carriesdelta.toolUsewithinputJSON fragments), andcontentBlockStop
Local files inspected
braintrust-sdk/instrumentation/aws_bedrock_2_30_0/src/main/java/dev/braintrust/instrumentation/awsbedrock/v2_30_0/BraintrustBedrockInterceptor.java— lines 273–289 (TeeingSubscriber.onNext: onlycontentBlockDelta→text,messageStop,metadatahandled; nocontentBlockStart), lines 322–339 (parseDeltaText: onlydelta.text), lines 385–410 (buildConverseJson: hardcoded single text block)braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java— lines 400–434 (normalizeBedrockMessage: non-streaming path correctly handlestoolUse,toolResult,imagecontent block types)braintrust-sdk/instrumentation/aws_bedrock_2_30_0/src/test/java/dev/braintrust/instrumentation/awsbedrock/v2_30_0/BraintrustAWSBedrockTest.java— no streaming test exercises tool use responses
- Vorherrschende Sprache
- Java
- Sterne
- 21
- Forks
- 5
- Ø Merge
- 1 T. 15 Std.
- Gemergte PRs (30 T.)
- 9
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus braintrustdata/braintrust-sdk-java
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
Alle Issues in braintrustdata/braintrust-sdk-java
Ähnliche Issues
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
MCModderAnchor/TACZ#758 ·
-
agent-java community triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
elastic/apm-agent-java#4594 ·
Maintainer antworten meist innerhalb von 1 Tag
-
area/plugin good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
kestra-io/plugin-soda#137 ·
-
area/plugin good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
kestra-io/plugin-aws#816 ·
Maintainer antworten meist innerhalb von 2 Tagen
-
area/plugin good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
kestra-io/plugin-kestra#200 ·
Maintainer antworten meist innerhalb von 1 Tag