Quickstart¶
Installation¶
AgentScope Java requires JDK 17 or newer. Maven 3.9+ is recommended.
Maven dependency¶
HarnessAgent is the recommended entry point — it packages workspace, long-term memory, session persistence, subagents, sandboxes, and other engineering capabilities into one builder. Depending on agentscope-harness pulls agentscope-core in transitively:
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-harness</artifactId>
<version>${agentscope.version}</version>
</dependency>
Note
The current latest version is 2.0.0-RC1 — substitute it for ${agentscope.version}. See the GitHub release notes for full release details.
If you only need a bare ReActAgent (no workspace / persistence / subagents / sandbox), depend on agentscope-core alone. The difference between the two is covered in Harness Architecture.
The DashScope / OpenAI / Anthropic / Gemini / Ollama formatters and chat models all live inside agentscope-core. MCP integration requires the official MCP SDK — see agentscope-examples/documentation/pom.xml for a working example.
Build from source¶
git clone -b main https://github.com/agentscope-ai/agentscope-java
cd agentscope-java
./mvnw -DskipTests install
Your first agent¶
The example below uses HarnessAgent to demonstrate three things at once: workspace-driven persona (AGENTS.md), automatic session persistence (the second turn with the same sessionId remembers the first), and conversation compaction (over-threshold compaction + long-term facts distilled into MEMORY.md). The model id is passed as a string to .model(...) — ModelRegistry resolves it and reads the matching API-key env var automatically.
import io.agentscope.core.agent.RuntimeContext;
import io.agentscope.core.message.UserMessage;
import io.agentscope.harness.agent.HarnessAgent;
import io.agentscope.harness.agent.memory.compaction.CompactionConfig;
import java.nio.file.Paths;
public class FirstAgent {
public static void main(String[] args) {
HarnessAgent agent = HarnessAgent.builder()
.name("note-taker")
.sysPrompt("You are a note-taking assistant.")
// String form resolved via ModelRegistry — picks up DASHSCOPE_API_KEY
// from the environment. Use "openai:gpt-5.5", "anthropic:claude-sonnet-4-5",
// "gemini:gemini-2.0-flash", or "ollama:llama3" to switch providers.
.model("dashscope:qwen-plus")
.workspace(Paths.get(".agentscope/workspace"))
.compaction(CompactionConfig.builder()
.triggerMessages(30)
.keepMessages(10)
.build())
.build();
RuntimeContext ctx = RuntimeContext.builder()
.sessionId("demo-session")
.userId("alice")
.build();
// Turn 1: introduce yourself + state today's task
agent.call(new UserMessage("My name is Alice, and I'm preparing a tech talk on ReAct today."), ctx).block();
// Turn 2: same sessionId — state from turn 1 is restored automatically
agent.call(new UserMessage("What is my name? What am I doing today?"), ctx).block();
}
}
After this run the workspace directory has grown:
.agentscope/workspace/
├── AGENTS.md ← write one to give the agent its persona (optional)
└── agents/note-taker/
├── context/demo-session/ ← AgentState auto-saved / auto-loaded
└── sessions/ ← never-compacted raw conversation log
Restart the process with the same sessionId and the second turn still remembers the first — because AgentState lives under agents/note-taker/context/demo-session/. After enough turns trip compaction, distilled facts first land in workspace/memory/YYYY-MM-DD.md, then a throttled background job merges them into MEMORY.md, which is injected into the system prompt on the next reasoning step.
Streaming reasoning and tool calls¶
Swap call(...) for streamEvents(...) to receive incremental events — text deltas, tool calls, etc. — suitable for Web / TUI rendering:
import io.agentscope.core.event.AgentEventType;
import io.agentscope.core.event.TextBlockDeltaEvent;
import io.agentscope.core.event.ToolCallStartEvent;
agent.streamEvents(new UserMessage("Summarize today in three bullets."))
.doOnNext(event -> {
if (event.getType() == AgentEventType.TEXT_BLOCK_DELTA) {
// Streaming text fragment — append to UI or stdout
System.out.print(((TextBlockDeltaEvent) event).getDelta());
} else if (event.getType() == AgentEventType.TOOL_CALL_START) {
// The agent is about to call a tool — surface the call info
System.out.println("\n[tool] " + ((ToolCallStartEvent) event).getToolName());
}
// Other events: thinking blocks, tool results, reply end, etc.
})
.blockLast();
Tip
Set DASHSCOPE_API_KEY in the environment before running. To switch providers, change the string passed to .model(...) and export the matching API key (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY). When you need explicit control over timeouts or custom endpoints, build the model with DashScopeChatModel.builder()...build() and pass it to .model(Model) instead.
Next steps¶
Agent — full
ReActAgentAPI, builder fields,call/streamEvents/observe, human-in-the-loop, Session configurationHarness Architecture — how
HarnessAgent’s capabilities cooperate, how state flowsWorkspace —
AGENTS.md/MEMORY.md/skills//subagents//tools.jsondirectory layout and loading modelFilesystem — local + shell / shared store / sandbox deployment modes