agentscope-ai / agentscope-ai/agentscope-java

[Bug]: Tool groups activated at build time are lost on first call for new sessions

Aberta
#2,200 5 comentários 0 reações 0 responsáveis Ver no GitHub
area/core/agent area/core/tool bug
Linguagem predominante
Java
Estrelas
5.6k
Forks
1.3k
Merge médio
4d 12h
PRs com merge (30d)
77

Descrição

**Describe the bug**

When creating a `ReActAgent` with a `Toolkit` that has tool groups activated at build time (via `toolkit.createToolGroup(name, desc, true)`), the activated groups are silently lost on the **first call** for any new session. This results in an empty `tools` array being sent to the LLM — the model cannot call any tools.

**To Reproduce**

Steps to reproduce the behavior:

1. Create a `Toolkit` and register a tool group with `active=true`:

```java
Toolkit toolkit = new Toolkit();
toolkit.createToolGroup("myTools", "My tool group", true);
toolkit.registration().tool(myToolObject).group("myTools").apply();

// At this point, toolkit.getActiveGroups() returns ["myTools"] ✓
```

2. Build a `ReActAgent` with this toolkit and an `AgentStateStore`:

```java
ReActAgent agent = ReActAgent.builder()
.name("testAgent")
.sysPrompt("You are a helpful assistant.")
.model(someModel)
.toolkit(toolkit)
.maxIters(10)
.stateStore(agentStateStore) // ← key: stateStore is configured
.build();
```

3. Call the agent with a **new** session (no prior state in the store):

```java
RuntimeContext ctx = RuntimeContext.builder()
.sessionId("new-session-001")
.userId("user-001")
.build();

agent.call("Please use myTool to do something", ctx);
```

4. Observe that the LLM request body has an empty `tools` array — the model cannot call any tools.

**What happens internally:**

Inside `ReActAgent.activateSlotForContext()` (line 479-481):

```java
if (toolkit != null) {
toolkit.setActiveGroups(loaded.getToolContext().getActivatedGroups());
}
```

For a new session, `loadOrCreateAgentStateForSlot()` returns a `freshState()` where `ToolContextState.activatedGroups` defaults to an **empty list**. This empty list then **overwrites** the toolkit's build-time active groups via `setActiveGroups([])`.

Then in `reasoning()` (line 1947-1949):

```java
List tools = toolkit.getToolSchemas(
state.getToolContext().getActivatedGroups() // ← empty list
);
// → all grouped tools are filtered out → tools = []
```

The LLM receives a request with no `tools` field, so it cannot invoke any tool.

**Expected behavior**

Tool groups activated at build time (`active=true`) should remain active for new sessions. The initial activation state should be treated as a template, similar to how `initialPermissionContext` is handled.

**Error messages**

No exception is thrown. The bug manifests as:

- The LLM request body has an empty (or missing) `tools` array
- The model responds without calling any tools, often saying it doesn't have access to tools

**Environment (please complete the following information):**

- AgentScope-Java Version: 2.0.0-SNAPSHOT (master branch)
- Java Version: 21
- OS: Windows

**Additional context**

**Root cause:**

The constructor saves `initialPermissionContext` as a template for new sessions, but does **not** save the toolkit's initial active groups:

```java
// ReActAgent constructor (line 315):
this.initialPermissionContext = builder.permissionContext; // ✓ saved
// ⚠️ No equivalent for toolkit active groups
```

When `freshState()` creates a new `AgentState`, it builds a default `ToolContextState` with an empty `activatedGroups` list. Then `activateSlotForContext()` uses this empty list to call `toolkit.setActiveGroups([])`, clearing all build-time activations.

**Suggested fix:**

1. Save the toolkit's initial active groups in the constructor:

```java
// In constructor:
this.initialActiveGroups = agentToolkit != null
? List.copyOf(agentToolkit.getActiveGroups())
: List.of();
```

2. Use them when creating fresh state:

```java
// In freshState():
ToolContextState toolCtx = ToolContextState.builder().build();
if (!initialActiveGroups.isEmpty()) {
toolCtx.setActivatedGroups(new ArrayList<>(initialActiveGroups));
}
asb.toolContext(toolCtx);
```

This ensures that new sessions inherit the build-time tool group activation, and `activateSlotForContext()` will correctly restore the toolkit's active groups instead of clearing them.

Guia de contribuição

Abrir o guia de contribuição

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.