CAMEL-23954: Add langchain4j-agent moderation support - #26174
CAMEL-23954: Add langchain4j-agent moderation support#26174atiaomar1978-hub wants to merge 5 commits into
Conversation
Bugbot reviewSeverity: medium — Guardrails xref missing module prefix
The Content moderation section linked to Status: Fixed in AI-generated Bugbot review summary on behalf of atiaomar1978-hub |
Grok review — initial findings (REQUEST CHANGES)The rewrite to Camel-owned pre-moderation is the correct architecture. LangChain4j High severity (addressed)
Medium severity (addressed)
Test gaps (addressed)
AI-generated Grok review summary on behalf of atiaomar1978-hub |
Review follow-up — fixes appliedThanks for the reviews. Actionable findings were addressed in commits Architecture
Producer / observability
Tests (all passing)./mvnw -pl components/camel-ai/camel-langchain4j-agent-api,components/camel-ai/camel-langchain4j-agent,components/camel-ai/camel-ai-observability-api -am test \
-Dtest=AgentModerationTest,AgentConfigurationTest,LangChain4jAgentModerationTest,GenAiErrorSupportTestPlease re-review when convenient. AI-generated comment on behalf of atiaomar1978-hub |
davsclaus
left a comment
There was a problem hiding this comment.
Thanks for this — the moderation feature itself is well-built: the pre-check semantics are the right call, the tests are thorough, and both catalog mirror copies were properly regenerated. I built the branch locally and all the new unit tests pass (AgentModerationTest 11/11, LangChain4jAgentModerationTest 4/4, GenAiErrorSupportTest 13/13, AgentConfigurationTest 31/31; the only failures were Ollama ITs failing on missing Docker infra, unrelated to this PR).
Two stray artifacts need to come out before this can go in, plus a behavioural concern about how moderation-provider outages are reported. Details inline; summary below.
Blocking
csimplere-added tocore/camel-core-model/.../model.properties— unrelated to moderation and partially reverts9e8d8e4fe979("Removal of csimple language"). See inline comment.AbstractAgent.configureBuildersignature widened fromAiServices<S>toAiServices<?>— leftover from the abandoned@Moderateapproach in563da0b, and a source-incompatible change to aprotectedextension point. See inline comment.
Significant
- Infrastructure failures of the moderation provider are labelled as content policy violations (
ModerationSupport.java). See inline comment. - No test for the moderation-model-throws path.
AgentModerationTestcovers flagged / clean / not-configured / null-verdict / empty-message, but not aModerationModelthat throws — which is exactly the branch with the behaviour questioned in (3). Per CLAUDE.md "Code Quality", new functionality needs test coverage. - FQCN usage in test code — 7 occurrences across the two new test classes. CLAUDE.md "Import Style" forbids fully-qualified names and states the rule applies to test code; the OpenRewrite pass in CI rewrites them and the uncommitted-changes check then fails. See inline comments.
Minor
- The
AgentWithMemory/AgentWithoutMemoryrefactor strips explanatory comments (// Multi-modal message with content,// Text-only message, thecreateAiAgentServicejavadoc) and reshapesif/elseinto early-return. That churn is unrelated to the feature and makes the diff harder to review — could it be dropped? FlaggingModerationModelis duplicated verbatim in both modules. Acceptable if there is no shared test-jar, but worth a note.
Questions
- Why not LangChain4j's native
AiServices.moderationModel(...)+@Moderate? It does exist in 1.19.0, and563da0bused it before7f5e6bfreplaced it. I believe the reason is that native moderation runs concurrently with the LLM call, so it cannot prevent tool execution or memory writes, whereas this pre-check can — which is genuinely the stronger guarantee. But that rationale is nowhere in the PR description, and every reviewer will ask. Could you state it explicitly in the description so the decision is on record? - Ordering vs input guardrails: moderation now runs strictly before input guardrails (which execute inside the AiServices call). Intentional? If so, a row in the guardrails page's "Guardrail Behavior Summary" table would make the ordering explicit.
Verified as correct
- Both mirrored catalog copies regenerated (component JSON + catalog JSON, both
.adocpairs). others:langchain4j-agent-guardrails.adocmatches the existing prefix atlangchain4j-agent-component.adoc:1257; the#_content_moderationfragment matches the auto-generated id for=== Content Moderation, with no explicit[[anchor]]block.- Commit subjects follow
CAMEL-XXXX: ...; AI co-authorship trailers present. - No upgrade-guide entry — correct, this is a new feature and the guide is migration-only.
@since 4.23on the new public methods; the new dependency is test-scope only.ModerationModel.moderate(String)is not deprecated in 1.19.0.
Scope note: this is a rules-and-conventions review against the project's contribution rules. It does not replace CodeRabbit, Sourcery, or SonarCloud.
Claude Code on behalf of davsclaus
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
✅ Generated files are up to dateAn earlier CI run reported uncommitted generated changes; the latest run no longer does. |
e47d7cd to
9ff0631
Compare
- Add AgentConfiguration.withModerationModel(ModerationModel) - Use moderated AiServices interfaces with @moderate when configured - Wire moderationModel in AbstractAgent.configureBuilder() - Surface ModerationException details on exchange headers - Add AgentModerationTest and LangChain4jAgentModerationTest - Document content moderation in component and guardrails docs Co-authored-by: Cursor Agent <noreply@cursor.com>
Replace duplicated @moderate service interfaces with Camel-owned pre-moderation via ModerationSupport so flagged input is rejected before the chat model, tools, or memory are updated. - Add AgentConfiguration.withModerationModel(ModerationModel) - Set CamelLangChain4jAgentModerationFlagged header on failure - Classify ModerationException as GenAiErrorCategory.VALIDATION - Expand API and component moderation tests - Document pre-moderation semantics in component and guardrails docs Co-authored-by: Cursor <cursoragent@cursor.com>
- Fail closed when moderation returns no verdict or throws - Use ModerationModel.moderate(String) public API with error wrapping - Make ModerationSupport public for custom Agent implementations - Walk cause chain when setting MODERATION_FLAGGED header - Fix guardrails xref module prefix and refresh header metadata - Expand tests for null verdict, memory provider skip, GenAI errors Co-authored-by: Cursor <cursoragent@cursor.com>
- Remove stale csimple re-addition from model.properties - Restore AbstractAgent.configureBuilder(AiServices<S>) signature - Rethrow moderation provider failures instead of wrapping as flagged - Fail closed on missing verdict without marking input as flagged - Fix FQCN usage in moderation tests and add provider failure tests - Document moderation ordering vs guardrails and fix component doc wording Co-authored-by: Cursor <cursoragent@cursor.com>
9ff0631 to
490b10d
Compare
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 74 tested, 25 compile-only — current: 72 all testedMaveniverse Scalpel detected 99 affected modules (current approach: 72).
|
| Module | Duration | Status |
|---|---|---|
| Camel :: AI :: LangChain4j :: Agent | 15.2s | SUCCESS |
| Camel :: Catalog :: Camel Catalog | 14.8s | SUCCESS |
| Camel :: AI :: LangChain4j :: Agent :: API | 11.1s | SUCCESS |
| Camel :: AI :: Observability API | 11.0s | SUCCESS |
| Camel :: Endpoint DSL | n/a |
Top 20 slowest modules:
Camel :: AI :: LangChain4j :: Agent(15.2s)Camel :: Catalog :: Camel Catalog(14.8s)Camel :: AI :: LangChain4j :: Agent :: API(11.1s)Camel :: AI :: Observability API(11.0s)
Description
Implements CAMEL-23954: content moderation support for
camel-langchain4j-agent.When
AgentConfiguration.withModerationModel(ModerationModel)is configured, Camel pre-moderates the user message before invoking the chat model. Flagged input raisesModerationExceptionbefore tools run or conversation memory is updated.Changes
AgentConfiguration.withModerationModel(ModerationModel)— fluent configuration for a LangChain4j moderation modelModerationSupport— public Camel-owned pre-check (fail-closed; usesModerationModel.moderate(String))CamelLangChain4jAgentModerationFlaggedheader — set totrueon moderation failure (cause chain aware)GenAiErrorSupport— classifiesModerationExceptionasVALIDATIONothers:module prefixExample
Testing
./mvnw -pl components/camel-ai/camel-langchain4j-agent-api,components/camel-ai/camel-langchain4j-agent,components/camel-ai/camel-ai-observability-api -am test \ -Dtest=AgentModerationTest,AgentConfigurationTest,LangChain4jAgentModerationTest,GenAiErrorSupportTestAll tests pass.
Target
mainbranch)Tracking
Apache Camel coding standards and style
AI-assisted contributions
Co-authored-by: Cursor <cursoragent@cursor.com>trailersAI-generated PR description on behalf of atiaomar1978-hub