jamesnetherton opened a new issue, #8836:
URL: https://github.com/apache/camel-quarkus/issues/8836

   ## Description
   
   When Quarkus LangChain4j (QL4J) is on the classpath and a default 
`ChatModel` is configured via `quarkus.langchain4j.*` properties, QL4J's 
`ChatMemoryProvider` silently leaks into Camel's `AgentWithoutMemory`, making 
it stateful despite the user's explicit intent for stateless behavior.
   
   ## Root Cause
   
   QL4J replaces `AiServices.builder()` via SPI (`AiServicesFactory`) in JVM 
mode and via GraalVM `@Substitute` in native mode. When Camel calls 
`AiServices.builder(AiAgentWithoutMemoryService.class)`:
   
   1. QL4J's `AiServicesProcessor.determinedImpliedRegisterAiService()` 
discovers `AiAgentWithoutMemoryService` because it has `@UserMessage` and 
`@SystemMessage` annotations. The `AGENTIC_PACKAGE_PREFIX` exclusion 
(`dev.langchain4j.agentic.*`) does not match Camel's package 
(`org.apache.camel.component.langchain4j.agent.api`).
   
   2. QL4J creates a synthetic `QuarkusAiServiceContext` CDI bean for this 
interface. Since no explicit `chatMemoryProviderSupplier` is set on the implied 
registration, it defaults to `BEAN_CHAT_MEMORY_PROVIDER_SUPPLIER` — meaning 
"inject `ChatMemoryProvider` from CDI."
   
   3. `ChatMemoryProcessor` always creates a default `@ApplicationScoped` 
`ChatMemoryProvider` (`MessageWindowChatMemory`). This gets injected into the 
synthetic context.
   
   4. `QuarkusAiServiceContextFactory.create()` returns this pre-configured 
context (with `ChatMemoryProvider` already set) to Camel's builder.
   
   5. Camel's `AgentWithoutMemory.createAiAgentService()` only calls 
`.chatModel(config.getChatModel())` — it never resets `chatMemoryProvider`. The 
QL4J-injected `ChatMemoryProvider` survives into the built proxy.
   
   ## Impact
   
   Since `AiAgentWithoutMemoryService` has no `@MemoryId` parameter, the memory 
ID falls back to either a request-scope hash (HTTP routes) or the literal 
string `"default"` (non-HTTP routes like timer, file, kafka). This causes:
   
   - **Non-HTTP routes**: All `AgentWithoutMemory` instances across the 
application share a single global chat memory. Messages from unrelated 
conversations contaminate each other.
   - **HTTP routes**: Per-request isolation, but `InMemoryChatMemoryStore` 
entries are never evicted (memory leak).
   - **All routes**: Each call sends up to 9 prior unrelated messages to the 
LLM (default window size = 10), increasing token cost, latency, and producing 
incorrect responses.
   
   No error or warning is logged. The agent silently behaves differently than 
its name and contract imply.
   
   ## Steps to Reproduce
   
   1. Add `quarkus-langchain4j-ollama` (or another QL4J model provider) as a 
dependency
   2. Configure a default model:
      ```properties
      quarkus.langchain4j.ollama.base-url=http://localhost:11434
      quarkus.langchain4j.ollama.chat-model.model-id=llama3.2
      ```
   3. Create an `AgentWithoutMemory` with a Camel-managed `ChatModel`:
      ```java
      new AgentWithoutMemory(new AgentConfiguration().withChatModel(chatModel))
      ```
   4. Send multiple unrelated messages through the agent
   5. Observe that responses reference content from previous, unrelated messages
   
   ## Expected Behavior
   
   `AgentWithoutMemory` should be stateless — each call processed independently 
with no conversation history, regardless of whether QL4J is on the classpath.
   
   ## Why Current Tests Don't Catch This
   
   The `langchain4j-agent-ql4j` integration test uses `@Identifier`-qualified 
`ChatModel` beans and does not configure a default QL4J model via properties. 
Without a default `ChatModel`, the CDI context bean creation fails and 
`QuarkusAiServiceContextFactory` falls back to a clean empty context. The 
`ChatMemoryProvider` doesn't leak — but only by accident, not by design.
   
   ## Additional Context
   
   The `langchain4j-agent-ql4j` test README acknowledges related interference: 
`RetrievalAugmentor` had to be disabled 
(`cq-test.retrieval.augmentor.disabled=true`) because "Testing with 
quarkus-langchain4j does not work when the RetrievalAugmentor bean is present 
with scope <default>."


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to