[bot] Bedrock ConverseStream drops tool use and non-text content blocks in streaming spans
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 64/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Tranquilo
- Stack tecnológico
- aws, java
- Área
- cloud, observability
Línea de trabajo
Empieza por TeeingSubscriber.onNext, parseDeltaText y buildConverseJson en braintrust-sdk/instrumentation/aws_bedrock_2_30_0/src/main/java/dev/braintrust/instrumentation/awsbedrock/v2_30_0/BraintrustBedrockInterceptor.java. Compara el manejo de eventos de streaming con normalizeBedrockMessage() en braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java y revisa las pruebas existentes de Bedrock. Se considera terminado cuando el contenido de tool-use en streaming, los identificadores, los nombres y la entrada estén representados en la salida del span, con cobertura en BraintrustAWSBedrockTest.java.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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
- Lenguaje dominante
- Java
- Estrellas
- 21
- Forks
- 5
- Merge medio
- 2 d 7 h
- PR fusionados (30 d)
- 8
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de braintrustdata/braintrust-sdk-java
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Todos los issues de braintrustdata/braintrust-sdk-java
Issues similares
-
executions.Query — startDate and timeRange filters are sent with inverted comparison operators Abiertoarea/plugin
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
kestra-io/plugin-kestra#190 ·
-
litertlm-android AAR ships no consumer ProGuard rules → "mid == null" SIGABRT in minified apps Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
google-ai-edge/LiteRT-LM#3739 ·
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
Add canonical URLs and a sitemap Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
integra-team-red/meet-map#249 ·
-
[Studio][Bug] Cancelled create-user dialog keeps the password and admin switch for the next attempt Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
apache/rocketmq-dashboard#5064 ·