Skip to content

Commit 03f0245

Browse files
author
Yuriy Bezsonov
committed
fix(java-spring-ai-agents): migrate to defaultTools, fix ContextAdvisor tool loop, align demo-scripts
- ContextAdvisor: augment the user message in place instead of removing and re-appending it (re-appending reordered it after tool-call/result messages during tool loops, causing the model to repeat tool calls) - ChatService: replace deprecated defaultToolCallbacks(...) with a second accumulating defaultTools(...) call - demo-scripts 05/06/07: same defaultTools migration; strip dead null-checks so the demo flow matches the fail-fast app - Update ContextAdvisorTest for in-place augmentation
1 parent c8d2944 commit 03f0245

7 files changed

Lines changed: 48 additions & 71 deletions

File tree

apps/java-spring-ai-agents/aiagent/src/main/java/com/example/agent/ChatService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public ChatService(AgentCoreMemory agentCoreMemory,
115115
this.chatClient = chatClientBuilder.defaultSystem(SYSTEM_PROMPT)
116116
.defaultAdvisors(advisors.toArray(new Advisor[0]))
117117
.defaultTools(localTools.toArray())
118-
.defaultToolCallbacks(toolCallbackProviders.toArray(new ToolCallbackProvider[0]))
118+
.defaultTools(toolCallbackProviders.toArray())
119119
.build();
120120
}
121121

