2323import java .util .HashMap ;
2424import java .util .List ;
2525import java .util .Map ;
26+ import java .util .Set ;
2627import org .slf4j .Logger ;
2728import org .slf4j .LoggerFactory ;
2829import org .springframework .ai .tool .ToolCallback ;
@@ -172,6 +173,17 @@ public List<ToolCallback> convertToSpringAiTools(Map<String, BaseTool> tools) {
172173 } catch (Exception e ) {
173174 logger .error ("Error serializing schema to JSON: {}" , e .getMessage (), e );
174175 }
176+ } else if (declaration .parametersJsonSchema ().isPresent ()) {
177+ callbackBuilder .inputType (Map .class );
178+ try {
179+ String schemaJson =
180+ new com .fasterxml .jackson .databind .ObjectMapper ()
181+ .writeValueAsString (declaration .parametersJsonSchema ().get ());
182+ callbackBuilder .inputSchema (schemaJson );
183+ logger .debug ("Set input schema JSON from parametersJsonSchema: {}" , schemaJson );
184+ } catch (Exception e ) {
185+ logger .error ("Error serializing parametersJsonSchema to JSON: {}" , e .getMessage (), e );
186+ }
175187 }
176188
177189 toolCallbacks .add (callbackBuilder .build ());
@@ -187,45 +199,63 @@ public List<ToolCallback> convertToSpringAiTools(Map<String, BaseTool> tools) {
187199 */
188200 private Map <String , Object > processArguments (
189201 Map <String , Object > args , FunctionDeclaration declaration ) {
190- // If the arguments already match the expected format, return as-is
191202 if (declaration .parameters ().isPresent ()) {
192203 var schema = declaration .parameters ().get ();
193204 if (schema .properties ().isPresent ()) {
194- var expectedParams = schema .properties ().get ().keySet ();
195-
196- // Check if all expected parameters are present at the top level
197- boolean allParamsPresent = expectedParams .stream ().allMatch (args ::containsKey );
198- if (allParamsPresent ) {
199- return args ;
205+ return normalizeArguments (args , schema .properties ().get ().keySet ());
206+ }
207+ } else if (declaration .parametersJsonSchema ().isPresent ()) {
208+ try {
209+ @ SuppressWarnings ("unchecked" )
210+ Map <String , Object > schemaMap =
211+ new com .fasterxml .jackson .databind .ObjectMapper ()
212+ .convertValue (declaration .parametersJsonSchema ().get (), Map .class );
213+ Object propertiesObj = schemaMap .get ("properties" );
214+ if (propertiesObj instanceof Map ) {
215+ @ SuppressWarnings ("unchecked" )
216+ Set <String > expectedParams = ((Map <String , Object >) propertiesObj ).keySet ();
217+ return normalizeArguments (args , expectedParams );
200218 }
219+ } catch (Exception e ) {
220+ logger .warn (
221+ "Error processing parametersJsonSchema for argument mapping: {}" , e .getMessage ());
222+ }
223+ }
201224
202- // Check if arguments are nested under a single key (common pattern)
203- if (args .size () == 1 ) {
204- var singleValue = args .values ().iterator ().next ();
205- if (singleValue instanceof Map ) {
206- @ SuppressWarnings ("unchecked" )
207- Map <String , Object > nestedArgs = (Map <String , Object >) singleValue ;
208- boolean allNestedParamsPresent =
209- expectedParams .stream ().allMatch (nestedArgs ::containsKey );
210- if (allNestedParamsPresent ) {
211- return nestedArgs ;
212- }
213- }
214- }
225+ // If no processing worked, return original args and let ADK handle the error
226+ return args ;
227+ }
215228
216- // Check if we have a single parameter function and got a direct value
217- if (expectedParams .size () == 1 ) {
218- String expectedParam = expectedParams .iterator ().next ();
219- if (args .size () == 1 && !args .containsKey (expectedParam )) {
220- // Try to map the single value to the expected parameter name
221- Object singleValue = args .values ().iterator ().next ();
222- return Map .of (expectedParam , singleValue );
223- }
229+ private Map <String , Object > normalizeArguments (
230+ Map <String , Object > args , Set <String > expectedParams ) {
231+ // Check if all expected parameters are present at the top level
232+ boolean allParamsPresent = expectedParams .stream ().allMatch (args ::containsKey );
233+ if (allParamsPresent ) {
234+ return args ;
235+ }
236+
237+ // Check if arguments are nested under a single key (common pattern)
238+ if (args .size () == 1 ) {
239+ var singleValue = args .values ().iterator ().next ();
240+ if (singleValue instanceof Map ) {
241+ @ SuppressWarnings ("unchecked" )
242+ Map <String , Object > nestedArgs = (Map <String , Object >) singleValue ;
243+ boolean allNestedParamsPresent = expectedParams .stream ().allMatch (nestedArgs ::containsKey );
244+ if (allNestedParamsPresent ) {
245+ return nestedArgs ;
224246 }
225247 }
226248 }
227249
228- // If no processing worked, return original args and let ADK handle the error
250+ // Check if we have a single parameter function and got a direct value
251+ if (expectedParams .size () == 1 ) {
252+ String expectedParam = expectedParams .iterator ().next ();
253+ if (args .size () == 1 && !args .containsKey (expectedParam )) {
254+ Object singleValue = args .values ().iterator ().next ();
255+ return Map .of (expectedParam , singleValue );
256+ }
257+ }
258+
229259 return args ;
230260 }
231261
0 commit comments