AgentScope Agent Oriented Framework.
AgentScope is an agent oriented programming framework for building LLM powered applications that has components for ReAct reasoning, tool calling, memory management, and multi agent collaboration.
Here we only use a subset of the Java implementation of AgentScope. For reference this is the home web page for Agentscope.
Using the Java Implementation of AgentScope: Hello World
For reference here is the GitHub repository for Java AgentScope and here is the documentation.
We start with the example in Java-AI-Book/source-code/AgentScope_gemini/src/main/java/com/markwatson/agentscope/Main.java. This code demonstrates the integration of the AgentScope framework with the Google Gemini language model to create a reasoning-based agent within a Java environment. By utilizing the ReActAgent class, the application implements a “Reasoning and Acting” loop, allowing the agent to process complex prompts by breaking them down into logical steps. The setup process begins with the secure retrieval of an API key from a system environment variable ensuring that sensitive credentials are not hard-coded into the source. Once validated, an instance of the GeminiChatModel class is instantiated with specific parameters, such as the gemini-2.5-flash model identifier, providing the underlying intelligence for the agent. This architectural approach highlights the simplicity of modern agentic frameworks using method call chaining, where a high level builder pattern is used to define the assistant’s persona and system prompts, effectively bridging the gap between standard Java enterprise development and the burgeoning field of autonomous AI agents.
1 package com.markwatson.agentscope;
2
3 import io.agentscope.core.ReActAgent;
4 import io.agentscope.core.message.Msg;
5 import io.agentscope.core.model.GeminiChatModel;
6
7 /**
8 * AgentScope ReActAgent demo using Google Gemini
9 * (gemini-2.5-flash).
10 *
11 * Set the environment variable GEMINI_API_KEY before running:
12 *
13 * export GEMINI_API_KEY=your_key_here
14 *
15 */
16 public class Main {
17
18 public static void main(String[] args) {
19 String apiKey = System.getenv("GEMINI_API_KEY");
20 if (apiKey == null || apiKey.isBlank()) {
21 System.err.println("ERROR: GEMINI_API_KEY environment variable is not set.");
22 System.exit(1);
23 }
24
25 // Build the Gemini chat model
26 GeminiChatModel model = GeminiChatModel.builder()
27 .apiKey(apiKey)
28 .modelName("gemini-2.5-flash")
29 .build();
30
31 // Build the ReActAgent
32 ReActAgent agent = ReActAgent.builder()
33 .name("Assistant")
34 .sysPrompt("You are a helpful AI assistant.")
35 .model(model)
36 .build();
37
38 // Send a message and print the response
39 Msg response = agent.call(
40 Msg.builder()
41 .textContent("Hello! Tell me a fun fact about Java programming.")
42 .build()
43 ).block();
44
45 System.out.println("Agent response:");
46 System.out.println(response.getTextContent());
47 }
48 }
This simple example relies on the fluent API provided by the AgentScope core library, specifically the GeminiChatModel.builder() and ReActAgent.builder() methods. This pattern allows for a clean separation between the model’s configuration, such as the API key and model version, and the agent’s behavioral definition, including its name and system instructions. By encapsulating these details within the builder, the code remains readable and easily extensible for more complex agent behaviors or multi-model configurations.
Once the agent is initialized the communication is handled via the Msg object, which standardizes the format for inputs and outputs. The call to agent.call().block() demonstrates a synchronous execution flow where the application waits for the agent to complete its reasoning and generate a response before proceeding. This straightforward interaction demonstrates how quickly developers can transition from boilerplate setup to functional AI driven logic, extracting the text content from the final message object to provide immediate feedback to the user.
When we run this code, the output trace represents the initial “Hello World” execution of the AgentScope framework, providing a baseline for verifying the connectivity between the Java application and the Google Gemini backend. When the user executes the make run command, the JVM loads the Main class and initializes the GeminiChatModel using the provided API credentials. The console log reveals an immediate interaction with the Google GenAI client, including a warning about environment variable precedence that ensures developers are aware of which key is actively billing. The final “Agent response” section confirms that the ReActAgent successfully transmitted the text prompt to the gemini-2.5-flash model, received a structured response regarding the historical origins of the Java language, and printed it to the standard output. Here is sample output:
1 $ make run
2 java -cp target/agentscope-gemini-1.0.0-SNAPSHOT.jar com.markwatson.agentscope.Main
3 Mar 25, 2026 1:49:28 PM com.google.genai.ApiClient getApiKeyFromEnv
4 WARNING: Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.
5 Agent response:
6 Hello there! Here's a fun fact about Java programming:
7
8 Java was originally named **"Oak"** by its creator, James Gosling, after an oak tree outside his office. However, it was later renamed **"Java"** after the type of coffee the developers were drinking a lot of during its creation – which is why the iconic Java logo is a steaming coffee cup! ☕
The trace demonstrates the efficiency of the gemini-2.5-flash model in a zero-shot conversational context. Despite the internal complexity of the ReAct (Reasoning and Acting) architecture, the agent identifies that the user’s request for a “fun fact” does not require external tools, leading it to generate a direct response from its internal training data. This illustrates the “path of least resistance” in agentic workflows: the agent only engages in complex multi-step reasoning when the task demands it, otherwise acting as a highly responsive chat interface.
Technically, the log confirms that the agent.call().block() sequence in the source code functions as expected, holding the main thread until the remote inference is complete. The inclusion of the coffee related trivia and the steaming cup emoji highlights the model’s ability to maintain a helpful, engaging persona as defined by the system prompt. For a developer, this successful run serves as the critical “smoke test,” proving that the environment, dependencies, and network permissions are all correctly configured before moving on to more advanced tool integrated examples.
Using the Java Implementation of AgentScope: Tool Use
Here is an example defining and using three tools that can be found in the file Java-AI-Book/source-code/AgentScope_gemini/src/main/java/com/markwatson/agentscope/ToolUseExample.java
In this section, we expand the capabilities of our agent by introducing the tool calling mechanism, enabling a Large Language Model to interact directly with external services and the local filesystem. The following code defines two service classes, WeatherService and FileService, which use the @Tool and @ToolParam annotations to provide the agent with semantic descriptions of available functions, specifically for retrieving weather data, listing directory contents, and reading file snippets. These tools are bundled into a Toolkit and attached to the ReActAgent, allowing the model to transition from simple text generation to an iterative “Reasoning and Acting” cycle. By processing complex, multi-step queries—such as searching for specific file types and summarizing their contents, and the agent demonstrates its ability to autonomously select the appropriate tool, pass the correct parameters, and synthesize the results into a coherent response.
1 import io.agentscope.core.message.Msg;
2 import io.agentscope.core.model.GeminiChatModel;
3 import io.agentscope.core.tool.Tool;
4 import io.agentscope.core.tool.ToolParam;
5 import io.agentscope.core.tool.Toolkit;
6
7 import java.io.IOException;
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10 import java.nio.file.Paths;
11 import java.util.List;
12 import java.util.stream.Collectors;
13 import java.util.stream.Stream;
14
15 /**
16 * Demonstrates AgentScope tool use with a stub "get weather" tool plus two
17 * real filesystem tools: {@code list_dir} and {@code read_file}.
18 *
19 * <p>The agent is asked two things:
20 * <ol>
21 * <li>What is the weather in Tokyo and Paris?</li>
22 * <li>List the current directory and display the first 10 lines of every
23 * {@code .md} file found there.</li>
24 * </ol>
25 *
26 * <pre>
27 * export GEMINI_API_KEY=your_key_here
28 * make run-tool
29 * </pre>
30 */
31 public class ToolUseExample {
32
33 // ------------------------------------------------------------------ //
34 // Stub weather tool //
35 // ------------------------------------------------------------------ //
36 public static class WeatherService {
37
38 @Tool(description = "Get the current weather for a specified city")
39 public String getWeather(
40 @ToolParam(name = "city", description = "The name of the city") String city) {
41 // Stub: in a real app you would call a weather API here
42 return String.format("%s weather: Sunny, 25°C", city);
43 }
44 }
45
46 // ------------------------------------------------------------------ //
47 // Filesystem tools //
48 // ------------------------------------------------------------------ //
49 public static class FileService {
50
51 @Tool(description = "List the files and sub-directories inside a directory")
52 public String listDir(
53 @ToolParam(name = "path", description = "Absolute or relative path of the directory to list") String path) {
54 try (Stream<Path> entries = Files.list(Paths.get(path))) {
55 String listing = entries
56 .map(p -> (Files.isDirectory(p) ? "[DIR] " : "[FILE] ") + p.getFileName())
57 .sorted()
58 .collect(Collectors.joining("\n"));
59 return listing.isEmpty() ? "(empty directory)" : listing;
60 } catch (IOException e) {
61 return "Error listing directory: " + e.getMessage();
62 }
63 }
64
65 @Tool(description = "Read the first N lines of a text file")
66 public String readFile(
67 @ToolParam(name = "path", description = "Path to the file to read") String path,
68 @ToolParam(name = "max_lines", description = "Maximum number of lines to return (default 10)") int maxLines) {
69 try {
70 List<String> lines = Files.readAllLines(Paths.get(path));
71 return lines.stream()
72 .limit(maxLines <= 0 ? 10 : maxLines)
73 .collect(Collectors.joining("\n"));
74 } catch (IOException e) {
75 return "Error reading file: " + e.getMessage();
76 }
77 }
78 }
79
80 // ------------------------------------------------------------------ //
81 // Main //
82 // ------------------------------------------------------------------ //
83 public static void main(String[] args) {
84 String apiKey = System.getenv("GEMINI_API_KEY");
85 if (apiKey == null || apiKey.isBlank()) {
86 System.err.println("ERROR: GEMINI_API_KEY environment variable is not set.");
87 System.exit(1);
88 }
89
90 // Build the Gemini chat model
91 GeminiChatModel model = GeminiChatModel.builder()
92 .apiKey(apiKey)
93 .modelName("gemini-2.5-flash")
94 .build();
95
96 // Register all tools
97 Toolkit toolkit = new Toolkit();
98 toolkit.registerTool(new WeatherService());
99 toolkit.registerTool(new FileService());
100
101 // Build the ReActAgent with the toolkit attached
102 ReActAgent agent = ReActAgent.builder()
103 .name("AssistantAgent")
104 .sysPrompt("You are a helpful assistant with access to weather data and the local filesystem.")
105 .model(model)
106 .toolkit(toolkit)
107 .build();
108
109 // --- Query 1: weather ---
110 Msg weatherResponse = agent.call(
111 Msg.builder()
112 .textContent("What is the weather like in Tokyo and Paris?")
113 .build()
114 ).block();
115
116 System.out.println("=== Weather Query ===");
117 System.out.println(weatherResponse.getTextContent());
118
119 // --- Query 2: filesystem ---
120 String cwd = System.getProperty("user.dir");
121 Msg fsResponse = agent.call(
122 Msg.builder()
123 .textContent("List the directory \"" + cwd + "\" and for every .md file you find there, " +
124 "display its name followed by its first 10 lines.")
125 .build()
126 ).block();
127
128 System.out.println("\n=== Filesystem Query ===");
129 System.out.println(fsResponse.getTextContent());
130 }
131 }
The core of this example lies in the declarative registration of tools via the Toolkit class. By annotating standard Java methods, you provide the underlying Gemini model with documentation it can consult when it encounters a problem it cannot solve with internal knowledge alone. For instance, when tasked with listing a directory, the agent recognizes that its internal training data doesn’t include your local files; it then triggers a call to listDir, processes the returned string, and intelligently decides to call readFile for each relevant .md file it identifies in the output.
This orchestration is managed by the ReActAgent, which handles the complex loop of generating a thought, executing a tool call, and observing the result. The use of System.getProperty("user.dir") ensures the agent has a valid starting point for its filesystem operations, while the Msg builder facilitates a clean exchange of information. This pattern effectively transforms the AI from a passive chatbot into an active participant capable of performing real-world tasks and handling I/O operations within a secure, developer-defined sandbox.
The following sample output trace illustrates the actual runtime behavior of the tool-augmented agent as it executes on the JVM. Upon launching the application via make run-tool, the AgentScope framework initializes the Toolkit, explicitly logging the registration of the getWeather, listDir, and readFile methods. The console output highlights the agent’s ability to parse complex natural language queries and map them to these registered Java methods. In the first interaction, the agent correctly identifies the need for external data and invokes the weather stub for both Tokyo and Paris. In the second, more complex interaction, the agent performs a multi-step workflow: it first retrieves a directory listing, identifies a relevant Markdown file, and subsequently calls the file-reading utility to extract and display the header content of the project’s documentation. Here is the sample output:
1 $ make run-tool
2 java -cp target/agentscope-gemini-1.0.0-SNAPSHOT.jar com.markwatson.agentscope.ToolUseExample
3 Mar 25, 2026 1:50:53 PM com.google.genai.ApiClient getApiKeyFromEnv
4 WARNING: Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.
5
6 [main] INFO io.agentscope.core.tool.Toolkit - Registered tool 'getWeather' in group 'ungrouped'
7 [main] INFO io.agentscope.core.tool.Toolkit - Registered tool 'listDir' in group 'ungrouped'
8 [main] INFO io.agentscope.core.tool.Toolkit - Registered tool 'readFile' in group 'ungrouped'
9
10 === Weather Query ===
11 The weather in Tokyo is Sunny with a temperature of 25°C. In Paris, it's also Sunny with a temperature of 25°C.
12
13 === Filesystem Query ===
14 The file README.md has the following first 10 lines:
15 ``
16 # AgentScope + Gemini Example
17
18 AgentScope is a framework for building LLM-powered applications and multi-agent systems on the JVM. Here we only look at two simple examples: a hello world example and a tool use example.
19
20 Please refer to [AgentScope](https://java.agentscope.io) for more information.
21 More docs: [https://java.agentscope.io/en/quickstart/installation.html](https://java.agentscope.io/en/quickstart/installation.html).
22
23 ## Background
24
25 **AgentScope** is an open-source, agent-oriented Java framework developed by **Alibaba Group**.
26 ``
Wrap Up: From Simple Chat to Autonomous Tool Use
The transition from a basic conversational agent to a tool augmented system represents a significant leap in the utility of LLM powered applications. In the first example, we established the fundamental plumbing required to connect a Java application to the Google Gemini backend using the AgentScope framework. This “Hello World” implementation proved that a ReActAgent can function as a standard chat interface, processing natural language and maintaining a persona with minimal boilerplate code. It serves as the foundation, ensuring that environment variables, network configurations, and model authentication are correctly synchronized before introducing more complex logic.
The second example elevated the agent’s role from a passive information retriever to an active participant in the local computing environment. By registering a Toolkit containing both a simulated weather service and a concrete filesystem service, we demonstrated how the agent utilizes its reasoning loop to solve multi step problems. The ability of the agent to “plan” its actions by first listing a directory, identifying relevant files, and then selectively reading their content, showcases the power of the Reasoning and Acting (ReAct) paradigm. This architecture allows developers to build safe, sandboxed environments where AI can perform real world tasks, transforming a static model into a dynamic assistant capable of interacting with proprietary data and external APIs.
Together, these examples illustrate the scalability of the AgentScope framework. Whether you are building a simple customer service bot or a complex autonomous researcher capable of navigating a codebase, the pattern remains consistent: define the model, describe the tools, and let the agent’s reasoning engine bridge the gap. As you move forward, you can extend these concepts by adding more specialized tools, implementing custom error handling logic, or even orchestrating multiple agents to collaborate on shared tasks within the same JVM environment.