Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the AI Agent component to wire Spring AI tool-calling support via ToolCallingManager/ToolCallAdvisor, and introduces explicit advisor ordering so chat-memory advisors run with a defined precedence.
Changes:
- Inject
ToolCallingManagerthrough the AI Agent component handler/actions and addToolCallAdvisorto the advisor chain. - Define explicit advisor ordering for chat-memory advisors (Prompt/VectorStore variants).
- Update unit tests to match new constructors/signatures.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| server/libs/modules/components/ai/agent/src/test/java/com/bytechef/component/chat/AiAgentComponentHandlerTest.java | Updates handler construction for the new constructor signature. |
| server/libs/modules/components/ai/agent/src/test/java/com/bytechef/component/ai/agent/action/AbstractAiAgentChatActionTest.java | Adds ToolCallingManager mocking and updates action construction. |
| server/libs/modules/components/ai/agent/src/main/java/com/bytechef/component/ai/agent/AiAgentComponentHandler.java | Injects ToolCallingManager and wires it into chat/stream chat actions. |
| server/libs/modules/components/ai/agent/src/main/java/com/bytechef/component/ai/agent/action/AiAgentStreamChatAction.java | Threads ToolCallingManager into the stream chat action. |
| server/libs/modules/components/ai/agent/src/main/java/com/bytechef/component/ai/agent/action/AiAgentChatAction.java | Threads ToolCallingManager into the chat action and updates factory method signature. |
| server/libs/modules/components/ai/agent/src/main/java/com/bytechef/component/ai/agent/action/AbstractAiAgentChatAction.java | Adds ToolCallAdvisor wiring and adjusts advisor composition around chat memory. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-vectorstore/src/main/java/com/bytechef/component/ai/chat/memory/cluster/VectorStoreChatMemory.java | Sets explicit advisor order for vectorstore chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-redis/src/main/java/com/bytechef/component/ai/agent/chat/memory/redis/cluster/RedisChatMemory.java | Sets explicit advisor order for redis chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-neo4j/src/main/java/com/bytechef/component/ai/agent/chat/memory/neo4j/cluster/Neo4jChatMemory.java | Sets explicit advisor order for neo4j chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-mongodb/src/main/java/com/bytechef/component/ai/agent/chat/memory/mongodb/cluster/MongoDbChatMemory.java | Sets explicit advisor order for mongodb chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-jdbc/src/main/java/com/bytechef/component/ai/agent/chat/memory/jdbc/cluster/JdbcChatMemory.java | Sets explicit advisor order for jdbc chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-in-memory/src/main/java/com/bytechef/component/ai/agent/chat/memory/memory/cluster/InMemoryChatMemory.java | Sets explicit advisor order for in-memory chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-cosmosdb/src/main/java/com/bytechef/component/ai/agent/chat/memory/cosmosdb/cluster/CosmosDbChatMemory.java | Sets explicit advisor order for cosmosdb chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-cassandra/src/main/java/com/bytechef/component/ai/agent/chat/memory/cassandra/cluster/CassandraChatMemory.java | Sets explicit advisor order for cassandra chat memory advisor. |
| server/libs/modules/components/ai/agent/chat-memory/chat-memory-builtin/src/main/java/com/bytechef/component/ai/agent/chat/memory/builtin/cluster/ChatMemory.java | Sets explicit advisor order for builtin chat memory advisor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
edb55d1 to
a400eee
Compare
c6bd156 to
a400eee
Compare
|
need to wait for #5009 before merging |
b7c086f to
a6b8ee3
Compare
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
This comment has been minimized.
This comment has been minimized.
e455f18 to
cfedcf1
Compare
1bb2823 to
030c7ee
Compare
9b62519 to
c38a5ad
Compare
…visor wiring Standardize (AiAgentToolFacade, ClusterElementDefinitionService, ToolCallingManager) across AiAgentChatAction.of, AiAgentStreamChatAction.of, their constructors, and the AiAgentComponentHandler call sites. Add tests asserting ToolCallAdvisor is present in the advisor list and that disableInternalConversationHistory() is applied only when a chat-memory advisor is configured. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…participates in every tool-call iteration The previous setup ran every chat-memory advisor at HIGHEST_PRECEDENCE + 200 and ToolCallAdvisor at HIGHEST_PRECEDENCE + 300 — Spring's lower-order-runs-first contract meant memory ran ONCE outside the tool-call loop. With disableInternalConversationHistory() enabled, ToolCallAdvisor passes only [system, lastMessage] between loop iterations and expects a downstream ChatMemoryAdvisor to supply the preceding assistant-with-tool-calls. Because no advisor was downstream, iteration 2 reached the model as just [system, toolResultMsg], producing the OpenAI 400 "messages with role 'tool' must be a response to a preceding message with 'tool_calls'" error. Drop the explicit orders on both sides so each advisor falls back to its Spring AI default: ToolCallAdvisor at HIGHEST_PRECEDENCE + 300 (its DEFAULT_ORDER) and the seven non-vector chat-memory advisors at DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER (Integer.MIN_VALUE + 1000). The vector-store advisor already uses the default after commit 37fb7aa8ae3. Spring AI documents these defaults as designed to compose — ToolCallAdvisor.DEFAULT_ORDER's Javadoc states "Placed early in the chain so that all downstream advisors (e.g. BaseChatMemoryAdvisor) participate in every tool-call iteration." Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… to ToolCallAdvisor testChatMemoryAdvisorOrderedDownstreamOfToolCallAdvisor builds the agent's advisor chain end-to-end with a production-style MessageChatMemoryAdvisor (built via the Spring AI builder default, the same way every chat-memory component now constructs it) and asserts its order is greater than the ToolCallAdvisor's. Verified by hand that this test fails when the previous buggy ordering is restored — catching the exact regression that produced OpenAI's "messages with role 'tool' must be a response to a preceding message with 'tool_calls'" failure. testSpringAiDefaultOrdersComposeCorrectly pins the Spring AI defaults directly (ToolCallAdvisor.builder().build().getOrder() vs MessageChatMemoryAdvisor.builder(...).build().getOrder()) so a future spring-ai version bump that inverts those defaults fails the test at the bump PR instead of producing chat-memory breakage in production. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… manually-registered ToolCallAdvisor Spring AI 2.0's docs make this call look optional or removable — auto-registered ToolCallAdvisors get the auto-disable behavior when a downstream ChatMemoryAdvisor is detected. Manually-registered ones (which we need because SuspendableToolCallingManager wraps the default ToolCallingManager) skip that path entirely, so the explicit call is load-bearing. Comment the WHY so a future reader doesn't reach for the obvious-looking deletion. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
M7 removes spring-ai-model-chat-memory-repository-cosmos-db (#6080), so delete the chat-memory-cosmosdb component along with its docs row and generated reference page. M7's "Sanitize Spring Boot related dependencies" (#6088) also stops leaking spring-boot-jdbc and spring-boot-autoconfigure transitively, so declare them explicitly in the two modules that were relying on the leak. The custom ToolCallAdvisor registration in AbstractAiAgentChatAction stays as-is: manual registration suppresses M7's new auto-registration (#5459), and SuspendableToolCallingManager requires the explicit toolCallingManager wiring that auto-registration cannot provide. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…AI M7 ToolSpec API Spring AI 2.0.0-M7 deprecated and marked for removal both ChatClient.ChatClientRequestSpec.toolCallbacks(List) and ChatClient.ChatClientRequestSpec.toolContext(Map) in favor of a unified tools(Consumer<ToolSpec>) entry point (see PR #6085 "Introduce ToolSpec fluent API"). This branch has a single deprecated call site — the toolCallbacks() registration in AbstractAiAgentChatAction — which is replaced with the new tools(spec -> spec.callbacks(...)) form. Behavior is identical; the new API just consolidates tool registration into a single fluent surface. (The toolContext() migrations from the upstream change live in suspend/resume code that is not part of this branch.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….0.0-M3
Two related fixes for the recently bumped Spring AI 2.0.0-M7:
1) Spring AI M7 packaging oversight. The M7 spring-ai-starter-mcp-client
POM no longer depends on spring-ai-autoconfigure-mcp-client-common,
but spring-ai-autoconfigure-mcp-client-httpclient:2.0.0-M7 still
references classes in org.springframework.ai.mcp.client.common.
autoconfigure.* (McpSseClientProperties, NamedClientMcpTransport,
etc.). Boot fails at the bean-definition phase with
ClassNotFoundException for McpSseClientProperties. The M7 jar exists
on Maven Central (just not listed in the directory index) so an
explicit dependency on spring-ai-autoconfigure-mcp-client-common
pulls it back in. Added with a comment explaining the workaround so
it can be removed once a future Spring AI release re-includes the
transitive dependency.
2) MCP SDK 2.0.0-M3 sync. The version pin in libs.versions.toml was
still M2 even though Spring AI M7 already resolves mcp-core to M3
transitively. Bumped to M3 explicitly to remove the mixed-version
state, and updated the forked FilterableMcpAsyncServer.java to match
the upstream M3 changes:
- DefaultMcpStreamableServerSessionFactory constructor now takes a
trailing jsonSchemaValidator parameter
- addTool() validates the tool's inputSchema / outputSchema via
jsonSchemaValidator.assertConforms() before insertion
- McpSchema.TextContent / ListToolsResult / ListResourcesResult /
ListResourceTemplatesResult / ListPromptsResult constructors are
replaced with their builder().build() forms (the constructors are
no longer public in M3)
- Javadoc header bumped from "fork of McpAsyncServer (2.0.0-M2)" to
"(2.0.0-M3)"
Verified with bootRun: ServerApplication now starts cleanly in ~19s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
M8 is a small stabilization release (4 bug fixes, 4 minor features); no API breakage, no module coordinate changes. Vendored spring-ai-tool-search-tool fork's super(...) patch remains valid since ToolCallAdvisor signature is unchanged in M8. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pplicationIntTest worker-app has no JDBC dependency — it's stateless and reaches database state through *-remote-client modules. The vestigial @import predates the remote-client refactor. Under Spring Boot 4, @Serviceconnection now throws when no matching ConnectionDetails registrar is on the classpath, so importing a Postgres container in an app without JDBC autoconfig fails the context load. Removing the unused import restores green testIntegration without affecting sibling app tests (connection-app, execution-app, etc.) that legitimately pull in JDBC starters. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…AI M8 Snapshots drifted because the LLM components pull model lists dynamically from Spring AI's provider enums (GoogleGenAiChatModel.ChatModel.values(), MistralAiApi.ChatModel.values(), OpenAiApi.ChatModel.values()), and M8 refreshed those enums: - Gemini: dropped -preview suffix on flash-lite, added gemini-3.5-flash - OpenAI: gained ~3 new chat models in one action - Mistral: trimmed one retired model The bulk of the diff is whitespace from Jackson 3.x's default pretty-printer emitting " : " (with leading space) instead of ": "; net model changes are small. Other LLM components (anthropic, ollama, azure-open-ai, amazon-bedrock, stability) verified unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…AI M8 Snapshots drifted because the LLM components pull model lists dynamically from Spring AI's provider enums (GoogleGenAiChatModel.ChatModel.values(), MistralAiApi.ChatModel.values(), OpenAiApi.ChatModel.values()), and M8 refreshed those enums: - Gemini: dropped -preview suffix on flash-lite, added gemini-3.5-flash - OpenAI: gained ~3 new chat models in one action - Mistral: trimmed one retired model The bulk of the diff is whitespace from Jackson 3.x's default pretty-printer emitting " : " (with leading space) instead of ": "; net model changes are small. Other LLM components (anthropic, ollama, azure-open-ai, amazon-bedrock, stability) verified unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> mistral
…ConversationHistory()
This reverts commit 77f054e8a9bb29827e67673c71f80632d4906069.
…InternalConversationHistory()" This reverts commit 0be576f.
…nalConversationHistory
|



Description
Resolved the failing GitHub Actions job
CI Build on PULL Request / server (pull_request)by fixing a stale test snapshot in the Mistral component module.The failure was caused by
MistralComponentHandlerTestexpecting a top-level"inputs": nullfield that is no longer present in the serialized component definition.Updated
server/libs/modules/components/ai/llm/mistral/src/test/resources/definition/mistral_v1.jsonto match current output.Type of change
How Has This Been Tested?
./gradlew :server:libs:modules:components:ai:llm:mistral:test --no-daemonMistralComponentHandlerTestpasses and build is successfulChecklist: