This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch 22793-2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8cb6bb8b39b2139151fc09e6a7b2ca71114d64ec
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Dec 19 11:41:06 2025 +0100

    CAMEL-22793 - Camel-Langchain4j-Agent: Provide pre-defined guardrails
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../agent/api/guardrails/WordCountGuardrail.java   |  48 ++++++
 .../api/guardrails/CodeInjectionGuardrailTest.java | 178 ++++++++++++++++++++
 .../agent/api/guardrails/GuardrailsTest.java       |  82 ++++++++-
 .../api/guardrails/LanguageGuardrailTest.java      | 156 +++++++++++++++++
 .../api/guardrails/NotEmptyGuardrailTest.java      | 167 +++++++++++++++++++
 .../api/guardrails/RegexPatternGuardrailTest.java  | 180 ++++++++++++++++++++
 .../api/guardrails/WordCountGuardrailTest.java     | 184 +++++++++++++++++++++
 .../src/main/docs/langchain4j-agent-component.adoc | 151 +++++++++++++++++
 8 files changed, 1145 insertions(+), 1 deletion(-)

diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/main/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrail.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/main/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrail.java
index 4a968fda29be..b2bd8ced8bbe 100644
--- 
a/components/camel-ai/camel-langchain4j-agent-api/src/main/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrail.java
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/main/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrail.java
@@ -119,6 +119,15 @@ public class WordCountGuardrail implements OutputGuardrail 
{
         return new WordCountGuardrail(minWords, maxWords);
     }
 
+    /**
+     * Creates a new builder for configuring the guardrail.
+     *
+     * @return a new builder instance
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
     @Override
     public OutputGuardrailResult validate(AiMessage aiMessage) {
         if (aiMessage == null || aiMessage.text() == null) {
@@ -173,4 +182,43 @@ public class WordCountGuardrail implements OutputGuardrail 
{
     public int getMaxWords() {
         return maxWords;
     }
+
+    /**
+     * Builder for creating WordCountGuardrail instances.
+     */
+    public static class Builder {
+        private int minWords = 0;
+        private int maxWords = Integer.MAX_VALUE;
+
+        /**
+         * Sets the minimum word count.
+         *
+         * @param  minWords minimum required word count
+         * @return          this builder
+         */
+        public Builder minWords(int minWords) {
+            this.minWords = minWords;
+            return this;
+        }
+
+        /**
+         * Sets the maximum word count.
+         *
+         * @param  maxWords maximum allowed word count
+         * @return          this builder
+         */
+        public Builder maxWords(int maxWords) {
+            this.maxWords = maxWords;
+            return this;
+        }
+
+        /**
+         * Builds the guardrail instance.
+         *
+         * @return a new WordCountGuardrail instance
+         */
+        public WordCountGuardrail build() {
+            return new WordCountGuardrail(minWords, maxWords);
+        }
+    }
 }
diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/CodeInjectionGuardrailTest.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/CodeInjectionGuardrailTest.java
new file mode 100644
index 000000000000..536b22d65a2f
--- /dev/null
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/CodeInjectionGuardrailTest.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.langchain4j.agent.api.guardrails;
+
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.guardrail.InputGuardrailResult;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CodeInjectionGuardrailTest {
+
+    @Test
+    void testCleanMessage() {
+        CodeInjectionGuardrail guardrail = new CodeInjectionGuardrail();
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello, how are you 
today?")).isSuccess());
+        assertTrue(guardrail.validate(UserMessage.from("What is the weather 
like?")).isSuccess());
+    }
+
+    @Test
+    void testShellCommandInjection() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("Run bash('ls 
-la')")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Execute system('rm 
-rf /')")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Try exec('cat 
/etc/passwd')")).isSuccess());
+    }
+
+    @Test
+    void testBacktickExecution() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("Run `ls 
-la`")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Execute `cat 
/etc/passwd`")).isSuccess());
+    }
+
+    @Test
+    void testCommandSubstitution() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("Run 
$(whoami)")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Execute $(cat 
/etc/passwd)")).isSuccess());
+    }
+
+    @Test
+    void testSqlInjection() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("' OR 
'1'='1")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("UNION SELECT * FROM 
users")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("'; DROP TABLE 
users--")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("INSERT INTO users 
VALUES")).isSuccess());
+    }
+
+    @Test
+    void testJavaScriptInjection() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        
assertFalse(guardrail.validate(UserMessage.from("<script>alert('XSS')</script>")).isSuccess());
+        
assertFalse(guardrail.validate(UserMessage.from("javascript:alert('XSS')")).isSuccess());
+        
assertFalse(guardrail.validate(UserMessage.from("onclick=alert('XSS')")).isSuccess());
+    }
+
+    @Test
+    void testHtmlXssInjection() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("<iframe 
src='evil.com'></iframe>")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("<embed 
src='evil.swf'>")).isSuccess());
+    }
+
+    @Test
+    void testPathTraversal() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("Read file 
../../../etc/passwd")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Access 
..\\..\\windows\\system32")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Get 
%2e%2e/etc/passwd")).isSuccess());
+    }
+
+    @Test
+    void testCommandChaining() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("Run && cat 
/etc/passwd")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("; cat 
/etc/passwd")).isSuccess());
+    }
+
+    @Test
+    void testTemplateInjection() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.strict();
+
+        assertFalse(guardrail.validate(UserMessage.from("Use 
{{constructor.constructor}}")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Try 
${7*7}")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Execute <% code 
%>")).isSuccess());
+    }
+
+    @Test
+    void testNonStrictModeRequiresMultipleMatches() {
+        CodeInjectionGuardrail guardrail = new CodeInjectionGuardrail();
+
+        // Single pattern match should pass in non-strict mode
+        assertTrue(guardrail.validate(UserMessage.from("Use 
{{template}}")).isSuccess());
+
+        // Multiple different types should fail
+        assertFalse(guardrail.validate(UserMessage.from("Run {{template}} and 
../../../etc/passwd")).isSuccess());
+    }
+
+    @Test
+    void testForSpecificTypes() {
+        // Use builder with strict mode to fail on single match
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.builder()
+                
.detectTypes(CodeInjectionGuardrail.InjectionType.SQL_INJECTION)
+                .strict(true)
+                .build();
+
+        // SQL injection should fail
+        assertFalse(guardrail.validate(UserMessage.from("' OR 
'1'='1")).isSuccess());
+
+        // Other types should pass since we only detect SQL
+        
assertTrue(guardrail.validate(UserMessage.from("<script>alert('XSS')</script>")).isSuccess());
+    }
+
+    @Test
+    void testNullMessage() {
+        CodeInjectionGuardrail guardrail = new CodeInjectionGuardrail();
+
+        InputGuardrailResult result = guardrail.validate((UserMessage) null);
+        assertTrue(result.isSuccess());
+    }
+
+    @Test
+    void testIsStrict() {
+        CodeInjectionGuardrail defaultGuard = new CodeInjectionGuardrail();
+        CodeInjectionGuardrail strictGuard = CodeInjectionGuardrail.strict();
+
+        assertFalse(defaultGuard.isStrict());
+        assertTrue(strictGuard.isStrict());
+    }
+
+    @Test
+    void testGetDetectTypes() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.forTypes(
+                CodeInjectionGuardrail.InjectionType.SQL_INJECTION,
+                CodeInjectionGuardrail.InjectionType.SHELL_COMMAND);
+
+        
assertTrue(guardrail.getDetectTypes().contains(CodeInjectionGuardrail.InjectionType.SQL_INJECTION));
+        
assertTrue(guardrail.getDetectTypes().contains(CodeInjectionGuardrail.InjectionType.SHELL_COMMAND));
+        
assertFalse(guardrail.getDetectTypes().contains(CodeInjectionGuardrail.InjectionType.JAVASCRIPT));
+    }
+
+    @Test
+    void testBuilderWithCustomPattern() {
+        CodeInjectionGuardrail guardrail = CodeInjectionGuardrail.builder()
+                
.detectTypes(CodeInjectionGuardrail.InjectionType.SHELL_COMMAND)
+                .strict(true)
+                .build();
+
+        assertTrue(guardrail.isStrict());
+        
assertTrue(guardrail.getDetectTypes().contains(CodeInjectionGuardrail.InjectionType.SHELL_COMMAND));
+    }
+}
diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/GuardrailsTest.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/GuardrailsTest.java
index c2865e730bd9..8f4c33d670f8 100644
--- 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/GuardrailsTest.java
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/GuardrailsTest.java
@@ -63,13 +63,26 @@ class GuardrailsTest {
         List<Class<?>> guardrails = Guardrails.strictInputGuardrails();
 
         assertNotNull(guardrails);
-        assertEquals(4, guardrails.size());
+        assertEquals(5, guardrails.size());
         assertTrue(guardrails.contains(InputLengthGuardrail.class));
         assertTrue(guardrails.contains(PiiDetectorGuardrail.class));
         assertTrue(guardrails.contains(PromptInjectionGuardrail.class));
+        assertTrue(guardrails.contains(CodeInjectionGuardrail.class));
         assertTrue(guardrails.contains(KeywordFilterGuardrail.class));
     }
 
+    @Test
+    void testComprehensiveOutputGuardrails() {
+        List<Class<?>> guardrails = Guardrails.comprehensiveOutputGuardrails();
+
+        assertNotNull(guardrails);
+        assertEquals(4, guardrails.size());
+        assertTrue(guardrails.contains(NotEmptyGuardrail.class));
+        assertTrue(guardrails.contains(OutputLengthGuardrail.class));
+        assertTrue(guardrails.contains(SensitiveDataOutputGuardrail.class));
+        assertTrue(guardrails.contains(KeywordOutputFilterGuardrail.class));
+    }
+
     @Test
     void testInputGuardrailFactories() {
         assertNotNull(Guardrails.inputLength());
@@ -165,4 +178,71 @@ class GuardrailsTest {
         assertEquals(3, config.getInputGuardrailClasses().size());
         assertEquals(1, config.getOutputGuardrailClasses().size());
     }
+
+    @Test
+    void testCodeInjectionFactories() {
+        assertNotNull(Guardrails.codeInjection());
+        assertFalse(Guardrails.codeInjection().isStrict());
+        assertTrue(Guardrails.codeInjectionStrict().isStrict());
+    }
+
+    @Test
+    void testLanguageFilterFactory() {
+        LanguageGuardrail guardrail = 
Guardrails.languageFilter(LanguageGuardrail.Language.ENGLISH);
+        assertNotNull(guardrail);
+        
assertTrue(guardrail.getAllowedLanguages().contains(LanguageGuardrail.Language.ENGLISH));
+    }
+
+    @Test
+    void testRegexPatternBuilderFactory() {
+        RegexPatternGuardrail.Builder builder = 
Guardrails.regexPatternBuilder();
+        assertNotNull(builder);
+
+        RegexPatternGuardrail guardrail = builder
+                .denyPattern("test", "Error")
+                .build();
+        assertNotNull(guardrail);
+    }
+
+    @Test
+    void testWordCountFactories() {
+        WordCountGuardrail atLeast = Guardrails.wordCountAtLeast(10);
+        assertEquals(10, atLeast.getMinWords());
+
+        WordCountGuardrail atMost = Guardrails.wordCountAtMost(100);
+        assertEquals(100, atMost.getMaxWords());
+
+        WordCountGuardrail between = Guardrails.wordCountBetween(5, 50);
+        assertEquals(5, between.getMinWords());
+        assertEquals(50, between.getMaxWords());
+    }
+
+    @Test
+    void testNotEmptyFactories() {
+        NotEmptyGuardrail notEmpty = Guardrails.notEmpty();
+        assertNotNull(notEmpty);
+        assertFalse(notEmpty.isDetectRefusals());
+
+        NotEmptyGuardrail withRefusal = 
Guardrails.notEmptyWithRefusalDetection();
+        assertNotNull(withRefusal);
+        assertTrue(withRefusal.isDetectRefusals());
+    }
+
+    @Test
+    void testConfigurationBuilderWithNewGuardrails() {
+        AgentConfiguration config = Guardrails.configure()
+                .withCodeInjectionDetection()
+                .withLanguageValidation()
+                .withNotEmptyValidation()
+                .withWordCountValidation()
+                .build();
+
+        assertNotNull(config);
+        assertEquals(2, config.getInputGuardrailClasses().size());
+        assertEquals(2, config.getOutputGuardrailClasses().size());
+        
assertTrue(config.getInputGuardrailClasses().contains(CodeInjectionGuardrail.class));
+        
assertTrue(config.getInputGuardrailClasses().contains(LanguageGuardrail.class));
+        
assertTrue(config.getOutputGuardrailClasses().contains(NotEmptyGuardrail.class));
+        
assertTrue(config.getOutputGuardrailClasses().contains(WordCountGuardrail.class));
+    }
 }
diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/LanguageGuardrailTest.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/LanguageGuardrailTest.java
new file mode 100644
index 000000000000..3c2f65737e9e
--- /dev/null
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/LanguageGuardrailTest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.langchain4j.agent.api.guardrails;
+
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.guardrail.InputGuardrailResult;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class LanguageGuardrailTest {
+
+    @Test
+    void testAllowAllLanguagesByDefault() {
+        LanguageGuardrail guardrail = new LanguageGuardrail();
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertTrue(guardrail.validate(UserMessage.from("Привет 
мир")).isSuccess());
+        assertTrue(guardrail.validate(UserMessage.from("你好世界")).isSuccess());
+    }
+
+    @Test
+    void testAllowOnlyEnglish() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.allowOnly(LanguageGuardrail.Language.ENGLISH);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Привет 
мир")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("你好世界")).isSuccess());
+    }
+
+    @Test
+    void testAllowLatinScript() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.allowOnly(LanguageGuardrail.Language.LATIN_SCRIPT);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertTrue(guardrail.validate(UserMessage.from("Hola 
mundo")).isSuccess());
+        assertTrue(guardrail.validate(UserMessage.from("Bonjour le 
monde")).isSuccess());
+    }
+
+    @Test
+    void testBlockCyrillic() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.CYRILLIC);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Привет 
мир")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Hello 
Привет")).isSuccess());
+    }
+
+    @Test
+    void testBlockChinese() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.CHINESE);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("你好世界")).isSuccess());
+    }
+
+    @Test
+    void testBlockArabic() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.ARABIC);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("مرحبا 
بالعالم")).isSuccess());
+    }
+
+    @Test
+    void testMultipleAllowedLanguages() {
+        LanguageGuardrail guardrail = LanguageGuardrail.builder()
+                .allowedLanguages(LanguageGuardrail.Language.ENGLISH, 
LanguageGuardrail.Language.LATIN_SCRIPT)
+                .build();
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        
assertTrue(guardrail.validate(UserMessage.from("Bonjour")).isSuccess());
+    }
+
+    @Test
+    void testMixedContentAllowed() {
+        LanguageGuardrail guardrail = LanguageGuardrail.builder()
+                .allowedLanguages(LanguageGuardrail.Language.ENGLISH, 
LanguageGuardrail.Language.LATIN_SCRIPT)
+                .allowMixed(true)
+                .build();
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
Bonjour")).isSuccess());
+    }
+
+    @Test
+    void testNullMessage() {
+        LanguageGuardrail guardrail = new LanguageGuardrail();
+
+        InputGuardrailResult result = guardrail.validate((UserMessage) null);
+        assertTrue(result.isSuccess());
+    }
+
+    @Test
+    void testJapaneseDetection() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.JAPANESE);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("こんにちは")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("カタカナ")).isSuccess());
+    }
+
+    @Test
+    void testKoreanDetection() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.KOREAN);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("안녕하세요")).isSuccess());
+    }
+
+    @Test
+    void testHebrewDetection() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.HEBREW);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("שלום 
עולם")).isSuccess());
+    }
+
+    @Test
+    void testGreekDetection() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.GREEK);
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Γειά σου 
κόσμε")).isSuccess());
+    }
+
+    @Test
+    void testGetAllowedLanguages() {
+        LanguageGuardrail guardrail = LanguageGuardrail.allowOnly(
+                LanguageGuardrail.Language.ENGLISH, 
LanguageGuardrail.Language.LATIN_SCRIPT);
+
+        
assertTrue(guardrail.getAllowedLanguages().contains(LanguageGuardrail.Language.ENGLISH));
+        
assertTrue(guardrail.getAllowedLanguages().contains(LanguageGuardrail.Language.LATIN_SCRIPT));
+    }
+
+    @Test
+    void testGetBlockedLanguages() {
+        LanguageGuardrail guardrail = 
LanguageGuardrail.block(LanguageGuardrail.Language.CYRILLIC);
+
+        
assertTrue(guardrail.getBlockedLanguages().contains(LanguageGuardrail.Language.CYRILLIC));
+    }
+}
diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/NotEmptyGuardrailTest.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/NotEmptyGuardrailTest.java
new file mode 100644
index 000000000000..3354fe72120d
--- /dev/null
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/NotEmptyGuardrailTest.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.langchain4j.agent.api.guardrails;
+
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.guardrail.OutputGuardrailResult;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NotEmptyGuardrailTest {
+
+    @Test
+    void testValidResponse() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail();
+
+        assertTrue(guardrail.validate(AiMessage.from("Hello, how can I help 
you?")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("Here is your 
answer.")).isSuccess());
+    }
+
+    @Test
+    void testEmptyResponse() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail();
+
+        assertFalse(guardrail.validate(AiMessage.from("")).isSuccess());
+    }
+
+    @Test
+    void testWhitespaceOnlyResponse() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail();
+
+        assertFalse(guardrail.validate(AiMessage.from("   ")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("\t\n")).isSuccess());
+    }
+
+    @Test
+    void testNullMessage() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail();
+
+        OutputGuardrailResult result = guardrail.validate((AiMessage) null);
+        assertFalse(result.isSuccess());
+    }
+
+    @Test
+    void testRefusalDetectionEnabled() {
+        NotEmptyGuardrail guardrail = NotEmptyGuardrail.withRefusalDetection();
+
+        // Normal responses should pass
+        assertTrue(guardrail.validate(AiMessage.from("Here is your 
answer.")).isSuccess());
+
+        // Refusal patterns should fail
+        assertFalse(guardrail.validate(AiMessage.from("I cannot help with 
that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I can't provide that 
information.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I'm unable to assist 
with that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I am unable to do 
that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I don't have access to 
that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I'm not able to 
help.")).isSuccess());
+    }
+
+    @Test
+    void testRefusalDetectionDisabledByDefault() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail();
+
+        // Refusal patterns should pass when detection is disabled
+        assertTrue(guardrail.validate(AiMessage.from("I cannot help with 
that.")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("I can't provide that 
information.")).isSuccess());
+    }
+
+    @Test
+    void testMinMeaningfulLength() {
+        NotEmptyGuardrail guardrail = NotEmptyGuardrail.withMinLength(10);
+
+        // Too short
+        assertFalse(guardrail.validate(AiMessage.from("Hi")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("Yes")).isSuccess());
+
+        // Just at minimum
+        
assertTrue(guardrail.validate(AiMessage.from("0123456789")).isSuccess());
+
+        // Above minimum
+        assertTrue(guardrail.validate(AiMessage.from("This is a proper 
response.")).isSuccess());
+    }
+
+    @Test
+    void testCustomConfiguration() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail(true, 20);
+
+        // Too short
+        assertFalse(guardrail.validate(AiMessage.from("Short")).isSuccess());
+
+        // Refusal
+        assertFalse(guardrail.validate(AiMessage.from("I cannot help with that 
request at all.")).isSuccess());
+
+        // Valid response
+        assertTrue(guardrail.validate(AiMessage.from("This is a proper 
response that is long enough.")).isSuccess());
+    }
+
+    @Test
+    void testMinLengthEnforcesAtLeastOne() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail(false, 0);
+
+        // Min length should be enforced to at least 1
+        assertEquals(1, guardrail.getMinMeaningfulLength());
+    }
+
+    @Test
+    void testNegativeMinLengthTreatedAsOne() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail(false, -5);
+
+        assertEquals(1, guardrail.getMinMeaningfulLength());
+    }
+
+    @Test
+    void testGetters() {
+        NotEmptyGuardrail guardrail = new NotEmptyGuardrail(true, 50);
+
+        assertTrue(guardrail.isDetectRefusals());
+        assertEquals(50, guardrail.getMinMeaningfulLength());
+    }
+
+    @Test
+    void testRefusalPatternsCaseInsensitive() {
+        NotEmptyGuardrail guardrail = NotEmptyGuardrail.withRefusalDetection();
+
+        // Test case insensitivity
+        assertFalse(guardrail.validate(AiMessage.from("I CANNOT help with 
that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("i cannot help with 
that.")).isSuccess());
+    }
+
+    @Test
+    void testRefusalMustBeAtStart() {
+        NotEmptyGuardrail guardrail = NotEmptyGuardrail.withRefusalDetection();
+
+        // Refusal at start should fail
+        assertFalse(guardrail.validate(AiMessage.from("I cannot do that for 
you.")).isSuccess());
+
+        // Refusal not at start should pass
+        assertTrue(
+                guardrail.validate(AiMessage.from("While I cannot do 
everything, here is what I can help with.")).isSuccess());
+    }
+
+    @Test
+    void testApologyRefusals() {
+        NotEmptyGuardrail guardrail = NotEmptyGuardrail.withRefusalDetection();
+
+        assertFalse(guardrail.validate(AiMessage.from("I apologize, but I 
cannot help with that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("Sorry, but I cannot 
assist.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I'm sorry, I cannot do 
that.")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("I'm afraid I cannot 
help.")).isSuccess());
+    }
+}
diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/RegexPatternGuardrailTest.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/RegexPatternGuardrailTest.java
new file mode 100644
index 000000000000..ac7169842df8
--- /dev/null
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/RegexPatternGuardrailTest.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.langchain4j.agent.api.guardrails;
+
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.guardrail.InputGuardrailResult;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class RegexPatternGuardrailTest {
+
+    @Test
+    void testEmptyGuardrailAllowsAll() {
+        RegexPatternGuardrail guardrail = new RegexPatternGuardrail();
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        
assertTrue(guardrail.validate(UserMessage.from("https://example.com";)).isSuccess());
+    }
+
+    @Test
+    void testBlockingPattern() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.blocking(
+                "https?://[^\\s]+", "URLs are not allowed");
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Visit 
https://example.com";)).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Go to 
http://test.org";)).isSuccess());
+    }
+
+    @Test
+    void testRequiringPattern() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.requiring(
+                "TICKET-\\d+", "Please include a ticket number");
+
+        assertTrue(guardrail.validate(UserMessage.from("Fix 
TICKET-123")).isSuccess());
+        assertTrue(guardrail.validate(UserMessage.from("Working on TICKET-456 
now")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+    }
+
+    @Test
+    void testMultipleDenyPatterns() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .denyPattern("https?://[^\\s]+", "URLs are not allowed")
+                .denyPattern("\\b(password|secret)\\b", "Sensitive keywords 
not allowed")
+                .build();
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Visit 
https://example.com";)).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("My password is 
123")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("The secret is 
here")).isSuccess());
+    }
+
+    @Test
+    void testMultipleRequirePatterns() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .requirePattern("TICKET-\\d+", "Please include a ticket 
number")
+                .requirePattern("@\\w+", "Please mention a user")
+                .build();
+
+        assertTrue(guardrail.validate(UserMessage.from("TICKET-123 
@john")).isSuccess());
+        
assertFalse(guardrail.validate(UserMessage.from("TICKET-123")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("@john")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+    }
+
+    @Test
+    void testCombinedDenyAndRequire() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .denyPattern("https?://[^\\s]+", "URLs are not allowed")
+                .requirePattern("TICKET-\\d+", "Please include a ticket 
number")
+                .build();
+
+        assertTrue(guardrail.validate(UserMessage.from("Fix 
TICKET-123")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("TICKET-123 at 
https://example.com";)).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+    }
+
+    @Test
+    void testFailOnFirstMatch() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .denyPattern("pattern1", "Error 1")
+                .denyPattern("pattern2", "Error 2")
+                .failOnFirstMatch(true)
+                .build();
+
+        InputGuardrailResult result = 
guardrail.validate(UserMessage.from("Contains pattern1 and pattern2"));
+        assertFalse(result.isSuccess());
+        // Should only contain first error due to failOnFirstMatch
+        assertTrue(result.toString().contains("Error 1"));
+    }
+
+    @Test
+    void testCollectAllErrors() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .denyPattern("pattern1", "Error 1")
+                .denyPattern("pattern2", "Error 2")
+                .failOnFirstMatch(false)
+                .build();
+
+        InputGuardrailResult result = 
guardrail.validate(UserMessage.from("Contains pattern1 and pattern2"));
+        assertFalse(result.isSuccess());
+        // Should contain both errors
+        assertTrue(result.toString().contains("Error 1"));
+        assertTrue(result.toString().contains("Error 2"));
+    }
+
+    @Test
+    void testNullMessage() {
+        RegexPatternGuardrail guardrail = 
RegexPatternGuardrail.blocking("test", "Error");
+
+        InputGuardrailResult result = guardrail.validate((UserMessage) null);
+        assertTrue(result.isSuccess());
+    }
+
+    @Test
+    void testGetDenyPatterns() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .denyPattern("pattern1", "Error 1")
+                .denyPattern("pattern2", "Error 2")
+                .build();
+
+        assertEquals(2, guardrail.getDenyPatterns().size());
+    }
+
+    @Test
+    void testGetRequirePatterns() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.builder()
+                .requirePattern("pattern1", "Error 1")
+                .requirePattern("pattern2", "Error 2")
+                .build();
+
+        assertEquals(2, guardrail.getRequirePatterns().size());
+    }
+
+    @Test
+    void testCaseInsensitivePattern() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.blocking(
+                "(?i)blocked", "Blocked word found");
+
+        assertFalse(guardrail.validate(UserMessage.from("This is 
BLOCKED")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("This is 
blocked")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("This is 
Blocked")).isSuccess());
+    }
+
+    @Test
+    void testEmailPattern() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.blocking(
+                "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}", "Email 
addresses not allowed");
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Contact me at 
[email protected]")).isSuccess());
+    }
+
+    @Test
+    void testPhoneNumberPattern() {
+        RegexPatternGuardrail guardrail = RegexPatternGuardrail.blocking(
+                "\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b", "Phone numbers not 
allowed");
+
+        assertTrue(guardrail.validate(UserMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Call me at 
555-123-4567")).isSuccess());
+        assertFalse(guardrail.validate(UserMessage.from("Call me at 
5551234567")).isSuccess());
+    }
+}
diff --git 
a/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrailTest.java
 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrailTest.java
new file mode 100644
index 000000000000..ceab1a54eb0a
--- /dev/null
+++ 
b/components/camel-ai/camel-langchain4j-agent-api/src/test/java/org/apache/camel/component/langchain4j/agent/api/guardrails/WordCountGuardrailTest.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.langchain4j.agent.api.guardrails;
+
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.guardrail.OutputGuardrailResult;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class WordCountGuardrailTest {
+
+    @Test
+    void testDefaultAllowsAll() {
+        WordCountGuardrail guardrail = new WordCountGuardrail();
+
+        assertTrue(guardrail.validate(AiMessage.from("Hello")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("Hello world how are you 
today")).isSuccess());
+    }
+
+    @Test
+    void testAtLeast() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(5);
+
+        // Fewer than 5 words
+        assertFalse(guardrail.validate(AiMessage.from("Hello")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("Hello 
world")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("One two three 
four")).isSuccess());
+
+        // Exactly 5 words
+        assertTrue(guardrail.validate(AiMessage.from("One two three four 
five")).isSuccess());
+
+        // More than 5 words
+        assertTrue(guardrail.validate(AiMessage.from("One two three four five 
six seven")).isSuccess());
+    }
+
+    @Test
+    void testAtMost() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atMost(5);
+
+        // Fewer than 5 words
+        assertTrue(guardrail.validate(AiMessage.from("Hello")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("Hello 
world")).isSuccess());
+
+        // Exactly 5 words
+        assertTrue(guardrail.validate(AiMessage.from("One two three four 
five")).isSuccess());
+
+        // More than 5 words
+        assertFalse(guardrail.validate(AiMessage.from("One two three four five 
six")).isSuccess());
+    }
+
+    @Test
+    void testBetween() {
+        WordCountGuardrail guardrail = WordCountGuardrail.between(3, 7);
+
+        // Fewer than 3 words
+        assertFalse(guardrail.validate(AiMessage.from("Hello")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("Hello 
world")).isSuccess());
+
+        // Between 3 and 7 words
+        assertTrue(guardrail.validate(AiMessage.from("One two 
three")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("One two three four 
five")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("One two three four five 
six seven")).isSuccess());
+
+        // More than 7 words
+        assertFalse(guardrail.validate(AiMessage.from("One two three four five 
six seven eight")).isSuccess());
+    }
+
+    @Test
+    void testBuilder() {
+        WordCountGuardrail guardrail = WordCountGuardrail.builder()
+                .minWords(10)
+                .maxWords(50)
+                .build();
+
+        assertEquals(10, guardrail.getMinWords());
+        assertEquals(50, guardrail.getMaxWords());
+    }
+
+    @Test
+    void testNullMessage() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(1);
+
+        OutputGuardrailResult result = guardrail.validate((AiMessage) null);
+        assertFalse(result.isSuccess());
+    }
+
+    @Test
+    void testEmptyMessage() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(1);
+
+        assertFalse(guardrail.validate(AiMessage.from("")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("   ")).isSuccess());
+    }
+
+    @Test
+    void testGetters() {
+        WordCountGuardrail guardrail = WordCountGuardrail.between(5, 100);
+
+        assertEquals(5, guardrail.getMinWords());
+        assertEquals(100, guardrail.getMaxWords());
+    }
+
+    @Test
+    void testWordCountWithPunctuation() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(5);
+
+        // Words with punctuation should still be counted as words
+        assertTrue(guardrail.validate(AiMessage.from("Hello, world! How are 
you?")).isSuccess());
+    }
+
+    @Test
+    void testWordCountWithMultipleSpaces() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(3);
+
+        // Multiple spaces should not create extra words
+        assertTrue(guardrail.validate(AiMessage.from("One   two   
three")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("One   
two")).isSuccess());
+    }
+
+    @Test
+    void testWordCountWithNewlines() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(4);
+
+        // Newlines should separate words
+        
assertTrue(guardrail.validate(AiMessage.from("One\ntwo\nthree\nfour")).isSuccess());
+    }
+
+    @Test
+    void testWordCountWithTabs() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(3);
+
+        // Tabs should separate words
+        
assertTrue(guardrail.validate(AiMessage.from("One\ttwo\tthree")).isSuccess());
+    }
+
+    @Test
+    void testLongResponse() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atMost(10);
+
+        String longResponse
+                = "This is a very long response that contains many more words 
than the maximum allowed limit of ten words";
+        
assertFalse(guardrail.validate(AiMessage.from(longResponse)).isSuccess());
+    }
+
+    @Test
+    void testExactWordCount() {
+        WordCountGuardrail guardrail = WordCountGuardrail.between(5, 5);
+
+        assertFalse(guardrail.validate(AiMessage.from("One two three 
four")).isSuccess());
+        assertTrue(guardrail.validate(AiMessage.from("One two three four 
five")).isSuccess());
+        assertFalse(guardrail.validate(AiMessage.from("One two three four five 
six")).isSuccess());
+    }
+
+    @Test
+    void testDefaultMaxIsDefault() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atLeast(1);
+
+        assertEquals(WordCountGuardrail.DEFAULT_MAX_WORDS, 
guardrail.getMaxWords());
+    }
+
+    @Test
+    void testDefaultMinIsDefault() {
+        WordCountGuardrail guardrail = WordCountGuardrail.atMost(100);
+
+        assertEquals(WordCountGuardrail.DEFAULT_MIN_WORDS, 
guardrail.getMinWords());
+    }
+}
diff --git 
a/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc
 
b/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc
index f67f50abab67..05eaec16a3cb 100644
--- 
a/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc
+++ 
b/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc
@@ -603,6 +603,15 @@ The `camel-langchain4j-agent-api` module provides 
production-ready guardrails in
 
 |`KeywordFilterGuardrail`
 |Blocks messages containing specific keywords or patterns.
+
+|`LanguageGuardrail`
+|Validates the language/script of user messages. Can allow or block specific 
languages (English, Cyrillic, Chinese, Japanese, Korean, Arabic, Hebrew, Greek, 
Thai, Devanagari).
+
+|`CodeInjectionGuardrail`
+|Detects potential code injection attempts including shell commands, SQL 
injection, JavaScript, HTML/XSS, path traversal, command chaining, and template 
injection.
+
+|`RegexPatternGuardrail`
+|Flexible guardrail using custom regex patterns. Can define deny patterns 
(block if matched) and require patterns (must be present).
 |===
 
 ===== Available Output Guardrails
@@ -622,6 +631,12 @@ The `camel-langchain4j-agent-api` module provides 
production-ready guardrails in
 
 |`KeywordOutputFilterGuardrail`
 |Blocks or redacts specific content in AI responses.
+
+|`NotEmptyGuardrail`
+|Ensures AI responses are not empty or contain only whitespace. Can optionally 
detect refusal patterns (e.g., "I cannot", "I'm unable to").
+
+|`WordCountGuardrail`
+|Validates the word count of AI responses. Can enforce minimum, maximum, or 
range constraints.
 |===
 
 ==== Quick Start with Default Guardrails
@@ -814,6 +829,122 @@ KeywordOutputFilterGuardrail outputFilter = 
KeywordOutputFilterGuardrail.builder
     .build();
 ----
 
+===== Language Validation Configuration
+
+[source,java]
+----
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.LanguageGuardrail;
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.LanguageGuardrail.Language;
+
+// Allow only English input
+LanguageGuardrail englishOnly = LanguageGuardrail.allowOnly(Language.ENGLISH);
+
+// Allow English and Latin script languages (Spanish, French, German, etc.)
+LanguageGuardrail latinLanguages = LanguageGuardrail.allowOnly(
+    Language.ENGLISH, Language.LATIN_SCRIPT);
+
+// Block specific languages
+LanguageGuardrail blockCyrillic = LanguageGuardrail.block(Language.CYRILLIC);
+
+// Custom configuration with mixed content control
+LanguageGuardrail customLanguage = LanguageGuardrail.builder()
+    .allowedLanguages(Language.ENGLISH, Language.LATIN_SCRIPT)
+    .blockedLanguages(Language.CYRILLIC)
+    .allowMixed(false)  // Don't allow mixed language content
+    .build();
+----
+
+===== Code Injection Detection Configuration
+
+[source,java]
+----
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.CodeInjectionGuardrail;
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.CodeInjectionGuardrail.InjectionType;
+
+// Default: detect all code injection types
+CodeInjectionGuardrail defaultGuard = new CodeInjectionGuardrail();
+
+// Strict mode: fail on any single pattern match
+CodeInjectionGuardrail strictGuard = CodeInjectionGuardrail.strict();
+
+// Detect only specific injection types
+CodeInjectionGuardrail sqlAndShellOnly = CodeInjectionGuardrail.forTypes(
+    InjectionType.SQL_INJECTION, InjectionType.SHELL_COMMAND);
+
+// Custom configuration
+CodeInjectionGuardrail customGuard = CodeInjectionGuardrail.builder()
+    .detectTypes(InjectionType.SQL_INJECTION, InjectionType.JAVASCRIPT, 
InjectionType.PATH_TRAVERSAL)
+    .strict(true)
+    .build();
+----
+
+===== Regex Pattern Guardrail Configuration
+
+[source,java]
+----
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.RegexPatternGuardrail;
+
+// Block messages containing URLs
+RegexPatternGuardrail noUrls = RegexPatternGuardrail.blocking(
+    "https?://[^\\s]+", "URLs are not allowed in messages");
+
+// Require messages to contain a ticket number
+RegexPatternGuardrail requireTicket = RegexPatternGuardrail.requiring(
+    "TICKET-\\d+", "Please include a ticket number (e.g., TICKET-123)");
+
+// Complex configuration with multiple patterns
+RegexPatternGuardrail customPatterns = RegexPatternGuardrail.builder()
+    .denyPattern("https?://[^\\s]+", "URLs are not allowed")
+    .denyPattern("\\b(password|secret)\\b", "Sensitive keywords are not 
allowed")
+    .requirePattern("[A-Z]{2,4}-\\d+", "Please include a valid issue ID")
+    .failOnFirstMatch(true)  // Stop checking after first failure
+    .build();
+----
+
+===== Not Empty Guardrail Configuration
+
+[source,java]
+----
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.NotEmptyGuardrail;
+
+// Default: just ensure response is not empty
+NotEmptyGuardrail notEmpty = new NotEmptyGuardrail();
+
+// Also detect refusal patterns like "I cannot", "I'm unable to"
+NotEmptyGuardrail withRefusalDetection = 
NotEmptyGuardrail.withRefusalDetection();
+
+// Require minimum meaningful length
+NotEmptyGuardrail minLength = NotEmptyGuardrail.withMinLength(50);
+
+// Custom configuration
+NotEmptyGuardrail customNotEmpty = new NotEmptyGuardrail(
+    true,   // detectRefusals
+    100     // minMeaningfulLength
+);
+----
+
+===== Word Count Guardrail Configuration
+
+[source,java]
+----
+import 
org.apache.camel.component.langchain4j.agent.api.guardrails.WordCountGuardrail;
+
+// Require at least 10 words
+WordCountGuardrail atLeast10 = WordCountGuardrail.atLeast(10);
+
+// Limit to maximum 500 words
+WordCountGuardrail atMost500 = WordCountGuardrail.atMost(500);
+
+// Require between 50 and 200 words
+WordCountGuardrail between = WordCountGuardrail.between(50, 200);
+
+// Custom configuration
+WordCountGuardrail custom = WordCountGuardrail.builder()
+    .minWords(20)
+    .maxWords(1000)
+    .build();
+----
+
 ==== Complete Example with Memory and Guardrails
 
 [source,java]
@@ -912,6 +1043,18 @@ public class AgentConfig {
 |Blocked keyword found
 |Blocks the request
 
+|`LanguageGuardrail`
+|Disallowed language/script detected
+|Blocks the request
+
+|`CodeInjectionGuardrail`
+|Code injection pattern detected
+|Blocks the request
+
+|`RegexPatternGuardrail`
+|Deny pattern matched or require pattern missing
+|Blocks the request
+
 |`OutputLengthGuardrail`
 |Response too short/long
 |Retries LLM or truncates
@@ -927,6 +1070,14 @@ public class AgentConfig {
 |`KeywordOutputFilterGuardrail`
 |Blocked content in response
 |Blocks or redacts
+
+|`NotEmptyGuardrail`
+|Empty response or refusal detected
+|Retries LLM call
+
+|`WordCountGuardrail`
+|Word count outside allowed range
+|Retries LLM call
 |===
 
 === Multimodal Content Support

Reply via email to