Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,9 @@ private static String serializeDocument(Document document) {

private static Document deserializeDocument(String json) {
JsonNode node = JSON_PARSER.parse(json);
if (node == null) {
return Document.mapBuilder().build();
}
return node.visit(DOCUMENT_UNMARSHALLER);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.within;

import io.opentelemetry.api.common.AttributeKey;
Expand Down Expand Up @@ -667,6 +668,65 @@ void testConverseToolCall() {
+ "The current weather in Seattle is 50 degrees and raining. In San Francisco, the weather is 70 degrees and sunny.")))));
}

@Test
void testConverseStreamToolCallWithEmptyToolArguments() {
BedrockRuntimeAsyncClientBuilder builder = BedrockRuntimeAsyncClient.builder();
builder.overrideConfiguration(createOverrideConfigurationBuilder().build());
configureClient(builder);
BedrockRuntimeAsyncClient client = configureBedrockRuntimeClient(builder.build());

String modelId = "amazon.nova-micro-v1:0";
List<Message> messages = new ArrayList<>();
messages.add(
Message.builder()
.role(ConversationRole.USER)
.content(ContentBlock.fromText("What time is it?"))
.build());

ConverseStreamResponseHandler responseHandler =
ConverseStreamResponseHandler.builder()
.subscriber(ConverseStreamResponseHandler.Visitor.builder().build())
.build();

assertThatCode(
() ->
client
.converseStream(
ConverseStreamRequest.builder()
.modelId(modelId)
.messages(messages)
.toolConfig(serverTimeToolConfig())
.build(),
responseHandler)
.join())
.doesNotThrowAnyException();

getTesting()
.waitAndAssertLogRecords(
log ->
log.hasAttributesSatisfyingExactly(
equalTo(GEN_AI_PROVIDER_NAME, AWS_BEDROCK),
equalTo(EVENT_NAME, "gen_ai.user.message"))
.hasBody(Value.of(KeyValue.of("content", Value.of("What time is it?")))),
log ->
log.hasAttributesSatisfyingExactly(
equalTo(GEN_AI_PROVIDER_NAME, AWS_BEDROCK),
equalTo(EVENT_NAME, "gen_ai.choice"))
.hasBody(
Value.of(
KeyValue.of("finish_reason", Value.of("tool_use")),
KeyValue.of("index", Value.of(0)),
KeyValue.of(
"toolCalls",
Value.of(
Value.of(
KeyValue.of("name", Value.of("get_server_time")),
KeyValue.of("arguments", Value.of("{}")),
KeyValue.of("id", Value.of("tooluse_empty_params_test")),
KeyValue.of("type", Value.of("function"))))),
KeyValue.of("content", Value.of("")))));
}

@Test
void testConverseToolCallStream() {
BedrockRuntimeAsyncClientBuilder builder = BedrockRuntimeAsyncClient.builder();
Expand Down Expand Up @@ -1067,6 +1127,27 @@ void testConverseToolCallStream() {
+ "The current weather in Seattle is 50 degrees and it is raining. In San Francisco, the weather is 70 degrees and sunny.")))));
}

private static ToolConfiguration serverTimeToolConfig() {
return ToolConfiguration.builder()
.tools(
Tool.builder()
.toolSpec(
ToolSpecification.builder()
.name("get_server_time")
.description("Get the current server time.")
.inputSchema(
ToolInputSchema.builder()
.json(
Document.mapBuilder()
.putString("type", "object")
.putDocument("properties", Document.mapBuilder().build())
.build())
.build())
.build())
.build())
.build();
}

private static ToolConfiguration currentWeatherToolConfig() {
return ToolConfiguration.builder()
.tools(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
name: model_amazonnova-micro-v10_converse-stream_empty_tool_args
request:
url: /model/amazon.nova-micro-v1%3A0/converse-stream
method: POST
bodyPatterns:
- equalToJson: |-
{
"messages" : [ {
"role" : "user",
"content" : [ {
"text" : "What time is it?"
} ]
} ],
"toolConfig" : {
"tools" : [ {
"toolSpec" : {
"name" : "get_server_time",
"description" : "Get the current server time.",
"inputSchema" : {
"json" : {
"type" : "object",
"properties" : { }
}
}
}
} ]
}
}
ignoreArrayOrder: false
ignoreExtraElements: false
response:
status: 200
base64Body: AAAAnQAAAFLJ0QwQCzpldmVudC10eXBlBwAMbWVzc2FnZVN0YXJ0DTpjb250ZW50LXR5cGUHABBhcHBsaWNhdGlvbi9qc29uDTptZXNzYWdlLXR5cGUHAAVldmVudHsicm9sZSI6ImFzc2lzdGFudCIsInAiOiJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRiJ94fNKfAAAAPwAAABXHemmYgs6ZXZlbnQtdHlwZQcAEWNvbnRlbnRCbG9ja1N0YXJ0DTpjb250ZW50LXR5cGUHABBhcHBsaWNhdGlvbi9qc29uDTptZXNzYWdlLXR5cGUHAAVldmVudHsiY29udGVudEJsb2NrSW5kZXgiOjAsInAiOiJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRiIsInN0YXJ0Ijp7InRvb2xVc2UiOnsibmFtZSI6ImdldF9zZXJ2ZXJfdGltZSIsInRvb2xVc2VJZCI6InRvb2x1c2VfZW1wdHlfcGFyYW1zX3Rlc3QifX19ecyMJQAAAKQAAABWYo0S/gs6ZXZlbnQtdHlwZQcAEGNvbnRlbnRCbG9ja1N0b3ANOmNvbnRlbnQtdHlwZQcAEGFwcGxpY2F0aW9uL2pzb24NOm1lc3NhZ2UtdHlwZQcABWV2ZW50eyJjb250ZW50QmxvY2tJbmRleCI6MCwicCI6ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGIn07lyU5AAAAlQAAAFFgqBZrCzpldmVudC10eXBlBwALbWVzc2FnZVN0b3ANOmNvbnRlbnQtdHlwZQcAEGFwcGxpY2F0aW9uL2pzb24NOm1lc3NhZ2UtdHlwZQcABWV2ZW50eyJwIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3QiLCJzdG9wUmVhc29uIjoidG9vbF91c2UifUV9XIkAAADgAAAATtySdCELOmV2ZW50LXR5cGUHAAhtZXRhZGF0YQ06Y29udGVudC10eXBlBwAQYXBwbGljYXRpb24vanNvbg06bWVzc2FnZS10eXBlBwAFZXZlbnR7Im1ldHJpY3MiOnsibGF0ZW5jeU1zIjoxMDB9LCJwIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUYiLCJ1c2FnZSI6eyJpbnB1dFRva2VucyI6NTAsIm91dHB1dFRva2VucyI6MTAsInRvdGFsVG9rZW5zIjo2MH198F6oVg==
headers:
Date: "Mon, 18 May 2026 10:00:00 GMT"
Content-Type: application/vnd.amazon.eventstream
x-amzn-RequestId: test-empty-tool-args-request-id
uuid: a1b2c3d4-e5f6-7890-abcd-ef1234567890
persistent: true
insertionIndex: 100
Loading