apps/java-spring-ai-agents/aiagent/src/main/java/com/example/agent/ContextAdvisor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ public ChatClientRequest before(ChatClientRequest request, AdvisorChain advisorC
2727
List<Message> messages = new ArrayList<>(original.getInstructions());
2828
UserMessage userMsg = original.getUserMessage();
2929
if (userMsg != null) {
30-
messages.remove(userMsg);
31-
messages.add(new UserMessage("[Current date and time: " + timestamp + "]"));
32-
messages.add(new UserMessage("[UserId: " + userId + "]\n" + userMsg.getText()));
30+
int idx = messages.lastIndexOf(userMsg);
31+
messages.set(idx, new UserMessage(
32+
"[Current date and time: " + timestamp + "] [UserId: " + userId + "]\n" + userMsg.getText()));
3333
}
3434

3535
Prompt augmented = new Prompt(messages, original.getOptions());

apps/java-spring-ai-agents/aiagent/src/test/java/com/example/agent/ContextAdvisorTest.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ void before_withConversationId_injectsTimestampAndUserId() {
3434
List<Message> messages = result.prompt().getInstructions();
3535
List<String> texts = messages.stream().map(Message::getText).toList();
3636

37-
// Original system message is preserved.
38-
assertThat(texts).anyMatch(t -> t.equals("system prompt"));
39-
// Timestamp message is added.
40-
assertThat(texts).anyMatch(t -> t.startsWith("[Current date and time:"));
41-
// User id is extracted from the conversation id (before the colon) and the original text retained.
42-
assertThat(texts).anyMatch(t -> t.startsWith("[UserId: user-123]") && t.contains("hello world"));
43-
// The bare original user message was replaced (not left as plain "hello world").
44-
assertThat(texts).doesNotContain("hello world");
37+
// Order is preserved and no extra messages are added (augmented in place).
38+
assertThat(messages).hasSize(2);
39+
assertThat(texts.get(0)).isEqualTo("system prompt");
40+
// The user message is augmented in place with timestamp + userId + original text.
41+
assertThat(texts.get(1))
42+
.startsWith("[Current date and time:")
43+
.contains("[UserId: user-123]")
44+
.contains("hello world");
4545
}
4646

4747
@Test
@@ -52,7 +52,7 @@ void before_withoutConversationId_usesUnknownUserId() {
5252
ChatClientRequest result = advisor.before(request, null);
5353

5454
List<String> texts = result.prompt().getInstructions().stream().map(Message::getText).toList();
55-
assertThat(texts).anyMatch(t -> t.startsWith("[UserId: unknown]") && t.contains("hi"));
55+
assertThat(texts).anyMatch(t -> t.contains("[UserId: unknown]") && t.contains("hi"));
5656
}
5757

5858
@Test

apps/java-spring-ai-agents/demo-scripts/04-tools.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class ContextAdvisor implements BaseAdvisor {
5757
List<Message> messages = new ArrayList<>(original.getInstructions());
5858
UserMessage userMsg = original.getUserMessage();
5959
if (userMsg != null) {
60-
messages.remove(userMsg);
61-
messages.add(new UserMessage("[Current date and time: " + timestamp + "]"));
62-
messages.add(new UserMessage("[UserId: " + userId + "]\n" + userMsg.getText()));
60+
int idx = messages.lastIndexOf(userMsg);
61+
messages.set(idx, new UserMessage(
62+
"[Current date and time: " + timestamp + "] [UserId: " + userId + "]\n" + userMsg.getText()));
6363
}
6464
6565
Prompt augmented = new Prompt(messages, original.getOptions());

apps/java-spring-ai-agents/demo-scripts/05-browser.sh

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,44 +93,38 @@ public class ChatService {
9393
logger.info("Memory enabled: {} advisors", agentCoreMemory.advisors.size());
9494
9595
// Knowledge Base (RAG)
96-
if (kbVectorStore != null) {
97-
advisors.add(QuestionAnswerAdvisor.builder(kbVectorStore)
98-
.promptTemplate(PromptTemplate.builder().template("""
99-
{query}
100-
101-
The following documents may be relevant as reference material:
102-
{question_answer_context}
103-
""").build())
104-
.build());
105-
logger.info("KB RAG enabled");
106-
}
96+
advisors.add(QuestionAnswerAdvisor.builder(kbVectorStore)
97+
.promptTemplate(PromptTemplate.builder().template("""
98+
{query}
99+
100+
The following documents may be relevant as reference material:
101+
{question_answer_context}
102+
""").build())
103+
.build());
104+
logger.info("KB RAG enabled");
107105
108106
// ContextAdvisor
109107
advisors.add(contextAdvisor);
110108
logger.info("Context Advisor enabled");
111109
112110
// Tools
113111
List<Object> localTools = new ArrayList<>();
114-
if (webGroundingTools != null) {
115-
localTools.add(webGroundingTools);
116-
logger.info("Web Grounding enabled");
117-
}
112+
localTools.add(webGroundingTools);
113+
logger.info("Web Grounding enabled");
118114
119115
// Browser
120116
this.browserArtifactStore = browserArtifactStore;
121117
122118
// Tool Callback Providers
123119
List<ToolCallbackProvider> toolCallbackProviders = new ArrayList<>();
124-
if (browserTools != null) {
125-
toolCallbackProviders.add(browserTools);
126-
logger.info("Browser enabled");
127-
}
120+
toolCallbackProviders.add(browserTools);
121+
logger.info("Browser enabled");
128122
129123
this.chatClient = chatClientBuilder
130124
.defaultSystem(SYSTEM_PROMPT)
131125
.defaultAdvisors(advisors.toArray(new Advisor[0]))
132126
.defaultTools(localTools.toArray())
133-
.defaultToolCallbacks(toolCallbackProviders.toArray(new ToolCallbackProvider[0]))
127+
.defaultTools(toolCallbackProviders.toArray())
134128
.build();
135129
}
136130
@@ -152,9 +146,6 @@ public class ChatService {
152146
}
153147
154148
private Flux<String> appendScreenshots(String sessionId) {
155-
if (browserArtifactStore == null) {
156-
return Flux.empty();
157-
}
158149
List<GeneratedFile> screenshots = browserArtifactStore.retrieve(sessionId);
159150
if (screenshots == null || screenshots.isEmpty()) {
160151
return Flux.empty();

apps/java-spring-ai-agents/demo-scripts/06-code-interpreter.sh

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,24 @@ public class ChatService {
7979
logger.info("Memory enabled: {} advisors", agentCoreMemory.advisors.size());
8080
8181
// Knowledge Base (RAG)
82-
if (kbVectorStore != null) {
83-
advisors.add(QuestionAnswerAdvisor.builder(kbVectorStore)
84-
.promptTemplate(PromptTemplate.builder().template("""
85-
{query}
86-
87-
The following documents may be relevant as reference material:
88-
{question_answer_context}
89-
""").build())
90-
.build());
91-
logger.info("KB RAG enabled");
92-
}
82+
advisors.add(QuestionAnswerAdvisor.builder(kbVectorStore)
83+
.promptTemplate(PromptTemplate.builder().template("""
84+
{query}
85+
86+
The following documents may be relevant as reference material:
87+
{question_answer_context}
88+
""").build())
89+
.build());
90+
logger.info("KB RAG enabled");
9391
9492
// ContextAdvisor
9593
advisors.add(contextAdvisor);
9694
logger.info("Context Advisor enabled");
9795
9896
// Tools
9997
List<Object> localTools = new ArrayList<>();
100-
if (webGroundingTools != null) {
101-
localTools.add(webGroundingTools);
102-
logger.info("Web Grounding enabled");
103-
}
98+
localTools.add(webGroundingTools);
99+
logger.info("Web Grounding enabled");
104100
105101
// Browser
106102
this.browserArtifactStore = browserArtifactStore;
@@ -110,20 +106,16 @@ public class ChatService {
110106
111107
// Tool Callback Providers
112108
List<ToolCallbackProvider> toolCallbackProviders = new ArrayList<>();
113-
if (browserTools != null) {
114-
toolCallbackProviders.add(browserTools);
115-
logger.info("Browser enabled");
116-
}
117-
if (codeInterpreterTools != null) {
118-
toolCallbackProviders.add(codeInterpreterTools);
119-
logger.info("Code Interpreter enabled");
120-
}
109+
toolCallbackProviders.add(browserTools);
110+
logger.info("Browser enabled");
111+
toolCallbackProviders.add(codeInterpreterTools);
112+
logger.info("Code Interpreter enabled");
121113
122114
this.chatClient = chatClientBuilder
123115
.defaultSystem(SYSTEM_PROMPT)
124116
.defaultAdvisors(advisors.toArray(new Advisor[0]))
125117
.defaultTools(localTools.toArray())
126-
.defaultToolCallbacks(toolCallbackProviders.toArray(new ToolCallbackProvider[0]))
118+
.defaultTools(toolCallbackProviders.toArray())
127119
.build();
128120
}
129121
@@ -146,9 +138,6 @@ public class ChatService {
146138
}
147139
148140
private Flux<String> appendScreenshots(String sessionId) {
149-
if (browserArtifactStore == null) {
150-
return Flux.empty();
151-
}
152141
List<GeneratedFile> screenshots = browserArtifactStore.retrieve(sessionId);
153142
if (screenshots == null || screenshots.isEmpty()) {
154143
return Flux.empty();
@@ -169,9 +158,6 @@ public class ChatService {
169158
}
170159
171160
private Flux<String> appendGeneratedFiles(String sessionId) {
172-
if (codeInterpreterArtifactStore == null) {
173-
return Flux.empty();
174-
}
175161
List<GeneratedFile> files = codeInterpreterArtifactStore.retrieve(sessionId);
176162
if (files == null || files.isEmpty()) {
177163
return Flux.empty();

apps/java-spring-ai-agents/demo-scripts/07-mcp.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ if ! grep -q "mcpToolCallbacks" "$CHATSERVICE"; then
127127
sed -i '/this.chatClient = chatClientBuilder/i \
128128
\ // Tool Callback Providers\n List<ToolCallbackProvider> toolCallbackProviders = new ArrayList<>();\n\n // MCP Tools\n if (mcpTools != null) {\n toolCallbackProviders.add(mcpTools);\n logger.info("MCP tools enabled");\n }\n' "$CHATSERVICE"
129129

130-
# Add .defaultToolCallbacks() to builder
131-
sed -i 's/\.build();/.defaultToolCallbacks(toolCallbackProviders.toArray(new ToolCallbackProvider[0]))\n .build();/' "$CHATSERVICE"
130+
# Add second .defaultTools() call to builder for the tool callback providers
131+
sed -i 's/\.build();/.defaultTools(toolCallbackProviders.toArray())\n .build();/' "$CHATSERVICE"
132132
fi
133133
fi
134134

0 commit comments

Comments
 (0)