Skip to content

CAMEL-23955: Fix conversation memory user turns and history reset#24880

Merged
davsclaus merged 2 commits into
apache:mainfrom
atiaomar1978-hub:CAMEL-23955-conversation-memory-fix
Jul 18, 2026
Merged

CAMEL-23955: Fix conversation memory user turns and history reset#24880
davsclaus merged 2 commits into
apache:mainfrom
atiaomar1978-hub:CAMEL-23955-conversation-memory-fix

Conversation

@atiaomar1978-hub

Copy link
Copy Markdown
Contributor

CAMEL-23955 — Summary

Branch: CAMEL-23955-conversation-memory-fix
Commit: 95e5ee478a7
Module: camel-openai


Bugs Fixed

# Problem Root Cause
1 User turns missing from conversation history Only assistant responses were saved
2 systemMessage reset had no effect removeHeader() used instead of removeProperty()

Code Changes

File modified: OpenAIProducer.java (+20 lines)

Area Before After
History reset in.removeHeader(...) exchange.removeProperty(...)
User message tracking Not stored Saved as PENDING_USER_MESSAGE in buildMessages()
History update Assistant only New helper appendPendingUserMessageToHistory() runs in all 3 update paths

Files added (from Jira reproducers):

  • OpenAIConversationMemoryUserMessageTest.java
  • OpenAIConversationMemoryResetTest.java

Tests Passed

Test Class What It Verifies Result
OpenAIConversationMemoryUserMessageTest Second turn includes previous user message ("My name is Alice") PASSED
OpenAIConversationMemoryResetTest systemMessage + conversationMemory=true clears stale history PASSED
OpenAIProducerMcpMockTest#conversationMemoryIncludesToolCallChain Agentic MCP path still builds full tool-call history PASSED

Build: BUILD SUCCESS — 3 tests, 0 failures


Flow After Fix

Turn 1:  user → API → history = [user, assistant]
Turn 2:  history + new user → API → history = [user, assistant, user, assistant]
Reset: systemMessage set → exchange property cleared → fresh history

Persist the outgoing user message in conversation history and clear history via exchange property when systemMessage is configured.

Co-authored-by: Cursor <cursoragent@cursor.com>

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — CAMEL-23955: Fix conversation memory user turns and history reset

Well-researched and focused fix for two real bugs. Both root causes are correctly identified and the approach is sound.

What works well

  • Precise diagnosis: removeHeader()removeProperty() is the exact fix for the history-reset bug, and the pending-user-message pattern correctly preserves user turns.
  • Test strategy: both tests capture the actual HTTP request and assert on the serialized payload — testing real user-visible behavior rather than internal state. The two-turn conversation test ("My name is Alice""What is my name?") is an effective reproducer.
  • Consistency: appendPendingUserMessageToHistory() is called in all three updateConversationHistory overloads, so user messages are preserved across simple, agentic-with-tools, and agentic-without-tools paths.

Suggestions

  1. Upgrade guide entry (docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc): This changes observable behavior — conversation history now contains user messages where it previously only contained assistant responses. Code reading CamelOpenAIConversationHistory directly may need adjustment. Per project convention, a short entry documenting both fixes would be helpful.

  2. Minor edge case — property cleanup on API failure: If the OpenAI API call throws (between buildMessages() setting PENDING_USER_MESSAGE and updateConversationHistory() consuming it), the property remains on the exchange. This is low risk in practice (exceptions propagate, retry logic typically creates new exchanges), but a defensive exchange.removeProperty(PENDING_USER_MESSAGE) at the start of buildMessages() would prevent stale state on exchange reuse.

  3. Nit — test assertion style: The project prefers AssertJ assertions. The current JUnit assertions (assertTrue, assertFalse, assertNull) are fine but AssertJ would give more readable failure messages.

Checklist

Item Status
Tests ✅ Two focused tests covering both bugs
Docs / upgrade guide ⚠️ Suggest adding entry
Commit convention CAMEL-23955: ...
Public API / backward compat ✅ Bugfix aligning with documented contract
Security ✅ No concerns — per-exchange, not cross-exchange
CI ⏳ Not yet run — needs verification
Thread safety ✅ Exchange processing is synchronous

LGTM with the minor suggestions above. Nice work identifying and fixing these two interconnected bugs. 👍


Reviewed with Claude Code on behalf of gnodet. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

Add 4.22 upgrade guide entry, clear pending user message at buildMessages start, and switch tests to AssertJ.

Co-authored-by: Cursor <cursoragent@cursor.com>
@atiaomar1978-hub

Copy link
Copy Markdown
Contributor Author

Review feedback is applied, tests pass, and the branch is pushed.

Changes Made

Suggestion Action
Upgrade guide Added === camel-openai section to camel-4x-upgrade-guide-4_22.adoc documenting both behavior fixes
Property cleanup Added exchange.removeProperty(PENDING_USER_MESSAGE) at the start of buildMessages()
AssertJ tests Replaced JUnit assertions with AssertJ (anyMatch, noneMatch, as(...)) in both test classes

Tests Passed

Test Result
OpenAIConversationMemoryUserMessageTest PASSED
OpenAIConversationMemoryResetTest PASSED
OpenAIProducerMcpMockTest#conversationMemoryIncludesToolCallChain PASSED

Build: BUILD SUCCESS — 3 tests, 0 failures

Pushed

  • Branch: CAMEL-23955-conversation-memory-fix
  • Commit: 260c73a3871CAMEL-23955: Address review feedback for conversation memory fix
  • Remote: https://github.com/atiaomar1978-hub/camel

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three suggestions from the previous review have been addressed — upgrade guide entry added, defensive property cleanup at the start of buildMessages(), and tests migrated to AssertJ. Clean follow-up. 👍


Reviewed with Claude Code on behalf of gnodet. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fixes are correct, well-tested, and documented in the upgrade guide.

Bug 1 — History reset was a no-op: in.removeHeader() was used to clear conversation history that's stored as an exchange property (exchange.getProperty()). This mismatch has been present since the original component commit (ac0b0e87f), so the documented reset behavior (systemMessage + conversationMemory=true clears history) never actually worked. The fix to exchange.removeProperty() is straightforward and correct.

Bug 2 — User messages missing from history: Only assistant responses were appended to the conversation history, so on subsequent turns the model saw answers without the questions that produced them. The PENDING_USER_MESSAGE exchange property approach is clean — set during buildMessages(), consumed and removed in appendPendingUserMessageToHistory(), and cleared at the start of each buildMessages() call to prevent leakage. All three updateConversationHistory() overloads are updated consistently.

Tests are well-structured reproducers for both scenarios. Upgrade guide entry properly documents the behavioral change.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of davsclaus

@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-ai/camel-openai
  • docs

🔬 Scalpel shadow comparison — Scalpel: 10 tested, 28 compile-only — current: 9 all tested

Maveniverse Scalpel detected 38 affected modules (current approach: 9).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 10 modules (2 direct + 8 downstream), skip tests for 28 (generated code, meta-modules)

Modules Scalpel would test (10)
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-openai
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
  • docs
Modules with tests skipped (28)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • components/camel-ai/camel-openai: 6 test(s) disabled on GitHub Actions
All tested modules (38 modules)
  • Camel :: AI :: OpenAI
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@davsclaus davsclaus added this to the 4.22.0 milestone Jul 18, 2026
@davsclaus davsclaus added the bug Something isn't working label Jul 18, 2026
@davsclaus
davsclaus merged commit 941c2fe into apache:main Jul 18, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants