V1 Migration Guide

Tip

Looking for per-version change records? See Release Notes.

AgentScope Java 2.0 aims to preserve compatibility with 1.x where possible so that most users can upgrade smoothly. That said, 2.0 does introduce API-level changes. This page splits those changes into two sections:

  • Migration Guide — what changes against 1.x, in two tiers:

    • Part A · Required — your code will fail to compile or throw at runtime if you don’t migrate

    • Part B · Recommended — still works but @Deprecated(forRemoval = true); will be removed in the next minor

  • What’s New — net-new capabilities that don’t appear in the Migration Guide

Migration Guide

Part A — Required (compile errors or runtime exceptions if you don’t migrate)

Items in this section are removed, renamed, or have their semantics tightened. Code that worked on 1.x will not work as-is on 2.0.

A.1 Removed ReActAgent.Builder methods

Removed in 2.0

Replacement

.memory(Memory)

.stateStore(AgentStateStore)AgentState.getContext() holds the conversation; the configured AgentStateStore saves/loads automatically on every call(), keyed by the call’s (userId, sessionId) from RuntimeContext

.statePersistence(StatePersistence)

Same — AgentStateStore subsumes persistence

.structuredOutputReminder(StructuredOutputReminder)

No longer needed — structured output is now handled natively at the model layer (Model.supportsNativeStructuredOutput()); the framework automatically selects native JSON schema or falls back to tool-choice

Detail → Context

A.2 Removed packages and classes

Removed in 2.0

Replacement

io.agentscope.core.session.SessionManager

Configure .stateStore(AgentStateStore) on the agent builder; persistence happens automatically per (userId, sessionId)

io.agentscope.core.pipeline.*Pipeline, Pipelines, SequentialPipeline, FanoutPipeline, MsgHub

Compose middleware + sub-agents + the event stream for multi-agent orchestration. See the subagent guide → Subagent

io.agentscope.core.model.tts.* (14 files, DashScope TTS / Realtime TTS / AudioPlayer, etc.)

Core no longer ships TTS. Integrate the upstream provider SDK directly if you need TTS

io.agentscope.core.model.StructuredOutputReminder

No longer needed — structured output is handled natively at the model layer

io.agentscope.core.agent.StructuredOutputCapableAgent

Removed — structured output capability is inlined into ReActAgent with native model-layer support

io.agentscope.core.hook.PendingToolRecoveryHook

Use Builder.enablePendingToolRecovery(boolean)

io.agentscope.core.hook.TTSHook

Removed alongside the TTS module

A.3 Model providers moved out of core

OpenAI, Gemini, Anthropic, DashScope, and Ollama chat model implementations are no longer packaged in agentscope-core. Core now keeps only shared model contracts such as Model, ChatModelBase, Formatter, ModelRegistry, and the ModelProvider SPI.

If your v1 code imported provider classes from core, replace them with the matching model extension module:

v1 import / dependency

v2 replacement

io.agentscope.core.model.OpenAIChatModel

Add agentscope-extensions-model-openai; import io.agentscope.extensions.model.openai.OpenAIChatModel

io.agentscope.core.model.GeminiChatModel

Add agentscope-extensions-model-gemini; import io.agentscope.extensions.model.gemini.GeminiChatModel

io.agentscope.core.model.AnthropicChatModel

Add agentscope-extensions-model-anthropic; import io.agentscope.extensions.model.anthropic.AnthropicChatModel

io.agentscope.core.model.DashScopeChatModel

Add agentscope-extensions-model-dashscope; import io.agentscope.extensions.model.dashscope.DashScopeChatModel

io.agentscope.core.model.OllamaChatModel

Add agentscope-extensions-model-ollama; import io.agentscope.extensions.model.ollama.OllamaChatModel

io.agentscope.core.formatter.<provider>.*

io.agentscope.extensions.model.<provider>.formatter.*

io.agentscope.core.credential.<Provider>Credential

io.agentscope.extensions.model.<provider>.credential.<Provider>Credential

ModelRegistry string ids still work, but only when the matching extension module is on the classpath:

ReActAgent agent = ReActAgent.builder()
    .name("assistant")
    .model("dashscope:qwen-plus")
    .build();

Spring Boot applications should use the provider-specific starters instead of relying on a generic core model path:

Provider

Spring Boot starter

OpenAI

agentscope-openai-spring-boot-starter

DashScope

agentscope-dashscope-spring-boot-starter

Gemini

agentscope-gemini-spring-boot-starter

Anthropic

agentscope-anthropic-spring-boot-starter

Ollama

agentscope-ollama-spring-boot-starter

Detail → Model, Model Providers

A.4 state package restructure (compile error)

v1

v2

AgentMetaState

AgentState

StateModule

removed — no longer a superclass for Memory, Toolkit, etc.

StatePersistence

removed — replaced by the AgentStateStore abstraction

ToolkitState

Moved to io.agentscope.core.state.legacy.ToolkitState (kept for compatibility only — do not reference in new code)

(new)

Task, TaskContextState, ToolContextState, PlanModeContextState, ReadCacheEntry

Any code that imports AgentMetaState, StateModule, StatePersistence, or ToolkitState from io.agentscope.core.state will fail to compile. Detail → Context

A.5 PlanNotebook removed — use HarnessAgent.enablePlanMode()

The entire io.agentscope.core.plan package (PlanNotebook, Plan, SubTask, PlanStorage, PlanToHint, and related classes) has been removed with no deprecated bridge.

What changed: PlanNotebook modeled plans as structured Plan + SubTask objects with a state machine (todo → in_progress → done → abandoned) and 8 tool functions. The v2 replacement is a fundamentally different design — plan mode is now a read-only investigation phase where the agent designs an approach in a plain markdown file before gaining write access.

v1 PlanNotebook

v2 Plan Mode

ReActAgent.builder().planNotebook(PlanNotebook.builder().build())

HarnessAgent.builder().enablePlanMode()

Structured Plan + SubTask objects with state machine

Plain markdown file (plans/PLAN.md)

8 tools: createPlan, reviseCurrentPlan, updateSubtaskState, finishSubtask, finishPlan, viewSubtasks, viewHistoricalPlans, recoverHistoricalPlan

3 tools: plan_enter, plan_write, plan_exit

Plan and execution intermixed — no read-only restriction

Plan mode is read-only; plan_exit triggers HITL gate before the agent regains write access

PlanToHint injected contextual hints per reasoning step

PlanModeMiddleware blocks mutating tools while in plan mode

PlanStorage (in-memory) + StateModule persistence

Plan file written via WorkspaceManager; state in AgentState.planModeContext

Subtask tracking: if your v1 code relied on PlanNotebook’s subtask state tracking (breaking work into subtasks and checking them off during execution), the v2 equivalent is the task list — enable it with .enableTaskList(true) on the builder, which registers TodoTools and TaskReminderMiddleware.

A.6 Msg content validation is stricter (runtime exception)

Msg now validates content against role at construction time:

  • USER — only TextBlock / DataBlock / ImageBlock / AudioBlock / VideoBlock

  • SYSTEM — only TextBlock

  • ASSISTANT — unrestricted

Combinations that v1 tolerated (for example, a USER message carrying a ToolUseBlock) now throw at construction. Use the role-pinned subclasses UserMessage / AssistantMessage / SystemMessage / ToolResultMessage to make role/content compatibility obvious at the call site. Detail → Message & Event

A.7 Agent is fully stateless (architecture change)

ReActAgent is now fully stateless — the instance itself holds no mutable “current session” state. All per-call mutable state (AgentState, PermissionEngine, event sink) is encapsulated in an internal CallExecution object and propagated through the call chain via Reactor Context. A single Agent instance can safely serve multiple (userId, sessionId) combinations concurrently without cross-session interference.

v1 → v2 impact:

Removed

Replacement

ReActAgent.getCurrentSessionId()

Supplied via RuntimeContext.getSessionId() at call() time

ReActAgent.getCurrentUserId()

Supplied via RuntimeContext.getUserId() at call() time

AgentBase(name, desc, checkRunning, hooks) constructor

Use AgentBase(name, desc, hooks)checkRunning is no longer needed; concurrency is guaranteed by per-session serialization

ReActAgent.getState()

ReActAgent.getAgentState() or getAgentState(userId, sessionId)

