diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index d29ca1649ff..c5ef53c5ecc 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -5174,15 +5174,25 @@ def _bedrock_tools_pt(tools: List) -> List[BedrockToolBlock]: # with circular references (see issue #19098). unpack_defs handles nested # refs recursively and correctly detects/skips circular references. unpack_defs(parameters, defs_copy) + _additional_properties = parameters.get("additionalProperties", None) tool_input_schema = BedrockToolInputSchemaBlock( json=BedrockToolJsonSchemaBlock( type=parameters.get("type", ""), properties=parameters.get("properties", {}), required=parameters.get("required", []), + **( + {"additionalProperties": _additional_properties} + if _additional_properties is not None + else {} + ), ) ) + _strict = tool.get("function", {}).get("strict", None) tool_spec = BedrockToolSpecBlock( - inputSchema=tool_input_schema, name=name, description=description + inputSchema=tool_input_schema, + name=name, + description=description, + **({"strict": _strict} if _strict is not None else {}), ) tool_block = BedrockToolBlock(toolSpec=tool_spec) tool_block_list.append(tool_block) diff --git a/litellm/types/llms/bedrock.py b/litellm/types/llms/bedrock.py index 54237dfb37a..cb152484188 100644 --- a/litellm/types/llms/bedrock.py +++ b/litellm/types/llms/bedrock.py @@ -203,13 +203,16 @@ class ConverseResponseBlock(TypedDict, total=False): str ] # end_turn | tool_use | max_tokens | stop_sequence | content_filtered usage: Required[ConverseTokenUsageBlock] - serviceTier: ServiceTierBlock # Optional - only present when serviceTier was sent in request + serviceTier: ( + ServiceTierBlock # Optional - only present when serviceTier was sent in request + ) class ToolJsonSchemaBlock(TypedDict, total=False): type: Literal["object"] properties: dict required: List[str] + additionalProperties: bool class ToolInputSchemaBlock(TypedDict): @@ -220,6 +223,7 @@ class ToolSpecBlock(TypedDict, total=False): inputSchema: Required[ToolInputSchemaBlock] name: Required[str] description: str + strict: Optional[bool] class SystemToolBlock(TypedDict, total=False): diff --git a/tests/llm_translation/test_bedrock_completion.py b/tests/llm_translation/test_bedrock_completion.py index 76ec2bdd1d7..b8de820d364 100644 --- a/tests/llm_translation/test_bedrock_completion.py +++ b/tests/llm_translation/test_bedrock_completion.py @@ -1116,6 +1116,52 @@ def test_bedrock_tools_transformation_valid_params(): assert "test" in result[0]["toolSpec"]["inputSchema"]["json"]["required"] +def test_bedrock_tools_pt_strict_parameter(): + """Test that strict and additionalProperties are passed through to Bedrock toolSpec.""" + tools_with_strict = [ + { + "type": "function", + "function": { + "name": "generate_sql", + "strict": True, + "description": "Generate a SQL query", + "parameters": { + "type": "object", + "properties": { + "query": {"type": "string"}, + }, + "required": ["query"], + "additionalProperties": False, + }, + }, + } + ] + result = _bedrock_tools_pt(tools_with_strict) + assert result[0]["toolSpec"]["strict"] is True + assert result[0]["toolSpec"]["inputSchema"]["json"]["additionalProperties"] is False + + # Test without strict - should not have strict key or additionalProperties + tools_without_strict = [ + { + "type": "function", + "function": { + "name": "generate_sql", + "description": "Generate a SQL query", + "parameters": { + "type": "object", + "properties": { + "query": {"type": "string"}, + }, + "required": ["query"], + }, + }, + } + ] + result = _bedrock_tools_pt(tools_without_strict) + assert "strict" not in result[0]["toolSpec"] + assert "additionalProperties" not in result[0]["toolSpec"]["inputSchema"]["json"] + + def test_not_found_error(): with pytest.raises(litellm.NotFoundError): completion(