[bot] Bedrock ConverseStream drops tool use and non-text content blocks in streaming spans
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 64/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 冷清
- 技术栈
- aws, java
- 领域
- cloud, observability
调研方向
从 braintrust-sdk/instrumentation/aws_bedrock_2_30_0/src/main/java/dev/braintrust/instrumentation/awsbedrock/v2_30_0/BraintrustBedrockInterceptor.java 中的 TeeingSubscriber.onNext、parseDeltaText 和 buildConverseJson 开始。将流式事件处理与 braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java 中的 normalizeBedrockMessage() 进行比较,并查看现有的 Bedrock 测试。当流式 tool-use 内容、标识符、名称和输入都在 span 输出中得到表示,并在 BraintrustAWSBedrockTest.java 中有覆盖时,即表示完成。
由索引模型根据 Issue 内容生成。
描述
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
- 主要语言
- Java
- 星标
- 21
- 派生
- 5
- 平均合并
- 2 天 34 分钟
- 30 天内合并 PR
- 6
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
braintrustdata/braintrust-sdk-java 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 78/100
-
难度 2/5 1-3 小时 新手友好度 68/100
查看 braintrustdata/braintrust-sdk-java 的全部 Issue
相似的 Issue
-
[Bug] Logo style setting missing and `classic` style not applied across multiple platforms (v3.1.0)未关闭
难度 2/5 1-3 小时 新手友好度 75/100
Stirling-Tools/Stirling-PDF#8382 · 1 个 reaction ·
维护者通常 2 天内回复
-
难度 1/5 1 小时以内 新手友好度 70/100
维护者通常 4 天内回复
-
enhancement untriaged
难度 2/5 1-3 小时 新手友好度 78/100
opensearch-project/sql#5842 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
openhab/openhab-addons#21882 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
YunaiV/ruoyi-vue-pro#1273 ·
维护者通常 3 天内回复