isCheckRunning() is still callable (returns false) and Builder.checkRunning(boolean) is still callable (ignored) — both are @Deprecated.



What’s New

The capabilities below are additive in 2.0 — none of them break 1.x code. The Migration Guide above already covers the event system, message refactor, and middleware mechanism, so they are not repeated here.

Toolkit & Permission

Tool execution is the main extension surface in 2.0, and the permission system sits directly on its execution path — so we present them together.

  • Toolkit upgrades:

    • Unified base classes: ToolBase / AgentTool

    • Tool groups: ToolGroup / ToolGroupScope / MetaToolFactory — activate on demand; the reserved basic group is always on

    • Annotation-driven registration: ReflectiveFunctionTool + @Tool / @ToolParam; Toolkit#registerTool(Object) reflectively registers any annotated methods

    • Built-in task tool: io.agentscope.core.tool.builtin.TodoTools.todoWrite (pairs with TaskReminderMiddleware)

  • Permission system (new package io.agentscope.core.permission):

    • PermissionEngine, PermissionRule, PermissionMode (DEFAULT / ACCEPT_EDITS / EXPLORE / BYPASS / DONT_ASK), PermissionBehavior

    • Every tool call goes through PermissionEngine: allow / require user confirmation / deny. HITL decisions flow back as UserConfirmResultEvent.

Detail → Tool, Permission System

Model fault tolerance and credentials

  • New package io.agentscope.core.credential — shared credential contracts and ModelCard; provider-specific credentials live with the model extension modules

  • ModelRegistry resolves models from "provider:model" strings when the matching model extension module is on the classpath (e.g. dashscope:qwen-max, openai:gpt-5)

  • Builder additions: .model(String), .maxRetries(int), .fallbackModel(Model) / .fallbackModel(String), .stopOnReject(boolean) — primary-model failure auto-retries and falls back

Detail → Model

Workspace (Harness module)

  • Workspace abstraction unifies local filesystem, Docker, and E2B cloud sandbox execution behind a single interface

  • Warm-up pool — pre-initialize execution environments in batches; useful for parallel RL rollouts

Detail → Workspace

Other new Builder methods

  • .enableTaskList(...) / .enableTaskList(boolean) — enable the built-in TodoTools

  • .permissionContext(PermissionContextState) — preload permission rules

  • ReActAgent.Builder.fromAgent(ReActAgent) — derive a new builder from an existing agent’s observable configuration (name, description, system prompt, model, maxIters, generateOptions, toolkit)

  • HarnessAgent.Builder.fromAgent(ReActAgent) — ReActAgent → HarnessAgent migration helper. Inherits the same 7 fields as ReActAgent.Builder.fromAgent plus every other observable configuration on ReActAgent: stateStore / defaultSessionId, ModelConfig (maxRetries / fallbackModel), ReactConfig.stopOnReject, modelExecutionConfig / toolExecutionConfig / toolExecutionContext, enablePendingToolRecovery, checkRunning, permissionContext, middlewares, and hooks. The only flags not copied are enableMetaTool / enableTaskList — these are builder-time toolkit-mutation flags, and the toolkit copy already carries the tools they registered. Harness-only config (workspace / filesystem / subagents / skills / plan mode / disable* toggles) still has to be set explicitly. See javadoc for the full table.

  • New getters on ReActAgent / parents to support the above migration: getModelExecutionConfig() / getToolExecutionConfig() / getToolExecutionContext() / isPendingToolRecoveryEnabled() / getPermissionContext() (on ReActAgent); isCheckRunning() (on AgentBase, deprecated, always returns false).

Detail → Agent

Dedicated model for Memory / Compaction

MemoryConfig and CompactionConfig gain .model(Model) / .model(String) builder methods, allowing a dedicated (typically lighter/cheaper) model for memory flush, consolidation, and context compaction operations independent of the agent’s primary reasoning model. When not set, the agent’s primary model is used (preserving existing behavior).

HarnessAgent.builder()
    .model("openai:o3")
    .memory(MemoryConfig.builder()
        .model("openai:gpt-4.1-mini")
        .build())
    .compaction(CompactionConfig.builder()
        .model("openai:gpt-4.1-mini")
        .build())
    .build();