Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs
Use tools like Google Search, code execution, and custom function calling with automatic or manual execution.
import com.google.genai.types.Tool;
import com.google.genai.types.FunctionDeclaration;
import com.google.genai.types.FunctionCall;
import com.google.genai.types.FunctionResponse;
import com.google.genai.types.ToolConfig;
import com.google.genai.types.FunctionCallingConfig;
import com.google.genai.types.AutomaticFunctionCallingConfig;
import com.google.genai.types.Schema;
import com.google.genai.types.GoogleSearch;
import com.google.genai.types.CodeExecution;
import java.lang.reflect.Method;package com.google.genai.types;
public final class Tool {
public static Builder builder();
public Optional<List<FunctionDeclaration>> functionDeclarations();
public Optional<GoogleSearchRetrieval> googleSearchRetrieval();
public Optional<GoogleSearch> googleSearch();
public Optional<GoogleMaps> googleMaps();
public Optional<CodeExecution> codeExecution();
public Optional<FileSearch> fileSearch();
public Optional<ComputerUse> computerUse();
public Optional<Retrieval> retrieval();
public Optional<UrlContext> urlContext();
}package com.google.genai.types;
public final class FunctionDeclaration {
public static Builder builder();
public Optional<String> name();
public Optional<String> description();
public Optional<Schema> parameters();
}package com.google.genai.types;
public final class ToolConfig {
public static Builder builder();
public Optional<FunctionCallingConfig> functionCallingConfig();
public Optional<RetrievalConfig> retrievalConfig();
}package com.google.genai.types;
public final class FunctionCallingConfig {
public static Builder builder();
public Optional<String> mode();
public Optional<List<String>> allowedFunctionNames();
public Optional<Boolean> streamFunctionCallArguments();
}package com.google.genai.types;
public final class AutomaticFunctionCallingConfig {
public static Builder builder();
public Optional<Boolean> disable();
public Optional<Integer> maxRemoteCalls();
public Optional<Boolean> appendHistory();
}Add to pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>public class WeatherService {
public static String getCurrentWeather(String location, String unit) {
// Implementation
return "The weather in " + location + " is sunny, 72 degrees " + unit;
}
}import java.lang.reflect.Method;
Method weatherMethod = WeatherService.class.getMethod(
"getCurrentWeather", String.class, String.class);
GenerateContentConfig config = GenerateContentConfig.builder()
.tools(Tool.builder()
.functions(weatherMethod)
.build())
.build();
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash",
"What's the weather in Vancouver?",
config
);
System.out.println("Response: " + response.text());
System.out.println("Function calling history: " +
response.automaticFunctionCallingHistory().orElse(null));public class ToolBox {
public static String getCurrentWeather(String location) {
return "Sunny, 75°F";
}
public static int add(int a, int b) {
return a + b;
}
public static String searchWeb(String query) {
return "Search results for: " + query;
}
}
// Load all methods
Method weatherMethod = ToolBox.class.getMethod("getCurrentWeather", String.class);
Method addMethod = ToolBox.class.getMethod("add", int.class, int.class);
Method searchMethod = ToolBox.class.getMethod("searchWeb", String.class);
Tool tool = Tool.builder()
.functions(weatherMethod, addMethod, searchMethod)
.build();
GenerateContentConfig config = GenerateContentConfig.builder()
.tools(tool)
.build();FunctionDeclaration function = FunctionDeclaration.builder()
.name("getCurrentWeather")
.description("Get the current weather in a location")
.parameters(Schema.builder()
.type(Type.Known.OBJECT)
.properties(ImmutableMap.of(
"location", Schema.builder()
.type(Type.Known.STRING)
.description("The city and state, e.g. San Francisco, CA")
.build(),
"unit", Schema.builder()
.type(Type.Known.STRING)
.enum_(ImmutableList.of("celsius", "fahrenheit"))
.build()
))
.required(ImmutableList.of("location"))
.build())
.build();
Tool tool = Tool.builder()
.functionDeclarations(ImmutableList.of(function))
.build();GenerateContentConfig config = GenerateContentConfig.builder()
.tools(tool)
.build();
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash",
"What's the weather in Boston?",
config
);
// Process function call
response.candidates().ifPresent(candidates -> {
if (!candidates.isEmpty()) {
Content content = candidates.get(0).content().orElse(null);
if (content != null && content.parts().isPresent()) {
for (Part part : content.parts().get()) {
part.functionCall().ifPresent(functionCall -> {
// Execute function
String functionName = functionCall.name().orElse("");
JsonNode args = functionCall.args().orElse(null);
// Call your function
String result = executeFunction(functionName, args);
// Send result back
sendFunctionResponse(functionCall, result);
});
}
}
}
});private void sendFunctionResponse(FunctionCall call, String result) {
FunctionResponse response = FunctionResponse.builder()
.name(call.name().orElse(""))
.response(objectMapper.valueToTree(ImmutableMap.of("result", result)))
.id(call.id().orElse(null))
.build();
Content responseContent = Content.fromParts(
Part.fromFunctionResponse(response)
);
GenerateContentResponse finalResponse = client.models.generateContent(
"gemini-2.0-flash",
responseContent,
null
);
System.out.println(finalResponse.text());
}import com.google.genai.types.GoogleSearch;
Tool searchTool = Tool.builder()
.googleSearch(GoogleSearch.builder().build())
.build();
GenerateContentConfig config = GenerateContentConfig.builder()
.tools(searchTool)
.build();
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash",
"What are the latest developments in quantum computing?",
config
);import com.google.genai.types.CodeExecution;
Tool codeExecTool = Tool.builder()
.codeExecution(CodeExecution.builder().build())
.build();
GenerateContentConfig config = GenerateContentConfig.builder()
.tools(codeExecTool)
.build();
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash",
"Calculate the first 10 fibonacci numbers",
config
);import com.google.genai.types.FunctionCallingMode;
// AUTO: Model decides when to call functions
ToolConfig autoConfig = ToolConfig.builder()
.functionCallingConfig(FunctionCallingConfig.builder()
.mode(FunctionCallingMode.Known.AUTO)
.build())
.build();
// ANY: Model must call at least one function
ToolConfig anyConfig = ToolConfig.builder()
.functionCallingConfig(FunctionCallingConfig.builder()
.mode(FunctionCallingMode.Known.ANY)
.build())
.build();
// NONE: Model cannot call functions
ToolConfig noneConfig = ToolConfig.builder()
.functionCallingConfig(FunctionCallingConfig.builder()
.mode(FunctionCallingMode.Known.NONE)
.build())
.build();
GenerateContentConfig config = GenerateContentConfig.builder()
.tools(tool)
.toolConfig(autoConfig)
.build();// Only allow specific functions
ToolConfig config = ToolConfig.builder()
.functionCallingConfig(FunctionCallingConfig.builder()
.mode(FunctionCallingMode.Known.ANY)
.allowedFunctionNames(ImmutableList.of("getCurrentWeather", "searchWeb"))
.build())
.build();
GenerateContentConfig genConfig = GenerateContentConfig.builder()
.tools(tool)
.toolConfig(config)
.build();// Customize automatic function calling behavior
AutomaticFunctionCallingConfig afcConfig = AutomaticFunctionCallingConfig.builder()
.maxRemoteCalls(5) // Limit remote calls
.appendHistory(true) // Include in history
.build();
GenerateContentConfig config = GenerateContentConfig.builder()
.tools(tool)
.automaticFunctionCalling(afcConfig)
.build();
// Or disable AFC
AutomaticFunctionCallingConfig disableAFC = AutomaticFunctionCallingConfig.builder()
.disable(true)
.build();
GenerateContentConfig manualConfig = GenerateContentConfig.builder()
.tools(tool)
.automaticFunctionCalling(disableAFC)
.build();List<Content> conversationHistory = new ArrayList<>();
// Initial query
conversationHistory.add(Content.builder()
.role("user")
.parts(ImmutableList.of(Part.fromText("What's the weather in Paris and Berlin?")))
.build());
GenerateContentResponse response1 = client.models.generateContent(
"gemini-2.0-flash",
conversationHistory,
config
);
// Process function calls and add to history
response1.candidates().ifPresent(candidates -> {
Content modelResponse = candidates.get(0).content().orElse(null);
if (modelResponse != null) {
conversationHistory.add(modelResponse);
// Execute function calls and add responses
for (Part part : modelResponse.parts().orElse(ImmutableList.of())) {
part.functionCall().ifPresent(call -> {
String result = executeFunct(call);
conversationHistory.add(Content.fromParts(
Part.fromFunctionResponse(FunctionResponse.builder()
.name(call.name().orElse(""))
.response(objectMapper.valueToTree(result))
.build())
));
});
}
}
});
// Continue conversation
GenerateContentResponse finalResponse = client.models.generateContent(
"gemini-2.0-flash",
conversationHistory,
config
);public static class WeatherParams {
public String location;
public String unit;
}
public static String getCurrentWeather(WeatherParams params) {
return "Weather in " + params.location + ": sunny";
}public static String safeFunction(String input) {
try {
// Function logic
return performOperation(input);
} catch (Exception e) {
return "Error: " + e.getMessage();
}
}FunctionCall call = /* ... */;
String result = executeFunction(call);
// Validate result before sending
if (result == null || result.isEmpty()) {
result = "Function returned no result";
}
FunctionResponse response = FunctionResponse.builder()
.name(call.name().orElse(""))
.response(objectMapper.valueToTree(ImmutableMap.of("result", result)))
.build();Install with Tessl CLI
npx tessl i tessl/maven-com-google-genai--google-genaidocs