Skip to content

[spring-ai] NullPointerException in ToolConverter when ADK tool uses ToolContext #699

@lurongjiang

Description

@lurongjiang

** Please make sure you read the contribution guide and file the issues in the rigth place. **
Contribution guide.

Describe the bug
In com.google.adk.models.springai.ToolConverter#convertToSpringAiTools, when converting ADK BaseTool instances to Spring AI ToolCallback, the toolContext parameter passed to tool.runAsync(...) is hardcoded as null. This causes a NullPointerException if the underlying ADK tool method expects and uses a non-null ToolContext (e.g., to access functionCallId()).

To Reproduce
Steps to reproduce the behavior:

  1. Define an ADK tool method that includes a ToolContext parameter.
  2. Use ToolConverter to convert this tool into a Spring AI ToolCallback.
  3. Invoke the resulting ToolCallback.call(...) with a valid org.springframework.ai.chat.model.ToolContext.
  4. Observe a NullPointerException because the ADK tool receives null for its ToolContext argument.

test case:

@Test
void testCallbackWithToolContext() throws Exception {
  ToolConverter converter = new ToolConverter();
  FunctionTool tool = FunctionTool.create(TestSayHelloFunctions.class, "sayHello");
  Map<String, BaseTool> tools = Map.of("sayHello", tool);

  List<ToolCallback> toolCallbacks = converter.convertToSpringAiTools(tools);
  ToolCallback callback = toolCallbacks.get(0);
  String res = callback.call("{\"name\":\"Jack\"}", new org.springframework.ai.chat.model.ToolContext(new HashMap<>()));
  System.out.println(res);
}

public static class TestSayHelloFunctions {
  @Annotations.Schema(name = "sayHello", description = "Test func: say hello for name")
  public static void sayHello(
      @Annotations.Schema(name = "name", description = "the name to say hello") String name,
      @Annotations.Schema(name = "toolContext", description = "toolContext") ToolContext toolContext) {
    toolContext.functionCallId().ifPresent(functionCallId -> System.out.println("callId:" + functionCallId));
    System.out.println("hello " + name);
  }
}

Expected behavior
The ADK ToolContext passed to the tool method should be constructed from the org.springframework.ai.chat.model.ToolContext provided to ToolCallback.call(...), rather than being null. At minimum, it should not cause an NPE when the tool expects a non-null context.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: windows 11
  • Java version: jdk17
  • ADK version(see maven dependency):
  <groupId>com.google.adk</groupId>
  <artifactId>google-adk-parent</artifactId>
  <version>0.5.1-SNAPSHOT</version>

Additional context

18:33:59.235 [main] ERROR com.google.adk.tools.FunctionTool -- Exception occurred while calling function tool: sayHello
java.lang.reflect.InvocationTargetException: null
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at com.google.adk.tools.FunctionTool.call(FunctionTool.java:238)
	at com.google.adk.tools.FunctionTool.runAsync(FunctionTool.java:227)
	at com.google.adk.models.springai.ToolConverter.lambda$convertToSpringAiTools$3(ToolConverter.java:144)
	at org.springframework.ai.tool.function.FunctionToolCallback.lambda$builder$0(FunctionToolCallback.java:141)
	at org.springframework.ai.tool.function.FunctionToolCallback.callMethod(FunctionToolCallback.java:113)
	at org.springframework.ai.tool.function.FunctionToolCallback.call(FunctionToolCallback.java:104)
	at com.google.adk.models.springai.ToolConverterArgumentProcessingTest.testCallback(ToolConverterArgumentProcessingTest.java:74)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	...
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:231)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: java.lang.NullPointerException: Cannot invoke "com.google.adk.tools.ToolContext.functionCallId()" because "toolContext" is null
	at com.google.adk.models.springai.ToolConverterArgumentProcessingTest$TestSayHelloFunctions.sayHello(ToolConverterArgumentProcessingTest.java:83)
	... 81 common frames omitted
{"status":"error","message":"An internal error occurred."}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions