agentscope-ai / agentscope-ai/agentscope-java

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

Ouverte
#2,200 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
area/core/agent area/core/tool bug
Langage dominant
Java
Étoiles
5.6k
Forks
1.3k
Merge moyen
4 j 12 h
PR mergées (30 j)
77

Description

**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.

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.