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

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 649d24914383ceeb3156869f0b3ae8b141bed8f3
Author: James Netherton <[email protected]>
AuthorDate: Thu Sep 4 13:07:37 2025 +0100

    Add langchain4j-agent native support
---
 .../ROOT/examples/components/langchain4j-agent.yml |   6 +-
 .../reference/extensions/langchain4j-agent.adoc    |  10 +-
 extensions-jvm/pom.xml                             |   1 -
 .../deployment/SupportLangchain4jProcessor.java    | 161 +++++++++++++++-
 extensions-support/langchain4j/runtime/pom.xml     |   8 +
 .../langchain4j-agent/deployment/pom.xml           |   0
 .../deployment/Langchain4jAgentProcessor.java      |  17 --
 .../langchain4j-agent/pom.xml                      |   2 +-
 .../langchain4j-agent/runtime/pom.xml              |   1 +
 .../main/resources/META-INF/quarkus-extension.yaml |   1 -
 .../chat/deployment/LangChain4jChatProcessor.java  |  33 ----
 .../langchain4j-web-search/deployment/pom.xml      |   5 +-
 .../deployment/Langchain4jWebSearchProcessor.java  |  21 --
 extensions/langchain4j-web-search/runtime/pom.xml  |   4 +
 extensions/pom.xml                                 |   1 +
 .../agent/it/Langchain4jAgentResource.java         |  50 -----
 integration-tests-jvm/pom.xml                      |   1 -
 .../WireMockTestResourceLifecycleManager.java      |   8 +
 integration-tests/langchain4j-agent/README.adoc    |  20 ++
 .../langchain4j-agent/pom.xml                      |  70 +++++++
 .../langchain4j/agent/it/AgentProducers.java       | 211 ++++++++++++++++++++
 .../agent/it/Langchain4jAgentResource.java         | 209 ++++++++++++++++++++
 .../agent/it/Langchain4jAgentRoutes.java           |  57 +++++-
 .../TestPojoJsonExtractorOutputGuardrail.java      |  41 ++++
 .../guardrail/ValidationFailureInputGuardrail.java |  19 +-
 .../ValidationFailureOutputGuardrail.java          |  19 +-
 .../guardrail/ValidationSuccessInputGuardrail.java |  27 +--
 .../ValidationSuccessOutputGuardrail.java          |  27 +--
 .../langchain4j/agent/it/model/TestPojo.java       |  18 +-
 .../agent/it/service/CustomAiService.java          |  22 +--
 .../agent/it/service/TestPojoAiAgent.java          |  52 +++++
 .../agent/it/util/PersistentChatMemoryStore.java   |  56 ++++++
 .../src/main/resources/application.properties      |  17 ++
 .../main/resources/rag/company-knowledge-base.txt  |  41 ++++
 .../langchain4j/agent/it/Langchain4jAgentIT.java   |  16 +-
 .../langchain4j/agent/it/Langchain4jAgentTest.java | 214 +++++++++++++++++++++
 .../agent/it/Langchain4jTestWatcher.java           |  53 +++++
 .../langchain4j/agent/it/OllamaTestResource.java   |  89 +++++++++
 ...embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json |   1 +
 ..._chat-1b3199b6-6110-4d15-94e7-f929c1334826.json |  26 +++
 ..._chat-22a4f651-2f57-4192-8da5-378365cac7c7.json |  26 +++
 ..._chat-2f5f4c05-7f04-4ece-ba42-2b560a76476d.json |  27 +++
 ..._chat-57c9341b-be13-4f43-a087-cbeb07099998.json |  24 +++
 ..._chat-581d8dbe-8619-40d5-b231-06dfc8e63e54.json |  24 +++
 ..._chat-65972a4c-1614-4880-b7a9-757f76c1e88e.json |  27 +++
 ..._chat-73474560-c2d8-4fbf-a14b-9739090453b4.json |  26 +++
 ..._chat-90d1f0a9-0e98-46b8-95be-6a0f10fa145f.json |  27 +++
 ..._chat-97c022a9-b386-47f1-8531-3a1ce3bfa4e0.json |  24 +++
 ..._chat-9ae841ef-69f5-46a1-a304-0a1c2296db8c.json |  24 +++
 ..._chat-a5d8bdce-dd3a-44ab-a796-001de6dba7d6.json |  24 +++
 ..._chat-df5c600e-ec18-4194-9037-7b54b6cbdfc3.json |  24 +++
 ..._chat-e1d90c56-38f7-4e1f-93d0-641fd6f1c5a7.json |  24 +++
 ..._chat-e7aee62a-a9b2-4d51-b31f-f817bc16e013.json |  24 +++
 ..._chat-f02d99a6-9cee-4e8d-bcff-7f6fd7ad3d12.json |  27 +++
 ..._chat-fceeb039-9b61-4ac5-a8c7-71a6483ea6a7.json |  24 +++
 ..._chat-fe594db1-b82f-4216-a1fc-0cfdddc1b33a.json |  24 +++
 ...embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json |  24 +++
 ...embed-f208155e-5af8-4c4c-802d-8b2f5be5cb34.json |  24 +++
 integration-tests/langchain4j-chat/pom.xml         |  13 --
 integration-tests/pom.xml                          |   1 +
 tooling/scripts/test-categories.yaml               |   1 +
 61 files changed, 1846 insertions(+), 252 deletions(-)

diff --git a/docs/modules/ROOT/examples/components/langchain4j-agent.yml 
b/docs/modules/ROOT/examples/components/langchain4j-agent.yml
index 9d9a249464..e242423db4 100644
--- a/docs/modules/ROOT/examples/components/langchain4j-agent.yml
+++ b/docs/modules/ROOT/examples/components/langchain4j-agent.yml
@@ -2,11 +2,11 @@
 # This file was generated by 
camel-quarkus-maven-plugin:update-extension-doc-page
 cqArtifactId: camel-quarkus-langchain4j-agent
 cqArtifactIdBase: langchain4j-agent
-cqNativeSupported: false
-cqStatus: Preview
+cqNativeSupported: true
+cqStatus: Stable
 cqDeprecated: false
 cqJvmSince: 3.26.0
-cqNativeSince: n/a
+cqNativeSince: 3.27.0
 cqCamelPartName: langchain4j-agent
 cqCamelPartTitle: LangChain4j Agent
 cqCamelPartDescription: LangChain4j Agent component
diff --git 
a/docs/modules/ROOT/pages/reference/extensions/langchain4j-agent.adoc 
b/docs/modules/ROOT/pages/reference/extensions/langchain4j-agent.adoc
index 84d4bf4b0d..0ef515f77b 100644
--- a/docs/modules/ROOT/pages/reference/extensions/langchain4j-agent.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/langchain4j-agent.adoc
@@ -4,17 +4,17 @@
 = LangChain4j Agent
 :linkattrs:
 :cq-artifact-id: camel-quarkus-langchain4j-agent
-:cq-native-supported: false
+:cq-native-supported: true
 :cq-status: Preview
 :cq-status-deprecation: Preview
 :cq-description: LangChain4j Agent component
 :cq-deprecated: false
 :cq-jvm-since: 3.26.0
-:cq-native-since: n/a
+:cq-native-since: 3.27.0
 
 ifeval::[{doc-show-badges} == true]
 [.badges]
-[.badge-key]##JVM since##[.badge-supported]##3.26.0## 
[.badge-key]##Native##[.badge-unsupported]##unsupported##
+[.badge-key]##JVM since##[.badge-supported]##3.26.0## [.badge-key]##Native 
since##[.badge-supported]##3.27.0##
 endif::[]
 
 LangChain4j Agent component
@@ -29,6 +29,10 @@ Please refer to the above link for usage and configuration 
details.
 [id="extensions-langchain4j-agent-maven-coordinates"]
 == Maven coordinates
 
+https://{link-quarkus-code-generator}/?extension-search=camel-quarkus-langchain4j-agent[Create
 a new project with this extension on {link-quarkus-code-generator}, 
window="_blank"]
+
+Or add the coordinates to your existing project:
+
 [source,xml]
 ----
 <dependency>
diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml
index aae5ed612f..e535cfcb0e 100644
--- a/extensions-jvm/pom.xml
+++ b/extensions-jvm/pom.xml
@@ -73,7 +73,6 @@
         <module>jooq</module>
         <module>json-patch</module>
         <module>jsonapi</module>
-        <module>langchain4j-agent</module>
         <module>langchain4j-embeddings</module>
         <module>ldif</module>
         <module>lucene</module>
diff --git 
a/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportLangchain4jProcessor.java
 
b/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportLangchain4jProcessor.java
index ac34d5398d..4c92451dab 100644
--- 
a/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportLangchain4jProcessor.java
+++ 
b/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportLangchain4jProcessor.java
@@ -16,25 +16,63 @@
  */
 package org.apache.camel.quarkus.component.support.langchain4j.deployment;
 
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import dev.langchain4j.guardrail.InputGuardrail;
+import dev.langchain4j.guardrail.JsonExtractorOutputGuardrail;
+import dev.langchain4j.guardrail.OutputGuardrail;
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
+import io.quarkus.bootstrap.model.ApplicationModel;
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.BuildSteps;
 import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
 import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
+import 
io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem;
+import 
io.quarkus.deployment.builditem.nativeimage.NativeImageResourcePatternsBuildItem;
 import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 import 
io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
 import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
+import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
+import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
+import io.quarkus.maven.dependency.ResolvedDependency;
+import opennlp.tools.sentdetect.SentenceDetectorFactory;
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.AnnotationTarget;
 import org.jboss.jandex.ClassInfo;
 import org.jboss.jandex.DotName;
+import org.jboss.jandex.IndexView;
+import org.jboss.jandex.MethodInfo;
+import org.jboss.jandex.MethodParameterInfo;
+import org.jboss.jandex.Type;
 
+@BuildSteps(onlyIf = NativeOrNativeSourcesBuild.class)
 class SupportLangchain4jProcessor {
+    private static final Class<?>[] AI_SERVICE_ANNOTATION_CLASSES = {
+            MemoryId.class,
+            SystemMessage.class,
+            UserMessage.class,
+            V.class
+    };
 
     @BuildStep
-    void indexDependencies(BuildProducer<IndexDependencyBuildItem> 
indexedDependencies) {
-        indexedDependencies.produce(new 
IndexDependencyBuildItem("dev.langchain4j", "langchain4j-http-client-jdk"));
-        indexedDependencies.produce(new 
IndexDependencyBuildItem("dev.langchain4j", "langchain4j-ollama"));
+    void indexDependencies(CurateOutcomeBuildItem curateOutcome, 
BuildProducer<IndexDependencyBuildItem> indexedDependencies) {
+        ApplicationModel applicationModel = 
curateOutcome.getApplicationModel();
+        for (ResolvedDependency dependency : 
applicationModel.getDependencies()) {
+            if (dependency.getGroupId().equals("dev.langchain4j")) {
+                indexedDependencies.produce(new 
IndexDependencyBuildItem(dependency.getGroupId(), dependency.getArtifactId()));
+            }
+        }
     }
 
     @BuildStep
@@ -43,10 +81,13 @@ class SupportLangchain4jProcessor {
     }
 
     @BuildStep
-    void registerForReflection(CombinedIndexBuildItem combinedIndex, 
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
-        Set<String> ollamaModelClasses = combinedIndex.getIndex()
-                .getClassesInPackage("dev.langchain4j.model.ollama")
-                .stream()
+    void registerLangChain4jJacksonTypesForReflection(
+            CombinedIndexBuildItem combinedIndex,
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
+        IndexView index = combinedIndex.getIndex();
+
+        // Discover all LangChain4j Jackson model types
+        Set<String> langChain4jModelClasses = 
langChain4jTypesStream(index.getKnownClasses())
                 .filter(classInfo -> classInfo.annotations().stream()
                         .anyMatch(annotationInstance -> 
annotationInstance.name().toString()
                                 
.startsWith("com.fasterxml.jackson.annotation")))
@@ -54,13 +95,117 @@ class SupportLangchain4jProcessor {
                 .map(DotName::toString)
                 .collect(Collectors.toSet());
 
-        
reflectiveClass.produce(ReflectiveClassBuildItem.builder(ollamaModelClasses.toArray(new
 String[0]))
+        
reflectiveClass.produce(ReflectiveClassBuildItem.builder(langChain4jModelClasses.toArray(new
 String[0]))
                 .methods(true)
                 .build());
+
+        // Discover all LangChain4j Jackson serializer / deserializer types
+        Set<String> jacksonSupportClasses = 
langChain4jTypesStream(index.getAllKnownSubclasses(JsonSerializer.class))
+                .map(classInfo -> classInfo.name().toString())
+                .collect(Collectors.toSet());
+
+        
langChain4jTypesStream(index.getAllKnownSubclasses(JsonDeserializer.class))
+                .map(classInfo -> classInfo.name().toString())
+                .forEach(jacksonSupportClasses::add);
+
+        
reflectiveClass.produce(ReflectiveClassBuildItem.builder(jacksonSupportClasses.toArray(new
 String[0])).build());
+
+        // Misc Jackson support
+        
ReflectiveClassBuildItem.builder(PropertyNamingStrategies.SnakeCaseStrategy.class).build();
+    }
+
+    @BuildStep
+    void registerLangChain4jAiServiceTypesForReflection(
+            CombinedIndexBuildItem combinedIndex,
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+            BuildProducer<NativeImageProxyDefinitionBuildItem> 
nativeImageProxy) {
+
+        IndexView index = combinedIndex.getIndex();
+        Set<String> aiServiceInterfaces = new HashSet<>();
+        Set<String> aiServiceTypes = new HashSet<>();
+
+        for (Class<?> aiServiceClass : AI_SERVICE_ANNOTATION_CLASSES) {
+            for (AnnotationInstance annotationInstance : 
index.getAnnotations(aiServiceClass)) {
+                AnnotationTarget annotationTarget = 
annotationInstance.target();
+
+                if 
(annotationTarget.kind().equals(AnnotationTarget.Kind.CLASS)) {
+                    
aiServiceInterfaces.add(annotationTarget.asClass().name().toString());
+                } else if 
(annotationTarget.kind().equals(AnnotationTarget.Kind.METHOD)) {
+                    MethodInfo method = annotationTarget.asMethod();
+                    
aiServiceInterfaces.add(method.declaringClass().name().toString());
+                    if (!method.returnType().kind().equals(Type.Kind.VOID)) {
+                        
aiServiceTypes.add(method.returnType().name().toString());
+                    }
+                } else if 
(annotationTarget.kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) {
+                    MethodParameterInfo methodParameter = 
annotationTarget.asMethodParameter();
+                    
aiServiceTypes.add(methodParameter.type().name().toString());
+
+                    MethodInfo method = methodParameter.method();
+                    
aiServiceInterfaces.add(method.declaringClass().name().toString());
+                    if (!method.returnType().kind().equals(Type.Kind.VOID)) {
+                        
aiServiceTypes.add(method.returnType().name().toString());
+                    }
+                }
+            }
+        }
+
+        // Any types participating in JsonExtractorOutputGuardrail operations 
require reflection
+        index.getAllKnownSubclasses(JsonExtractorOutputGuardrail.class)
+                .stream()
+                .filter(classInfo -> classInfo.superClassType() != null)
+                .filter(classInfo -> 
classInfo.superClassType().kind().equals(Type.Kind.PARAMETERIZED_TYPE))
+                .map(ClassInfo::superClassType)
+                .map(Type::asParameterizedType)
+                .flatMap(type -> type.arguments().stream())
+                .findFirst()
+                .ifPresent(typeParameter -> {
+                    aiServiceTypes.add(typeParameter.name().toString());
+                });
+
+        // AI service interfaces must be registered as native image proxies
+        aiServiceInterfaces
+                .stream()
+                .map(NativeImageProxyDefinitionBuildItem::new)
+                .forEach(nativeImageProxy::produce);
+
+        // Register any types related to the AI service for reflection
+        
reflectiveClass.produce(ReflectiveClassBuildItem.builder(aiServiceTypes.toArray(new
 String[0]))
+                .methods()
+                .build());
+
+        // Guardrails are instantiated dynamically
+        Set<String> guardrailTypes = 
index.getAllKnownImplementations(InputGuardrail.class)
+                .stream()
+                .map(classInfo -> classInfo.name().toString())
+                .collect(Collectors.toSet());
+
+        index.getAllKnownImplementations(OutputGuardrail.class)
+                .stream()
+                .map(classInfo -> classInfo.name().toString())
+                .forEach(guardrailTypes::add);
+
+        
reflectiveClass.produce(ReflectiveClassBuildItem.builder(guardrailTypes.toArray(new
 String[0])).build());
+    }
+
+    @BuildStep
+    void 
registerLangChain4jNlpTypesForReflection(BuildProducer<ReflectiveClassBuildItem>
 reflectiveClass) {
+        
reflectiveClass.produce(ReflectiveClassBuildItem.builder(SentenceDetectorFactory.class).build());
     }
 
     @BuildStep
     RuntimeInitializedClassBuildItem runtimeInitializedClasses() {
         return new 
RuntimeInitializedClassBuildItem("dev.langchain4j.internal.RetryUtils");
     }
+
+    @BuildStep
+    NativeImageResourcePatternsBuildItem nativeImageResources() {
+        return NativeImageResourcePatternsBuildItem.builder()
+                .includeGlob("opennlp/*.bin")
+                .build();
+    }
+
+    static Stream<ClassInfo> langChain4jTypesStream(Collection<ClassInfo> 
classes) {
+        return classes.stream()
+                .filter(classInfo -> 
classInfo.name().toString().startsWith("dev.langchain4j"));
+    }
 }
diff --git a/extensions-support/langchain4j/runtime/pom.xml 
b/extensions-support/langchain4j/runtime/pom.xml
index 033c35c041..553ffd3e8b 100644
--- a/extensions-support/langchain4j/runtime/pom.xml
+++ b/extensions-support/langchain4j/runtime/pom.xml
@@ -38,6 +38,14 @@
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-jackson</artifactId>
         </dependency>
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-core</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/extensions-jvm/langchain4j-agent/deployment/pom.xml 
b/extensions/langchain4j-agent/deployment/pom.xml
similarity index 100%
rename from extensions-jvm/langchain4j-agent/deployment/pom.xml
rename to extensions/langchain4j-agent/deployment/pom.xml
diff --git 
a/extensions-jvm/langchain4j-agent/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/deployment/Langchain4jAgentProcessor.java
 
b/extensions/langchain4j-agent/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/deployment/Langchain4jAgentProcessor.java
similarity index 61%
rename from 
extensions-jvm/langchain4j-agent/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/deployment/Langchain4jAgentProcessor.java
rename to 
extensions/langchain4j-agent/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/deployment/Langchain4jAgentProcessor.java
index 767c3352c0..0f3e510c35 100644
--- 
a/extensions-jvm/langchain4j-agent/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/deployment/Langchain4jAgentProcessor.java
+++ 
b/extensions/langchain4j-agent/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/deployment/Langchain4jAgentProcessor.java
@@ -17,30 +17,13 @@
 package org.apache.camel.quarkus.component.langchain4j.agent.deployment;
 
 import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.annotations.ExecutionTime;
-import io.quarkus.deployment.annotations.Record;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
-import org.apache.camel.quarkus.core.JvmOnlyRecorder;
-import org.jboss.logging.Logger;
 
 class Langchain4jAgentProcessor {
-
-    private static final Logger LOG = 
Logger.getLogger(Langchain4jAgentProcessor.class);
     private static final String FEATURE = "camel-langchain4j-agent";
 
     @BuildStep
     FeatureBuildItem feature() {
         return new FeatureBuildItem(FEATURE);
     }
-
-    /**
-     * Remove this once this extension starts supporting the native mode.
-     */
-    @BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
-    @Record(value = ExecutionTime.RUNTIME_INIT)
-    void warnJvmInNative(JvmOnlyRecorder recorder) {
-        JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time
-        recorder.warnJvmInNative(FEATURE); // warn at runtime
-    }
 }
diff --git a/extensions-jvm/langchain4j-agent/pom.xml 
b/extensions/langchain4j-agent/pom.xml
similarity index 96%
rename from extensions-jvm/langchain4j-agent/pom.xml
rename to extensions/langchain4j-agent/pom.xml
index 9ee3d88123..aab51a76ba 100644
--- a/extensions-jvm/langchain4j-agent/pom.xml
+++ b/extensions/langchain4j-agent/pom.xml
@@ -21,7 +21,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-extensions-jvm</artifactId>
+        <artifactId>camel-quarkus-extensions</artifactId>
         <version>3.27.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
diff --git a/extensions-jvm/langchain4j-agent/runtime/pom.xml 
b/extensions/langchain4j-agent/runtime/pom.xml
similarity index 98%
rename from extensions-jvm/langchain4j-agent/runtime/pom.xml
rename to extensions/langchain4j-agent/runtime/pom.xml
index df30f7c261..769e00cebe 100644
--- a/extensions-jvm/langchain4j-agent/runtime/pom.xml
+++ b/extensions/langchain4j-agent/runtime/pom.xml
@@ -33,6 +33,7 @@
     <properties>
         <camel.quarkus.jvmSince>3.26.0</camel.quarkus.jvmSince>
         <quarkus.metadata.status>preview</quarkus.metadata.status>
+        <camel.quarkus.nativeSince>3.27.0</camel.quarkus.nativeSince>
     </properties>
 
     <dependencies>
diff --git 
a/extensions-jvm/langchain4j-agent/runtime/src/main/resources/META-INF/quarkus-extension.yaml
 
b/extensions/langchain4j-agent/runtime/src/main/resources/META-INF/quarkus-extension.yaml
similarity index 98%
rename from 
extensions-jvm/langchain4j-agent/runtime/src/main/resources/META-INF/quarkus-extension.yaml
rename to 
extensions/langchain4j-agent/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index ceb064c2c9..69a2e1ebc1 100644
--- 
a/extensions-jvm/langchain4j-agent/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ 
b/extensions/langchain4j-agent/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -26,7 +26,6 @@ description: "LangChain4j Agent component"
 metadata:
   icon-url: 
"https://raw.githubusercontent.com/apache/camel-website/main/antora-ui-camel/src/img/logo-d.svg";
   sponsor: "Apache Software Foundation"
-  unlisted: true
   guide: 
"https://camel.apache.org/camel-quarkus/latest/reference/extensions/langchain4j-agent.html";
   categories:
   - "integration"
diff --git 
a/extensions/langchain4j-chat/deployment/src/main/java/org/apache/camel/quarkus/component/langchain/chat/deployment/LangChain4jChatProcessor.java
 
b/extensions/langchain4j-chat/deployment/src/main/java/org/apache/camel/quarkus/component/langchain/chat/deployment/LangChain4jChatProcessor.java
index 43b259daa2..21b454122f 100644
--- 
a/extensions/langchain4j-chat/deployment/src/main/java/org/apache/camel/quarkus/component/langchain/chat/deployment/LangChain4jChatProcessor.java
+++ 
b/extensions/langchain4j-chat/deployment/src/main/java/org/apache/camel/quarkus/component/langchain/chat/deployment/LangChain4jChatProcessor.java
@@ -16,11 +16,8 @@
  */
 package org.apache.camel.quarkus.component.langchain.chat.deployment;
 
-import com.fasterxml.jackson.databind.PropertyNamingStrategies;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
-import 
io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 
 class LangChain4jChatProcessor {
     private static final String FEATURE = "camel-langchain4j-chat";
@@ -29,34 +26,4 @@ class LangChain4jChatProcessor {
     FeatureBuildItem feature() {
         return new FeatureBuildItem(FEATURE);
     }
-
-    @BuildStep
-    NativeImageProxyDefinitionBuildItem nativeImageProxyConfig() {
-        return new 
NativeImageProxyDefinitionBuildItem("dev.langchain4j.model.ollama.OllamaApi");
-    }
-
-    @BuildStep
-    ReflectiveClassBuildItem reflectiveClass() {
-        return 
ReflectiveClassBuildItem.builder(PropertyNamingStrategies.SnakeCaseStrategy.class).constructors().build();
-    }
-
-    @BuildStep
-    ReflectiveClassBuildItem registerForReflection() {
-        return ReflectiveClassBuildItem.builder(
-                "dev.langchain4j.model.ollama.FormatSerializer",
-                "dev.langchain4j.model.ollama.Function",
-                "dev.langchain4j.model.ollama.FunctionCall",
-                "dev.langchain4j.model.ollama.Message",
-                "dev.langchain4j.model.ollama.OllamaChatRequest",
-                "dev.langchain4j.model.ollama.OllamaChatResponse",
-                "dev.langchain4j.model.ollama.Options",
-                "dev.langchain4j.model.ollama.Parameters",
-                "dev.langchain4j.model.ollama.Role",
-                "dev.langchain4j.model.ollama.Tool",
-                "dev.langchain4j.model.ollama.ToolCall",
-                "dev.langchain4j.model.ollama.ChatRequest",
-                "dev.langchain4j.model.ollama.ChatResponse")
-                .methods(true)
-                .build();
-    }
 }
diff --git a/extensions/langchain4j-web-search/deployment/pom.xml 
b/extensions/langchain4j-web-search/deployment/pom.xml
index 9b0d90b8b8..648d3e5f9f 100644
--- a/extensions/langchain4j-web-search/deployment/pom.xml
+++ b/extensions/langchain4j-web-search/deployment/pom.xml
@@ -34,7 +34,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-core-deployment</artifactId>
         </dependency>
-        <!-- TODO: Have a conditional dep for this or transform to JAX-RS -->
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            
<artifactId>camel-quarkus-support-langchain4j-deployment</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-support-retrofit-deployment</artifactId>
diff --git 
a/extensions/langchain4j-web-search/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/web/search/deployment/Langchain4jWebSearchProcessor.java
 
b/extensions/langchain4j-web-search/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/web/search/deployment/Langchain4jWebSearchProcessor.java
index d19af52ed6..5eac56e9cc 100644
--- 
a/extensions/langchain4j-web-search/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/web/search/deployment/Langchain4jWebSearchProcessor.java
+++ 
b/extensions/langchain4j-web-search/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/web/search/deployment/Langchain4jWebSearchProcessor.java
@@ -20,16 +20,11 @@ import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
-import io.quarkus.bootstrap.model.ApplicationModel;
-import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
 import 
io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem;
 import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
-import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
-import io.quarkus.maven.dependency.ResolvedDependency;
 import org.jboss.jandex.ClassInfo;
 import org.jboss.jandex.DotName;
 
@@ -42,22 +37,6 @@ class Langchain4jWebSearchProcessor {
         return new FeatureBuildItem(FEATURE);
     }
 
-    @BuildStep
-    void indexDependencies(
-            BuildProducer<IndexDependencyBuildItem> indexedDependency,
-            CurateOutcomeBuildItem curateOutcome) {
-
-        // Index any dependencies with artifactId prefix 
langchain4j-web-search-engine
-        ApplicationModel applicationModel = 
curateOutcome.getApplicationModel();
-        for (ResolvedDependency dependency : 
applicationModel.getDependencies()) {
-            if (dependency.getGroupId().equals("dev.langchain4j")
-                    && 
dependency.getArtifactId().startsWith("langchain4j-web-search-engine")) {
-                String artifactId = dependency.getArtifactId();
-                indexedDependency.produce(new 
IndexDependencyBuildItem(dependency.getGroupId(), artifactId));
-            }
-        }
-    }
-
     @BuildStep
     NativeImageProxyDefinitionBuildItem 
registerRestServiceProxies(CombinedIndexBuildItem combinedIndex) {
         // If there are any retrofit2 REST service definitions, we need to 
register native proxy definitions for them
diff --git a/extensions/langchain4j-web-search/runtime/pom.xml 
b/extensions/langchain4j-web-search/runtime/pom.xml
index 3e107f7bcd..1cfb4645ff 100644
--- a/extensions/langchain4j-web-search/runtime/pom.xml
+++ b/extensions/langchain4j-web-search/runtime/pom.xml
@@ -41,6 +41,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-langchain4j</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-support-retrofit</artifactId>
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 32c7e01aa5..5698167ae9 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -172,6 +172,7 @@
         <module>kubernetes</module>
         <module>kubernetes-cluster-service</module>
         <module>kudu</module>
+        <module>langchain4j-agent</module>
         <module>langchain4j-chat</module>
         <module>langchain4j-tokenizer</module>
         <module>langchain4j-tools</module>
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentResource.java
 
b/integration-tests-jvm/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentResource.java
deleted file mode 100644
index 5e7a3d5abf..0000000000
--- 
a/integration-tests-jvm/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentResource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.quarkus.component.langchain4j.agent.it;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import org.apache.camel.CamelContext;
-import org.jboss.logging.Logger;
-
-@Path("/langchain4j-agent")
-@ApplicationScoped
-public class Langchain4jAgentResource {
-
-    private static final Logger LOG = 
Logger.getLogger(Langchain4jAgentResource.class);
-
-    private static final String COMPONENT_LANGCHAIN4J_AGENT = 
"langchain4j-agent";
-    @Inject
-    CamelContext context;
-
-    @Path("/load/component/langchain4j-agent")
-    @GET
-    @Produces(MediaType.TEXT_PLAIN)
-    public Response loadComponentLangchain4jAgent() throws Exception {
-        /* This is an autogenerated test */
-        if (context.getComponent(COMPONENT_LANGCHAIN4J_AGENT) != null) {
-            return Response.ok().build();
-        }
-        LOG.warnf("Could not load [%s] from the Camel context", 
COMPONENT_LANGCHAIN4J_AGENT);
-        return Response.status(500, COMPONENT_LANGCHAIN4J_AGENT + " could not 
be loaded from the Camel context").build();
-    }
-}
diff --git a/integration-tests-jvm/pom.xml b/integration-tests-jvm/pom.xml
index 126a29ed1a..88c4732276 100644
--- a/integration-tests-jvm/pom.xml
+++ b/integration-tests-jvm/pom.xml
@@ -72,7 +72,6 @@
         <module>jooq</module>
         <module>json-patch</module>
         <module>jsonapi</module>
-        <module>langchain4j-agent</module>
         <module>langchain4j-embeddings</module>
         <module>ldif</module>
         <module>lucene</module>
diff --git 
a/integration-tests-support/wiremock/src/main/java/org/apache/camel/quarkus/test/wiremock/WireMockTestResourceLifecycleManager.java
 
b/integration-tests-support/wiremock/src/main/java/org/apache/camel/quarkus/test/wiremock/WireMockTestResourceLifecycleManager.java
index bd02e45860..e77d1069e6 100644
--- 
a/integration-tests-support/wiremock/src/main/java/org/apache/camel/quarkus/test/wiremock/WireMockTestResourceLifecycleManager.java
+++ 
b/integration-tests-support/wiremock/src/main/java/org/apache/camel/quarkus/test/wiremock/WireMockTestResourceLifecycleManager.java
@@ -95,6 +95,8 @@ public abstract class WireMockTestResourceLifecycleManager 
implements QuarkusTes
                 SnapshotRecordResult recordResult = server.stopRecording();
 
                 List<StubMapping> stubMappings = 
recordResult.getStubMappings();
+                processRecordedStubMappings(stubMappings);
+
                 if (isDeleteRecordedMappingsOnError()) {
                     for (StubMapping mapping : stubMappings) {
                         int status = mapping.getResponse().getStatus();
@@ -209,6 +211,12 @@ public abstract class WireMockTestResourceLifecycleManager 
implements QuarkusTes
     protected void customizeWiremockConfiguration(WireMockConfiguration 
config) {
     }
 
+    /**
+     * Hook to get a handle on any record stub mappings. Useful for performing 
stub post-processing or cleanup tasks.
+     */
+    protected void processRecordedStubMappings(List<StubMapping> stubMappings) 
{
+    }
+
     /**
      * Creates and starts a {@link WireMockServer} on a random port. {@link 
MockBackendUtils} triggers the log
      * message that signifies mocking is in use.
diff --git a/integration-tests/langchain4j-agent/README.adoc 
b/integration-tests/langchain4j-agent/README.adoc
new file mode 100644
index 0000000000..7c58a613e8
--- /dev/null
+++ b/integration-tests/langchain4j-agent/README.adoc
@@ -0,0 +1,20 @@
+== Camel Quarkus Langchain4j Agent Integration Tests
+
+By default, the Langchain4j-agent integration tests use WireMock to stub 
Ollama API interactions.
+
+To run the `camel-quarkus-langchain4j-agent` integration tests against the 
real API, you need a Ollama instance running with the `orca-mini` model 
downloaded.
+
+When Ollama is running, set the following environment variables:
+
+[source,shell]
+----
+export LANGCHAIN4J_OLLAMA_BASE_URL=your-ollama-api-url
+----
+
+If the WireMock stub recordings need updating, then remove the existing files 
from `src/test/resources/mappings` and run tests with either:
+
+System property `-Dwiremock.record=true`
+
+Or
+
+Set environment variable `WIREMOCK_RECORD=true`
diff --git a/integration-tests-jvm/langchain4j-agent/pom.xml 
b/integration-tests/langchain4j-agent/pom.xml
similarity index 54%
rename from integration-tests-jvm/langchain4j-agent/pom.xml
rename to integration-tests/langchain4j-agent/pom.xml
index 5d801e8ee4..acbee495f1 100644
--- a/integration-tests-jvm/langchain4j-agent/pom.xml
+++ b/integration-tests/langchain4j-agent/pom.xml
@@ -31,14 +31,26 @@
     <description>Integration tests for Camel Quarkus LangChain4j Agent 
extension</description>
 
     <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-langchain4j-agent</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-langchain4j-tools</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy</artifactId>
         </dependency>
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-ollama</artifactId>
+        </dependency>
 
         <!-- test dependencies -->
         <dependency>
@@ -51,6 +63,11 @@
             <artifactId>rest-assured</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-integration-wiremock-support</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
@@ -63,6 +80,19 @@
             </activation>
             <dependencies>
                 <!-- The following dependencies guarantee that this module is 
built after them. You can update them by running `mvn process-resources 
-Pformat -N` from the source tree root directory -->
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-direct-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
                 <dependency>
                     <groupId>org.apache.camel.quarkus</groupId>
                     
<artifactId>camel-quarkus-langchain4j-agent-deployment</artifactId>
@@ -76,7 +106,47 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    
<artifactId>camel-quarkus-langchain4j-tools-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
             </dependencies>
         </profile>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <quarkus.native.enabled>true</quarkus.native.enabled>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
     </profiles>
 </project>
diff --git 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/AgentProducers.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/AgentProducers.java
index 0d0988ccb0..f60dd5ad05 100644
--- 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/AgentProducers.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/AgentProducers.java
@@ -1,4 +1,215 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import dev.langchain4j.data.document.Document;
+import dev.langchain4j.data.document.splitter.DocumentSplitters;
+import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.model.ollama.OllamaChatModel;
+import dev.langchain4j.model.ollama.OllamaEmbeddingModel;
+import dev.langchain4j.rag.DefaultRetrievalAugmentor;
+import dev.langchain4j.rag.RetrievalAugmentor;
+import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
+import dev.langchain4j.store.memory.chat.ChatMemoryStore;
+import io.smallrye.common.annotation.Identifier;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import org.apache.camel.component.langchain4j.agent.api.Agent;
+import org.apache.camel.component.langchain4j.agent.api.AgentConfiguration;
+import org.apache.camel.component.langchain4j.agent.api.AgentWithMemory;
+import org.apache.camel.component.langchain4j.agent.api.AgentWithoutMemory;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.TestPojoJsonExtractorOutputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationFailureInputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationFailureOutputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationSuccessInputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationSuccessOutputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.service.TestPojoAiAgent;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.util.PersistentChatMemoryStore;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import static java.time.Duration.ofSeconds;
+
+@ApplicationScoped
 public class AgentProducers {
+    @ConfigProperty(name = "langchain4j.ollama.base-url")
+    String baseUrl;
+
+    @Produces
+    @Identifier("ollamaOrcaMiniModel")
+    ChatModel ollamaOrcaMiniModel() {
+        return OllamaChatModel.builder()
+                .baseUrl(baseUrl)
+                .modelName("orca-mini")
+                .temperature(0.3)
+                .build();
+    }
+
+    @Produces
+    @Identifier("ollamaLlama31Model")
+    ChatModel ollamaLlama31Model() {
+        return OllamaChatModel.builder()
+                .baseUrl(baseUrl)
+                .modelName("llama3.1:latest")
+                .temperature(0.3)
+                .logResponses(true)
+                .logRequests(true)
+                .build();
+    }
+
+    @Produces
+    ChatMemoryStore chatMemoryStore() {
+        return new PersistentChatMemoryStore();
+    }
+
+    @Produces
+    RetrievalAugmentor retrievalAugmentor() throws IOException {
+        ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+        try (InputStream stream = 
classLoader.getResourceAsStream("rag/company-knowledge-base.txt")) {
+            if (stream == null) {
+                throw new IllegalArgumentException("company-knowledge.txt not 
found");
+            }
+
+            Document document = Document.from(new 
String(stream.readAllBytes(), StandardCharsets.UTF_8));
+
+            List<TextSegment> segments = DocumentSplitters.recursive(300, 
100).split(document);
+
+            EmbeddingModel embeddingModel = OllamaEmbeddingModel.builder()
+                    .baseUrl(baseUrl)
+                    .modelName("nomic-embed-text")
+                    .timeout(Duration.ofSeconds(30))
+                    .build();
+
+            List<Embedding> embeddings = 
embeddingModel.embedAll(segments).content();
+
+            // Store in embedding store
+            EmbeddingStore<TextSegment> embeddingStore = new 
InMemoryEmbeddingStore<>();
+            embeddingStore.addAll(embeddings, segments);
+
+            // Create content retriever
+            EmbeddingStoreContentRetriever contentRetriever = 
EmbeddingStoreContentRetriever.builder()
+                    .embeddingStore(embeddingStore)
+                    .embeddingModel(embeddingModel)
+                    .maxResults(3)
+                    .minScore(0.6)
+                    .build();
+
+            // Create a RetrievalAugmentor that uses only a content retriever 
: naive rag scenario
+            return DefaultRetrievalAugmentor.builder()
+                    .contentRetriever(contentRetriever)
+                    .build();
+        }
+    }
+
+    @Produces
+    @Identifier("simpleAgent")
+    Agent simpleAgent(@Identifier("ollamaOrcaMiniModel") ChatModel chatModel) {
+        return new AgentWithoutMemory(new 
AgentConfiguration().withChatModel(chatModel));
+    }
+
+    @Produces
+    @Identifier("agentWithMemory")
+    Agent agentWithMemory(@Identifier("ollamaLlama31Model") ChatModel 
chatModel, ChatMemoryStore chatMemoryStore) {
+        ChatMemoryProvider chatMemoryProvider = memoryId -> 
MessageWindowChatMemory.builder()
+                .id(memoryId)
+                .maxMessages(10)
+                .chatMemoryStore(chatMemoryStore)
+                .build();
+
+        return new AgentWithMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                .withChatMemoryProvider(chatMemoryProvider));
+    }
+
+    @Produces
+    @Identifier("agentWithSuccessInputGuardrail")
+    Agent agentWithSuccessInputGuardrail(@Identifier("ollamaOrcaMiniModel") 
ChatModel chatModel) {
+        return new AgentWithoutMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                
.withInputGuardrailClasses(List.of(ValidationSuccessInputGuardrail.class)));
+    }
+
+    @Produces
+    @Identifier("agentWithFailingInputGuardrail")
+    Agent agentWithFailingInputGuardrail(@Identifier("ollamaOrcaMiniModel") 
ChatModel chatModel) {
+        return new AgentWithoutMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                
.withInputGuardrailClasses(List.of(ValidationFailureInputGuardrail.class)));
+    }
+
+    @Produces
+    @Identifier("agentWithSuccessOutputGuardrail")
+    Agent agentWithSuccessOutputGuardrail(@Identifier("ollamaOrcaMiniModel") 
ChatModel chatModel) {
+        return new AgentWithoutMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                
.withOutputGuardrailClasses(List.of(ValidationSuccessOutputGuardrail.class)));
+    }
+
+    @Produces
+    @Identifier("agentWithFailingOutputGuardrail")
+    Agent agentWithFailingOutputGuardrail(@Identifier("ollamaOrcaMiniModel") 
ChatModel chatModel) {
+        return new AgentWithoutMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                
.withOutputGuardrailClasses(List.of(ValidationFailureOutputGuardrail.class)));
+    }
+
+    @Produces
+    @Identifier("agentWithJsonExtractorOutputGuardrail")
+    Agent 
agentWithJsonExtractorOutputGuardrail(@Identifier("ollamaOrcaMiniModel") 
ChatModel chatModel) {
+        return new AgentWithoutMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                
.withOutputGuardrailClasses(List.of(TestPojoJsonExtractorOutputGuardrail.class)));
+    }
+
+    @Produces
+    @Identifier("agentWithRag")
+    public Agent agentWithRag(
+            @Identifier("ollamaOrcaMiniModel") ChatModel chatModel,
+            RetrievalAugmentor retrievalAugmentor) {
+        return new AgentWithoutMemory(new AgentConfiguration()
+                .withChatModel(chatModel)
+                .withRetrievalAugmentor(retrievalAugmentor));
+    }
+
+    @Produces
+    @Identifier("agentWithTools")
+    public Agent agentWithTools(@Identifier("ollamaLlama31Model") ChatModel 
chatModel) {
+        return new AgentWithoutMemory(new 
AgentConfiguration().withChatModel(chatModel));
+    }
+
+    @Produces
+    @Identifier("agentWithCustomService")
+    public Agent agentCustom(
+            @Identifier("ollamaOrcaMiniModel") ChatModel chatModel,
+            ObjectMapper objectMapper) {
+        return new TestPojoAiAgent(new AgentConfiguration()
+                .withChatModel(chatModel), objectMapper);
+    }
 }
diff --git 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentResource.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentResource.java
new file mode 100644
index 0000000000..290e2362e0
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentResource.java
@@ -0,0 +1,209 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.apache.camel.Exchange;
+import org.apache.camel.FluentProducerTemplate;
+import org.apache.camel.component.langchain4j.agent.api.AiAgentBody;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationSuccessInputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationSuccessOutputGuardrail;
+
+import static org.apache.camel.component.langchain4j.agent.Headers.MEMORY_ID;
+import static 
org.apache.camel.component.langchain4j.agent.Headers.SYSTEM_MESSAGE;
+
+@Path("/langchain4j-agent")
+@ApplicationScoped
+public class Langchain4jAgentResource {
+    @Inject
+    FluentProducerTemplate producerTemplate;
+
+    @Path("/simple")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithSimpleUserMessage(
+            @QueryParam("bodyAsBean") boolean isBodyAsBean,
+            @QueryParam("systemMessage") String systemMessage,
+            String userMessage) {
+
+        Map<String, Object> headers = new HashMap<>();
+        if (!isBodyAsBean && systemMessage != null) {
+            headers.put(SYSTEM_MESSAGE, systemMessage);
+        }
+
+        Object body;
+        if (isBodyAsBean) {
+            body = new AiAgentBody()
+                    .withSystemMessage(systemMessage)
+                    .withUserMessage(userMessage);
+        } else {
+            body = userMessage;
+        }
+
+        String result = producerTemplate.to("direct:simple-agent")
+                .withBody(body)
+                .withHeaders(headers)
+                .request(String.class);
+
+        return Response.ok(result.trim()).build();
+    }
+
+    @Path("/memory")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithAgentMemory(
+            @QueryParam("memoryId") String memoryId,
+            String userMessage) {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(MEMORY_ID, memoryId);
+
+        String result = producerTemplate.to("direct:agent-with-memory")
+                .withBody(userMessage)
+                .withHeaders(headers)
+                .request(String.class);
+
+        return Response.ok(result.trim()).build();
+    }
+
+    @Path("/input/guardrail/success")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithSuccessInputGuardrail(String userMessage) {
+        producerTemplate.to("direct:agent-with-success-input-guardrail")
+                .withBody(userMessage)
+                .request(String.class);
+
+        return 
Response.ok(ValidationSuccessInputGuardrail.isValidateCalled()).build();
+    }
+
+    @Path("/input/guardrail/failure")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithFailingInputGuardrail(String userMessage) {
+        Exchange result = 
producerTemplate.to("direct:agent-with-failing-input-guardrail")
+                .withBody(userMessage)
+                .send();
+
+        if (result.getException() != null) {
+            return Response.serverError()
+                    .entity(result.getException().getMessage())
+                    .build();
+        }
+
+        return Response.ok().build();
+    }
+
+    @Path("/output/guardrail/success")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithSuccessOutputGuardrail(String userMessage) {
+        producerTemplate.to("direct:agent-with-success-output-guardrail")
+                .withBody(userMessage)
+                .request(String.class);
+
+        return 
Response.ok(ValidationSuccessOutputGuardrail.isValidateCalled()).build();
+    }
+
+    @Path("/output/guardrail/failure")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithFailingOutputGuardrail(String userMessage) {
+        Exchange result = 
producerTemplate.to("direct:agent-with-failing-output-guardrail")
+                .withBody(userMessage)
+                .send();
+
+        if (result.getException() != null) {
+            return Response.serverError()
+                    .entity(result.getException().getMessage())
+                    .build();
+        }
+
+        return Response.ok().build();
+    }
+
+    @Path("/output/guardrail/json/extractor")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response chatWithJsonExtractorOutputGuardrail(String userMessage) {
+        Exchange result = 
producerTemplate.to("direct:agent-with-json-extractor-output-guardrail")
+                .withBody(userMessage)
+                .send();
+
+        if (result.getException() != null) {
+            return Response.serverError()
+                    .entity(result.getException().getMessage())
+                    .build();
+        }
+
+        return Response.ok(result.getMessage().getBody()).build();
+    }
+
+    @Path("/rag")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithRag(String userMessage) {
+        String result = producerTemplate.to("direct:agent-with-rag")
+                .withBody(userMessage)
+                .request(String.class);
+
+        return Response.ok(result.trim()).build();
+    }
+
+    @Path("/tools")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response chatWithTools(String userMessage) {
+        String result = producerTemplate.to("direct:agent-with-tools")
+                .withBody(userMessage)
+                .request(String.class);
+
+        return Response.ok(result.trim()).build();
+    }
+
+    @Path("/custom/service")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response chatWithCustomAiService(String userMessage) {
+        String result = producerTemplate.to("direct:agent-with-custom-service")
+                .withBody(userMessage)
+                .request(String.class);
+
+        return Response.ok(result.trim()).build();
+    }
+}
diff --git 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentRoutes.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentRoutes.java
index 5a7de2040e..3c09c356e6 100644
--- 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentRoutes.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentRoutes.java
@@ -1,4 +1,59 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it;
 
-public class Langchain4jAgentRoutes {
+import org.apache.camel.builder.RouteBuilder;
+
+public class Langchain4jAgentRoutes extends RouteBuilder {
+    public static final String USER_JOHN = "John Doe";
+
+    @Override
+    public void configure() throws Exception {
+        from("direct:simple-agent")
+                .to("langchain4j-agent:test-agent?agent=#simpleAgent");
+
+        from("direct:agent-with-memory")
+                
.to("langchain4j-agent:test-memory-agent?agent=#agentWithMemory");
+
+        from("direct:agent-with-success-input-guardrail")
+                
.to("langchain4j-agent:test-agent-with-success-input-guardrail?agent=#agentWithSuccessInputGuardrail");
+
+        from("direct:agent-with-failing-input-guardrail")
+                
.to("langchain4j-agent:test-agent-with-failing-input-guardrail?agent=#agentWithFailingInputGuardrail");
+
+        from("direct:agent-with-success-output-guardrail")
+                
.to("langchain4j-agent:test-agent-with-success-output-guardrail?agent=#agentWithSuccessOutputGuardrail");
+
+        from("direct:agent-with-failing-output-guardrail")
+                
.to("langchain4j-agent:test-agent-with-failing-output-guardrail?agent=#agentWithFailingOutputGuardrail");
+
+        from("direct:agent-with-json-extractor-output-guardrail")
+                
.to("langchain4j-agent:test-agent-with-json-extractor-output-guardrail?agent=#agentWithJsonExtractorOutputGuardrail");
+
+        from("direct:agent-with-rag")
+                
.to("langchain4j-agent:test-agent-with-rag?agent=#agentWithRag");
+
+        from("direct:agent-with-custom-service")
+                
.to("langchain4j-agent:test-agent-with-custom-service?agent=#agentWithCustomService");
+
+        from("direct:agent-with-tools")
+                
.to("langchain4j-agent:test-agent-with-tools?agent=#agentWithTools&tags=users");
+
+        from("langchain4j-tools:userDb?tags=users&description=Query user 
database by user ID&parameter.userId=integer")
+                .setBody().constant("{\"name\": \"" + USER_JOHN + "\", \"id\": 
\"123\"}");
+    }
 }
diff --git 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/TestPojoJsonExtractorOutputGuardrail.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/TestPojoJsonExtractorOutputGuardrail.java
new file mode 100644
index 0000000000..4edf92b060
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/TestPojoJsonExtractorOutputGuardrail.java
@@ -0,0 +1,41 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it.guardrail;
+
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.guardrail.JsonExtractorOutputGuardrail;
+import dev.langchain4j.guardrail.OutputGuardrailResult;
+import org.apache.camel.quarkus.component.langchain4j.agent.it.model.TestPojo;
+
+public class TestPojoJsonExtractorOutputGuardrail extends 
JsonExtractorOutputGuardrail<TestPojo> {
+    public TestPojoJsonExtractorOutputGuardrail() {
+        super(TestPojo.class);
+    }
+
+    @Override
+    public OutputGuardrailResult validate(AiMessage aiMessage) {
+        OutputGuardrailResult parentResult = super.validate(aiMessage);
+
+        if (parentResult.isSuccess()) {
+            // Return JSON String representation of TestPojo since that's all 
the agent can handle
+            return 
OutputGuardrailResult.successWith(trimNonJson(aiMessage.text()));
+        }
+
+        // Return failures
+        return OutputGuardrailResult.failure(parentResult.failures());
+    }
+}
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationFailureInputGuardrail.java
similarity index 63%
copy from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
copy to 
integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationFailureInputGuardrail.java
index 79890649b0..e720cc9123 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationFailureInputGuardrail.java
@@ -14,21 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.langchain4j.agent.it;
+package org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail;
 
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class Langchain4jAgentTest {
-
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
-    }
+import dev.langchain4j.guardrail.InputGuardrail;
 
+public class ValidationFailureInputGuardrail implements InputGuardrail {
+    // Empty impl to leverage default methods from InputGuardrail, which 
always result in validation failure
 }
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationFailureOutputGuardrail.java
similarity index 63%
copy from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
copy to 
integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationFailureOutputGuardrail.java
index 79890649b0..97bcf7025b 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationFailureOutputGuardrail.java
@@ -14,21 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.langchain4j.agent.it;
+package org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail;
 
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class Langchain4jAgentTest {
-
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
-    }
+import dev.langchain4j.guardrail.OutputGuardrail;
 
+public class ValidationFailureOutputGuardrail implements OutputGuardrail {
+    // Empty impl to leverage default methods from OutputGuardrail, which 
always result in validation failure
 }
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationSuccessInputGuardrail.java
similarity index 54%
copy from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
copy to 
integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationSuccessInputGuardrail.java
index 79890649b0..ac12835725 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationSuccessInputGuardrail.java
@@ -14,21 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.langchain4j.agent.it;
+package org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail;
 
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
+import java.util.concurrent.atomic.AtomicBoolean;
 
-@QuarkusTest
-class Langchain4jAgentTest {
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.guardrail.InputGuardrail;
+import dev.langchain4j.guardrail.InputGuardrailResult;
 
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
+public class ValidationSuccessInputGuardrail implements InputGuardrail {
+    private static final AtomicBoolean validateCalled = new 
AtomicBoolean(false);
+
+    @Override
+    public InputGuardrailResult validate(UserMessage userMessage) {
+        validateCalled.set(true);
+        return InputGuardrailResult.success();
     }
 
+    public static boolean isValidateCalled() {
+        return validateCalled.get();
+    }
 }
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationSuccessOutputGuardrail.java
similarity index 54%
copy from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
copy to 
integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationSuccessOutputGuardrail.java
index 79890649b0..f677dd531c 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/guardrail/ValidationSuccessOutputGuardrail.java
@@ -14,21 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.langchain4j.agent.it;
+package org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail;
 
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
+import java.util.concurrent.atomic.AtomicBoolean;
 
-@QuarkusTest
-class Langchain4jAgentTest {
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.guardrail.OutputGuardrail;
+import dev.langchain4j.guardrail.OutputGuardrailResult;
 
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
+public class ValidationSuccessOutputGuardrail implements OutputGuardrail {
+    private static final AtomicBoolean validateCalled = new 
AtomicBoolean(false);
+
+    @Override
+    public OutputGuardrailResult validate(AiMessage responseFromLLM) {
+        validateCalled.set(true);
+        return OutputGuardrailResult.success();
     }
 
+    public static boolean isValidateCalled() {
+        return validateCalled.get();
+    }
 }
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/model/TestPojo.java
similarity index 63%
copy from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
copy to 
integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/model/TestPojo.java
index 79890649b0..be28be175c 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/model/TestPojo.java
@@ -14,21 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.langchain4j.agent.it;
-
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class Langchain4jAgentTest {
-
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
-    }
+package org.apache.camel.quarkus.component.langchain4j.agent.it.model;
 
+public record TestPojo(String name, String description) {
 }
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/service/CustomAiService.java
similarity index 63%
copy from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
copy to 
integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/service/CustomAiService.java
index 79890649b0..812f6bd7ba 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/service/CustomAiService.java
@@ -14,21 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.langchain4j.agent.it;
+package org.apache.camel.quarkus.component.langchain4j.agent.it.service;
 
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class Langchain4jAgentTest {
-
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
-    }
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
+import org.apache.camel.quarkus.component.langchain4j.agent.it.model.TestPojo;
 
+public interface CustomAiService {
+    @UserMessage("Return an example JSON object about a person named {{name}} 
with the fields name and description")
+    TestPojo getTestPojo(@V("name") String name);
 }
diff --git 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/service/TestPojoAiAgent.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/service/TestPojoAiAgent.java
new file mode 100644
index 0000000000..4dcf8cbcca
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/service/TestPojoAiAgent.java
@@ -0,0 +1,52 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it.service;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import dev.langchain4j.service.AiServices;
+import dev.langchain4j.service.tool.ToolProvider;
+import org.apache.camel.component.langchain4j.agent.api.Agent;
+import org.apache.camel.component.langchain4j.agent.api.AgentConfiguration;
+import org.apache.camel.component.langchain4j.agent.api.AiAgentBody;
+import org.apache.camel.quarkus.component.langchain4j.agent.it.model.TestPojo;
+
+public class TestPojoAiAgent implements Agent {
+    private final AgentConfiguration configuration;
+    private final ObjectMapper objectMapper;
+
+    public TestPojoAiAgent(AgentConfiguration configuration, ObjectMapper 
objectMapper) {
+        this.configuration = configuration;
+        this.objectMapper = objectMapper;
+    }
+
+    @Override
+    public String chat(AiAgentBody aiAgentBody, ToolProvider toolProvider) {
+        TestPojo response = 
createService().getTestPojo(aiAgentBody.getUserMessage());
+        try {
+            return objectMapper.writeValueAsString(response);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    CustomAiService createService() {
+        return AiServices.builder(CustomAiService.class)
+                .chatModel(configuration.getChatModel())
+                .build();
+    }
+}
diff --git 
a/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/util/PersistentChatMemoryStore.java
 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/util/PersistentChatMemoryStore.java
new file mode 100644
index 0000000000..33ff4c9ee2
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/it/util/PersistentChatMemoryStore.java
@@ -0,0 +1,56 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it.util;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.store.memory.chat.ChatMemoryStore;
+
+import static 
dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson;
+import static 
dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson;
+
+public class PersistentChatMemoryStore implements ChatMemoryStore {
+    private final Map<Object, String> memoryMap = new ConcurrentHashMap<>();
+
+    @Override
+    public List<ChatMessage> getMessages(Object memoryId) {
+        String json = memoryMap.get(memoryId);
+        return json != null ? messagesFromJson(json) : List.of();
+    }
+
+    @Override
+    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
+        String json = messagesToJson(messages);
+        memoryMap.put(memoryId, json);
+    }
+
+    @Override
+    public void deleteMessages(Object memoryId) {
+        memoryMap.remove(memoryId);
+    }
+
+    public int getMemoryCount() {
+        return memoryMap.size();
+    }
+
+    public void clearAll() {
+        memoryMap.clear();
+    }
+}
diff --git 
a/integration-tests/langchain4j-agent/src/main/resources/application.properties 
b/integration-tests/langchain4j-agent/src/main/resources/application.properties
new file mode 100644
index 0000000000..38bd39fb72
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/main/resources/application.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+quarkus.native.resources.includes=rag/*
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/main/resources/rag/company-knowledge-base.txt
 
b/integration-tests/langchain4j-agent/src/main/resources/rag/company-knowledge-base.txt
new file mode 100644
index 0000000000..96fe9ab1fe
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/main/resources/rag/company-knowledge-base.txt
@@ -0,0 +1,41 @@
+Miles of Camels Car Rental - Company Information
+
+BUSINESS HOURS:
+Monday-Friday: 8:00 AM - 6:00 PM
+Saturday: 9:00 AM - 4:00 PM
+Sunday: Closed
+
+RENTAL AGREEMENT
+- This agreement is between Miles of Camels Car Rental ("Company") and the 
customer ("Renter").
+
+RENTAL POLICIES:
+- Minimum age: 21 years old
+- Valid driver's license required
+- Credit card required for security deposit
+- Full tank of gas required at return
+
+VEHICLE FLEET:
+- Economy cars: Starting at $29/day
+- Mid-size cars: Starting at $39/day
+- SUVs: Starting at $59/day
+- Luxury vehicles: Starting at $89/day
+
+CANCELLATION POLICY
+- Cancellations made 24 hours before pickup: Full refund
+- Cancellations made 12-24 hours before pickup: 50% refund
+- Cancellations made less than 12 hours before pickup: No refund
+
+VEHICLE RETURN
+- Vehicles must be returned with the same fuel level as at pickup.
+- Late returns incur a fee of $25 per hour or fraction thereof.
+
+DAMAGE POLICY
+- Minor damages under $200: Covered by insurance
+- Major damages over $200: Customer responsibility
+
+INSURANCE
+- Basic insurance is included. Premium insurance available for $15/day.
+
+AGE REQUIREMENTS
+- Minimum age: 21 years old
+- Drivers under 25: Additional surcharge of $20/day
diff --git 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentIT.java
similarity index 68%
rename from 
integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
rename to 
integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentIT.java
index 79890649b0..c0905b5bee 100644
--- 
a/integration-tests-jvm/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
+++ 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentIT.java
@@ -16,19 +16,9 @@
  */
 package org.apache.camel.quarkus.component.langchain4j.agent.it;
 
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import org.junit.jupiter.api.Test;
+import io.quarkus.test.junit.QuarkusIntegrationTest;
 
-@QuarkusTest
-class Langchain4jAgentTest {
-
-    @Test
-    public void loadComponentLangchain4jAgent() {
-        /* A simple autogenerated test */
-        RestAssured.get("/langchain4j-agent/load/component/langchain4j-agent")
-                .then()
-                .statusCode(200);
-    }
+@QuarkusIntegrationTest
+class Langchain4jAgentIT extends Langchain4jAgentTest {
 
 }
diff --git 
a/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
new file mode 100644
index 0000000000..fce52dbc17
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentTest.java
@@ -0,0 +1,214 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationFailureInputGuardrail;
+import 
org.apache.camel.quarkus.component.langchain4j.agent.it.guardrail.ValidationFailureOutputGuardrail;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import static 
org.apache.camel.quarkus.component.langchain4j.agent.it.Langchain4jAgentRoutes.USER_JOHN;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.startsWith;
+
+@ExtendWith(Langchain4jTestWatcher.class)
+@QuarkusTestResource(OllamaTestResource.class)
+@QuarkusTest
+class Langchain4jAgentTest {
+    static final String TEST_USER_MESSAGE_SIMPLE = "What is Apache Camel?";
+    static final String TEST_USER_MESSAGE_STORY = "Write a short story about a 
lost cat.";
+    static final String TEST_SYSTEM_MESSAGE = """
+            You are a whimsical storyteller. Your responses should be 
imaginative, descriptive, and always include a touch of magic. Start every 
story with 'Once upon a starlit night...'""";
+    static final String EXPECTED_STORY_START = "Once upon a starlit night";
+    static final String EXPECTED_STORY_CONTENT = "cat";
+
+    static final String USER_ALICE = "Alice";
+    static final String USER_FAVORITE_COLOR = "blue";
+    static final String MEMORY_ID = "camel-quarkus-memory-1";
+
+    @Test
+    void simpleUserMessage() {
+        RestAssured.given()
+                .body(TEST_USER_MESSAGE_SIMPLE)
+                .post("/langchain4j-agent/simple")
+                .then()
+                .statusCode(200)
+                .body(
+                        not(TEST_USER_MESSAGE_SIMPLE),
+                        containsString("Apache Camel"));
+    }
+
+    @Test
+    void simpleUserMessageWithSystemMessagePrompt() {
+        RestAssured.given()
+                .queryParam("systemMessage", TEST_SYSTEM_MESSAGE)
+                .body(TEST_USER_MESSAGE_STORY)
+                .post("/langchain4j-agent/simple")
+                .then()
+                .statusCode(200)
+                .body(
+                        not(TEST_USER_MESSAGE_SIMPLE),
+                        startsWith(EXPECTED_STORY_START),
+                        containsString(EXPECTED_STORY_CONTENT));
+    }
+
+    @Test
+    void simpleUserMessageWithAiAgentBody() {
+        RestAssured.given()
+                .queryParam("bodyAsBean", true)
+                .queryParam("systemMessage", TEST_SYSTEM_MESSAGE)
+                .body(TEST_USER_MESSAGE_STORY)
+                .post("/langchain4j-agent/simple")
+                .then()
+                .statusCode(200)
+                .body(
+                        not(TEST_USER_MESSAGE_SIMPLE),
+                        startsWith(EXPECTED_STORY_START),
+                        containsString(EXPECTED_STORY_CONTENT));
+    }
+
+    @Test
+    void agentMemory() {
+        RestAssured.given()
+                .queryParam("memoryId", MEMORY_ID)
+                .body("Hello - my name is " + USER_ALICE)
+                .post("/langchain4j-agent/memory")
+                .then()
+                .statusCode(200);
+
+        RestAssured.given()
+                .queryParam("memoryId", MEMORY_ID)
+                .body("And my favorite color is " + USER_FAVORITE_COLOR)
+                .post("/langchain4j-agent/memory")
+                .then()
+                .statusCode(200);
+
+        RestAssured.given()
+                .queryParam("memoryId", MEMORY_ID)
+                .body("Now tell me about myself - what's my name and favorite 
color?")
+                .post("/langchain4j-agent/memory")
+                .then()
+                .statusCode(200)
+                .body(
+                        containsString(USER_ALICE),
+                        containsString(USER_FAVORITE_COLOR));
+    }
+
+    @Test
+    void inputGuardrailSuccess() {
+        RestAssured.given()
+                .body("Hello - my name is " + USER_ALICE)
+                .post("/langchain4j-agent/input/guardrail/success")
+                .then()
+                .statusCode(200)
+                .body(is("true"));
+    }
+
+    @Test
+    void inputGuardrailFailure() {
+        RestAssured.given()
+                .body("Hello - my name is " + USER_ALICE)
+                .post("/langchain4j-agent/input/guardrail/failure")
+                .then()
+                .statusCode(500)
+                .body(containsString("guardrail %s 
failed".formatted(ValidationFailureInputGuardrail.class.getName())));
+    }
+
+    @Test
+    void outputGuardrailSuccess() {
+        RestAssured.given()
+                .body("Hello - my name is " + USER_ALICE)
+                .post("/langchain4j-agent/output/guardrail/success")
+                .then()
+                .statusCode(200)
+                .body(is("true"));
+    }
+
+    @Test
+    void outputGuardrailFailure() {
+        RestAssured.given()
+                .body("Hello - my name is " + USER_ALICE)
+                .post("/langchain4j-agent/output/guardrail/failure")
+                .then()
+                .statusCode(500)
+                .body(containsString("guardrail %s 
failed".formatted(ValidationFailureOutputGuardrail.class.getName())));
+    }
+
+    @Test
+    void jsonExtractorOutputGuardrailSuccess() {
+        RestAssured.given()
+                .body("Return an example JSON object about a person named '%s' 
with the fields name and description"
+                        .formatted(USER_JOHN))
+                .post("/langchain4j-agent/output/guardrail/json/extractor")
+                .then()
+                .statusCode(200)
+                .body(
+                        "name", is(USER_JOHN),
+                        "description", notNullValue());
+    }
+
+    @Test
+    void jsonExtractorOutputGuardrailFailure() {
+        RestAssured.given()
+                // Returns field age which is not defined in TestPojo
+                .body("Return an example JSON object about a person named '%s' 
with the fields age and description"
+                        .formatted(USER_JOHN))
+                .post("/langchain4j-agent/output/guardrail/json/extractor")
+                .then()
+                .statusCode(500)
+                .body(containsString("Invalid JSON"));
+    }
+
+    @Test
+    void simpleRag() {
+        RestAssured.given()
+                .body("Describe the Miles of Camels Car Rental cancellations 
policy for cancelling 24 hours before pickup. What is the refund amount?")
+                .post("/langchain4j-agent/rag")
+                .then()
+                .statusCode(200)
+                .body(containsStringIgnoringCase("full refund"));
+    }
+
+    @Test
+    void simpleToolInvocation() {
+        RestAssured.given()
+                .body("What is the name of user ID 123?")
+                .post("/langchain4j-agent/tools")
+                .then()
+                .statusCode(200)
+                .body(containsStringIgnoringCase(USER_JOHN));
+    }
+
+    @Test
+    void customAiService() {
+        RestAssured.given()
+                .body(USER_JOHN)
+                .post("/langchain4j-agent/custom/service")
+                .then()
+                .statusCode(200)
+                .body(
+                        "name", is(USER_JOHN),
+                        "description", notNullValue());
+    }
+}
diff --git 
a/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jTestWatcher.java
 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jTestWatcher.java
new file mode 100644
index 0000000000..1232c8aca1
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jTestWatcher.java
@@ -0,0 +1,53 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.TestWatcher;
+
+public class Langchain4jTestWatcher implements TestWatcher {
+    private static final String TEST_TO_WATCH = "simpleRag";
+    private static final AtomicBoolean RAG_TEST_EXECUTED = new 
AtomicBoolean(false);
+
+    public static boolean isRagTestExecuted() {
+        return RAG_TEST_EXECUTED.get();
+    }
+
+    public static void reset() {
+        RAG_TEST_EXECUTED.set(false);
+    }
+
+    @Override
+    public void testSuccessful(ExtensionContext context) {
+        if (isTargetTest(context)) {
+            RAG_TEST_EXECUTED.set(true);
+        }
+    }
+
+    @Override
+    public void testFailed(ExtensionContext context, Throwable cause) {
+        if (isTargetTest(context)) {
+            RAG_TEST_EXECUTED.set(true);
+        }
+    }
+
+    private boolean isTargetTest(ExtensionContext context) {
+        return context.getDisplayName().equals(TEST_TO_WATCH);
+    }
+}
diff --git 
a/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/OllamaTestResource.java
 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/OllamaTestResource.java
new file mode 100644
index 0000000000..ee56621035
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/OllamaTestResource.java
@@ -0,0 +1,89 @@
+/*
+ * 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.quarkus.component.langchain4j.agent.it;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Map;
+
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
+import 
org.apache.camel.quarkus.test.wiremock.WireMockTestResourceLifecycleManager;
+
+public class OllamaTestResource extends WireMockTestResourceLifecycleManager {
+    private static final String OLLAMA_ENV_URL = "LANGCHAIN4J_OLLAMA_BASE_URL";
+
+    @Override
+    public Map<String, String> start() {
+        Map<String, String> properties = super.start();
+        String wiremockUrl = properties.get("wiremock.url");
+        String url = wiremockUrl != null ? wiremockUrl : 
getRecordTargetBaseUrl();
+        properties.put("langchain4j.ollama.base-url", url);
+        return properties;
+    }
+
+    @Override
+    protected String getRecordTargetBaseUrl() {
+        return System.getenv(OLLAMA_ENV_URL);
+    }
+
+    @Override
+    protected boolean isMockingEnabled() {
+        return !envVarsPresent(OLLAMA_ENV_URL);
+    }
+
+    @Override
+    protected void processRecordedStubMappings(List<StubMapping> stubMappings) 
{
+        stubMappings.forEach(mapping -> {
+            String fileName = mapping.getName() + "-" + mapping.getId() + 
".json";
+            Path mappingFilePath = Paths.get("./src/test/resources/mappings/", 
fileName);
+
+            // ignoreExtraElements directive can lead to WireMock getting 
confused about which stub to use on request matching.
+            // Force disabling it manually since there's no specific WireMock 
config option to tune it
+            try {
+                String mappingContent = Files.readString(mappingFilePath);
+                mappingContent = 
mappingContent.replace("\"ignoreExtraElements\" : true", 
"\"ignoreExtraElements\" : false");
+                Files.writeString(mappingFilePath, mappingContent);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+            // RetrievalAugmentor bean setup causes /api/embed stubs to be 
recorded on every test run.
+            // So clean up superfluous recordings unless the RAG test actually 
ran
+            if (!Langchain4jTestWatcher.isRagTestExecuted() && 
mapping.getName().startsWith("api_embed")) {
+                Path mappingBodyFilePath = 
Paths.get("./src/test/resources/__files", 
mapping.getResponse().getBodyFileName());
+                try {
+                    Files.deleteIfExists(mappingFilePath);
+                    Files.deleteIfExists(mappingBodyFilePath);
+                } catch (IOException e) {
+                    // Ignored
+                }
+            }
+        });
+    }
+
+    @Override
+    public void stop() {
+        try {
+            super.stop();
+        } finally {
+            Langchain4jTestWatcher.reset();
+        }
+    }
+}
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/__files/api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json
 
b/integration-tests/langchain4j-agent/src/test/resources/__files/api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json
new file mode 100644
index 0000000000..51abe1eb64
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/__files/api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json
@@ -0,0 +1 @@
+{"model":"nomic-embed-text","embeddings":[[-0.07452105,0.008169046,-0.19769989,0.010827969,0.022558905,-0.0049091205,-0.024375705,-0.030121969,-0.016969366,-0.010704407,-0.0005079617,-0.011742291,0.020993004,-0.021422928,0.06289979,-0.01598493,0.013814787,-0.039411496,-0.027963826,0.04861051,0.019435575,0.0045811683,-0.008926697,-0.0142346155,0.05645905,0.020602351,0.039079726,0.056176674,0.012757396,0.0048789666,0.050709747,0.037688315,0.022191847,-0.042426426,-0.058710158,-0.030974913,
 [...]
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-1b3199b6-6110-4d15-94e7-f929c1334826.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-1b3199b6-6110-4d15-94e7-f929c1334826.json
new file mode 100644
index 0000000000..01afffbe17
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-1b3199b6-6110-4d15-94e7-f929c1334826.json
@@ -0,0 +1,26 @@
+{
+  "id" : "1b3199b6-6110-4d15-94e7-f929c1334826",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Make sure you return a valid JSON 
object following the specified format\"\n  } ],\n  \"options\" : {\n    
\"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  \"stream\" : false,\n  
\"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:41:05.942507866Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Sure, I'll do my best to assist you with that. Please provide me with the 
specific format of the JSON object you would like to 
receive.\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":1564689217,\"load_duration\":5121066,\"prompt_eval_count\":52,\"prompt_eval_duration\":48967007,\"eval_count\":32,\"eval_duration\":1509759220}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:05 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "1b3199b6-6110-4d15-94e7-f929c1334826",
+  "persistent" : true,
+  "scenarioName" : "scenario-3-api-chat",
+  "requiredScenarioState" : "scenario-3-api-chat-2",
+  "insertionIndex" : 6
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-22a4f651-2f57-4192-8da5-378365cac7c7.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-22a4f651-2f57-4192-8da5-378365cac7c7.json
new file mode 100644
index 0000000000..722dda1ab3
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-22a4f651-2f57-4192-8da5-378365cac7c7.json
@@ -0,0 +1,26 @@
+{
+  "id" : "22a4f651-2f57-4192-8da5-378365cac7c7",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Hello - my name is Alice\"\n  } 
],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  
\"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:41:17.084840245Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Hello, Alice. How can I assist you 
today?\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":718450885,\"load_duration\":5142315,\"prompt_eval_count\":46,\"prompt_eval_duration\":180030056,\"eval_count\":12,\"eval_duration\":532488717}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:17 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "22a4f651-2f57-4192-8da5-378365cac7c7",
+  "persistent" : true,
+  "scenarioName" : "scenario-2-api-chat",
+  "requiredScenarioState" : "scenario-2-api-chat-3",
+  "insertionIndex" : 2
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-2f5f4c05-7f04-4ece-ba42-2b560a76476d.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-2f5f4c05-7f04-4ece-ba42-2b560a76476d.json
new file mode 100644
index 0000000000..838f4445e4
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-2f5f4c05-7f04-4ece-ba42-2b560a76476d.json
@@ -0,0 +1,27 @@
+{
+  "id" : "2f5f4c05-7f04-4ece-ba42-2b560a76476d",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"system\",\n    \"content\" : \"You are a whimsical storyteller. 
Your responses should be imaginative, descriptive, and always include a touch 
of magic. Start every story with 'Once upon a starlit night...'\"\n  }, {\n    
\"role\" : \"user\",\n    \"content\" : \"Write a short story about a lost 
cat.\"\n  } ],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ 
]\n  },\n  \"stream\" [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:51.505571144Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Once upon a starlit night, a little black and white kitten named Whiskers went 
out to explore her neighborhood. She meowed her way through the streets, 
catching the attention of a kindhearted lady who stopped to pet her. The lady 
promised to keep an eye out for Whiskers and even gave her a name: 
Luna.\\n\\nWhiskers was a happy kitten, exploring every [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:51 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "2f5f4c05-7f04-4ece-ba42-2b560a76476d",
+  "persistent" : true,
+  "scenarioName" : "scenario-1-api-chat",
+  "requiredScenarioState" : "Started",
+  "newScenarioState" : "scenario-1-api-chat-2",
+  "insertionIndex" : 12
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-57c9341b-be13-4f43-a087-cbeb07099998.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-57c9341b-be13-4f43-a087-cbeb07099998.json
new file mode 100644
index 0000000000..1edaa95cef
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-57c9341b-be13-4f43-a087-cbeb07099998.json
@@ -0,0 +1,24 @@
+{
+  "id" : "57c9341b-be13-4f43-a087-cbeb07099998",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Return an example JSON object 
about a person named John Doe with the fields name and description\\nYou must 
answer strictly in the following JSON format: {\\n\\\"name\\\": (type: 
string),\\n\\\"description\\\": (type: string)\\n}\"\n  } ],\n  \"options\" : 
{\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  \"stream\" : 
false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:58.01517105Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Sure! Here's an example JSON object for John Doe:\\n\\n```\\n{\\n 
\\\"name\\\": \\\"John Doe\\\",\\n \\\"description\\\": \\\"A person with a 
unique name that is easy to remember and 
pronounce.\\\"\\n}\\n```\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":3135963143,\"load_duration\":5398287,\"prompt_eval_count\":90,\"prompt_eval_duration
 [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:58 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "57c9341b-be13-4f43-a087-cbeb07099998",
+  "persistent" : true,
+  "insertionIndex" : 10
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-581d8dbe-8619-40d5-b231-06dfc8e63e54.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-581d8dbe-8619-40d5-b231-06dfc8e63e54.json
new file mode 100644
index 0000000000..c7ebe2209a
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-581d8dbe-8619-40d5-b231-06dfc8e63e54.json
@@ -0,0 +1,24 @@
+{
+  "id" : "581d8dbe-8619-40d5-b231-06dfc8e63e54",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Describe the Miles of Camels Car 
Rental cancellations policy for cancelling 24 hours before pickup. What is the 
refund amount?\\n\\nAnswer using the following information:\\nCANCELLATION 
POLICY\\n- Cancellations made 24 hours before pickup: Full refund\\n- 
Cancellations made 12-24 hours before pickup: 50% refund\\n- Cancellations made 
less than 12 hours before picku [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:13.2085886Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Miles of Camels Car Rental cancellations policy for cancelling 24 hours before 
pickup is as follows:\\n\\nCANCELLATION POLICY\\n- Cancellations made 24 hours 
before pickup: Full refund\\n- Cancellations made 12-24 hours before pickup: 
50% refund\\n- Cancellations made less than 12 hours before pickup: No 
refund\\n\\nTherefore, if you cancel your rental [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:13 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "581d8dbe-8619-40d5-b231-06dfc8e63e54",
+  "persistent" : true,
+  "insertionIndex" : 17
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-65972a4c-1614-4880-b7a9-757f76c1e88e.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-65972a4c-1614-4880-b7a9-757f76c1e88e.json
new file mode 100644
index 0000000000..86ffb4ce48
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-65972a4c-1614-4880-b7a9-757f76c1e88e.json
@@ -0,0 +1,27 @@
+{
+  "id" : "65972a4c-1614-4880-b7a9-757f76c1e88e",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Hello - my name is Alice\"\n  } 
],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  
\"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:58.787447825Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Hello, Alice. How can I assist you 
today?\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":708726888,\"load_duration\":6145323,\"prompt_eval_count\":46,\"prompt_eval_duration\":169405185,\"eval_count\":12,\"eval_duration\":532384421}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:58 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "65972a4c-1614-4880-b7a9-757f76c1e88e",
+  "persistent" : true,
+  "scenarioName" : "scenario-2-api-chat",
+  "requiredScenarioState" : "scenario-2-api-chat-2",
+  "newScenarioState" : "scenario-2-api-chat-3",
+  "insertionIndex" : 9
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-73474560-c2d8-4fbf-a14b-9739090453b4.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-73474560-c2d8-4fbf-a14b-9739090453b4.json
new file mode 100644
index 0000000000..c25863e1eb
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-73474560-c2d8-4fbf-a14b-9739090453b4.json
@@ -0,0 +1,26 @@
+{
+  "id" : "73474560-c2d8-4fbf-a14b-9739090453b4",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"system\",\n    \"content\" : \"You are a whimsical storyteller. 
Your responses should be imaginative, descriptive, and always include a touch 
of magic. Start every story with 'Once upon a starlit night...'\"\n  }, {\n    
\"role\" : \"user\",\n    \"content\" : \"Write a short story about a lost 
cat.\"\n  } ],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ 
]\n  },\n  \"stream\" [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:41:35.954805674Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Once upon a starlit night, a curious little girl named Lily wandered through 
the forest near her home. She loved to explore and was always on the lookout 
for new adventures. As she walked, she noticed a small black and white kitten 
wandering around in the distance. The kitten looked lost and scared.\\n\\nLily 
decided to help the little cat and went t [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:35 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "73474560-c2d8-4fbf-a14b-9739090453b4",
+  "persistent" : true,
+  "scenarioName" : "scenario-1-api-chat",
+  "requiredScenarioState" : "scenario-1-api-chat-2",
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-90d1f0a9-0e98-46b8-95be-6a0f10fa145f.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-90d1f0a9-0e98-46b8-95be-6a0f10fa145f.json
new file mode 100644
index 0000000000..b608420e88
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-90d1f0a9-0e98-46b8-95be-6a0f10fa145f.json
@@ -0,0 +1,27 @@
+{
+  "id" : "90d1f0a9-0e98-46b8-95be-6a0f10fa145f",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Hello - my name is Alice\"\n  } 
],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  
\"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:25.87196959Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Hello, Alice. How can I assist you 
today?\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":707788963,\"load_duration\":5513604,\"prompt_eval_count\":46,\"prompt_eval_duration\":168871300,\"eval_count\":12,\"eval_duration\":532436800}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:25 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "90d1f0a9-0e98-46b8-95be-6a0f10fa145f",
+  "persistent" : true,
+  "scenarioName" : "scenario-2-api-chat",
+  "requiredScenarioState" : "Started",
+  "newScenarioState" : "scenario-2-api-chat-2",
+  "insertionIndex" : 14
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-97c022a9-b386-47f1-8531-3a1ce3bfa4e0.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-97c022a9-b386-47f1-8531-3a1ce3bfa4e0.json
new file mode 100644
index 0000000000..af879e3cac
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-97c022a9-b386-47f1-8531-3a1ce3bfa4e0.json
@@ -0,0 +1,24 @@
+{
+  "id" : "97c022a9-b386-47f1-8531-3a1ce3bfa4e0",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"llama3.1:latest\",\n  \"messages\" : 
[ {\n    \"role\" : \"user\",\n    \"content\" : \"What is the name of user ID 
123?\"\n  }, {\n    \"role\" : \"assistant\",\n    \"tool_calls\" : [ {\n      
\"function\" : {\n        \"name\" : \"QueryUserDatabaseByUserID\",\n        
\"arguments\" : {\n          \"userId\" : 123\n        }\n      }\n    } ]\n  
}, {\n    \"role\" : \"tool\",\n    \"content\" : \"{\\\"name\\\": \\\"John 
Doe\\\", \\\"id\\\": \\\ [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"llama3.1:latest\",\"created_at\":\"2025-09-05T08:40:25.005956891Z\",\"message\":{\"role\":\"assistant\",\"content\":\"The
 name associated with user ID 123 is John 
Doe.\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":2737024526,\"load_duration\":18514317,\"prompt_eval_count\":109,\"prompt_eval_duration\":1409228801,\"eval_count\":13,\"eval_duration\":1308313918}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:25 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "97c022a9-b386-47f1-8531-3a1ce3bfa4e0",
+  "persistent" : true,
+  "insertionIndex" : 15
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-9ae841ef-69f5-46a1-a304-0a1c2296db8c.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-9ae841ef-69f5-46a1-a304-0a1c2296db8c.json
new file mode 100644
index 0000000000..046920acc0
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-9ae841ef-69f5-46a1-a304-0a1c2296db8c.json
@@ -0,0 +1,24 @@
+{
+  "id" : "9ae841ef-69f5-46a1-a304-0a1c2296db8c",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"llama3.1:latest\",\n  \"messages\" : 
[ {\n    \"role\" : \"user\",\n    \"content\" : \"Hello - my name is Alice\"\n 
 } ],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  
},\n  \"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"llama3.1:latest\",\"created_at\":\"2025-09-05T08:41:08.791258999Z\",\"message\":{\"role\":\"assistant\",\"content\":\"Nice
 to meet you, Alice! Is there something I can help you with or would you like 
to 
chat?\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":2775439999,\"load_duration\":18186129,\"prompt_eval_count\":16,\"prompt_eval_duration\":367047842,\"eval_count\":23,\"eval_duration\":2389767523}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:08 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "9ae841ef-69f5-46a1-a304-0a1c2296db8c",
+  "persistent" : true,
+  "insertionIndex" : 5
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-a5d8bdce-dd3a-44ab-a796-001de6dba7d6.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-a5d8bdce-dd3a-44ab-a796-001de6dba7d6.json
new file mode 100644
index 0000000000..f37d32a5d3
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-a5d8bdce-dd3a-44ab-a796-001de6dba7d6.json
@@ -0,0 +1,24 @@
+{
+  "id" : "a5d8bdce-dd3a-44ab-a796-001de6dba7d6",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Return an example JSON object 
about a person named 'John Doe' with the fields age and description\"\n  } ],\n 
 \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  
\"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:41:02.730350164Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Sure, here's an example JSON object for John Doe:\\n\\n```json\\n{\\n 
\\\"name\\\": \\\"John Doe\\\",\\n \\\"age\\\": 30,\\n \\\"description\\\": 
\\\"John Doe is a software engineer at XYZ Company. He enjoys hiking and 
playing video games in his free 
time.\\\"\\n}\\n```\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":3896449854,\"load_du
 [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:02 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "a5d8bdce-dd3a-44ab-a796-001de6dba7d6",
+  "persistent" : true,
+  "insertionIndex" : 8
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-df5c600e-ec18-4194-9037-7b54b6cbdfc3.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-df5c600e-ec18-4194-9037-7b54b6cbdfc3.json
new file mode 100644
index 0000000000..c901891dc9
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-df5c600e-ec18-4194-9037-7b54b6cbdfc3.json
@@ -0,0 +1,24 @@
+{
+  "id" : "df5c600e-ec18-4194-9037-7b54b6cbdfc3",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"llama3.1:latest\",\n  \"messages\" : 
[ {\n    \"role\" : \"user\",\n    \"content\" : \"Hello - my name is Alice\"\n 
 }, {\n    \"role\" : \"assistant\",\n    \"content\" : \"Nice to meet you, 
Alice! Is there something I can help you with or would you like to chat?\",\n   
 \"tool_calls\" : [ ]\n  }, {\n    \"role\" : \"user\",\n    \"content\" : 
\"And my favorite color is blue\"\n  }, {\n    \"role\" : \"assistant\",\n    
\"content\" : \"Blue is  [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"llama3.1:latest\",\"created_at\":\"2025-09-05T08:41:16.29486056Z\",\"message\":{\"role\":\"assistant\",\"content\":\"Your
 name is Alice, and your favorite color is blue! (I 
remember!)\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":2387529222,\"load_duration\":18340751,\"prompt_eval_count\":119,\"prompt_eval_duration\":620669949,\"eval_count\":17,\"eval_duration\":1747369140}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:16 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "df5c600e-ec18-4194-9037-7b54b6cbdfc3",
+  "persistent" : true,
+  "insertionIndex" : 3
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-e1d90c56-38f7-4e1f-93d0-641fd6f1c5a7.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-e1d90c56-38f7-4e1f-93d0-641fd6f1c5a7.json
new file mode 100644
index 0000000000..78fa6763ad
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-e1d90c56-38f7-4e1f-93d0-641fd6f1c5a7.json
@@ -0,0 +1,24 @@
+{
+  "id" : "e1d90c56-38f7-4e1f-93d0-641fd6f1c5a7",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"llama3.1:latest\",\n  \"messages\" : 
[ {\n    \"role\" : \"user\",\n    \"content\" : \"Hello - my name is Alice\"\n 
 }, {\n    \"role\" : \"assistant\",\n    \"content\" : \"Nice to meet you, 
Alice! Is there something I can help you with or would you like to chat?\",\n   
 \"tool_calls\" : [ ]\n  }, {\n    \"role\" : \"user\",\n    \"content\" : 
\"And my favorite color is blue\"\n  } ],\n  \"options\" : {\n    
\"temperature\" : 0.3,\n    \"stop\" [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"llama3.1:latest\",\"created_at\":\"2025-09-05T08:41:13.790159977Z\",\"message\":{\"role\":\"assistant\",\"content\":\"Blue
 is a wonderful color. It's so calming and serene. Do you have a particular 
shade of blue that you especially love - light sky blue, navy blue, or perhaps 
a bright cobalt 
blue?\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":4900250015,\"load_duration\":18049552,\"prompt_eval_count\":54,\"prompt_eval_duration\":415571264,\"eval_
 [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:13 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "e1d90c56-38f7-4e1f-93d0-641fd6f1c5a7",
+  "persistent" : true,
+  "insertionIndex" : 4
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-e7aee62a-a9b2-4d51-b31f-f817bc16e013.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-e7aee62a-a9b2-4d51-b31f-f817bc16e013.json
new file mode 100644
index 0000000000..2eb2ab3607
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-e7aee62a-a9b2-4d51-b31f-f817bc16e013.json
@@ -0,0 +1,24 @@
+{
+  "id" : "e7aee62a-a9b2-4d51-b31f-f817bc16e013",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Return an example JSON object 
about a person named 'John Doe' with the fields name and description\"\n  } 
],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  
\"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:54.652463131Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Sure, here's an example JSON object for John Doe:\\n\\n```json\\n{\\n 
\\\"name\\\": \\\"John Doe\\\",\\n \\\"description\\\": \\\"An example person 
with a unique name and a short 
description.\\\"\\n}\\n```\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":3088735669,\"load_duration\":5816213,\"prompt_eval_count\":60,\"prompt_eval_duration\
 [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:54 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "e7aee62a-a9b2-4d51-b31f-f817bc16e013",
+  "persistent" : true,
+  "insertionIndex" : 11
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-f02d99a6-9cee-4e8d-bcff-7f6fd7ad3d12.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-f02d99a6-9cee-4e8d-bcff-7f6fd7ad3d12.json
new file mode 100644
index 0000000000..f51ddcba73
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-f02d99a6-9cee-4e8d-bcff-7f6fd7ad3d12.json
@@ -0,0 +1,27 @@
+{
+  "id" : "f02d99a6-9cee-4e8d-bcff-7f6fd7ad3d12",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"Make sure you return a valid JSON 
object following the specified format\"\n  } ],\n  \"options\" : {\n    
\"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  \"stream\" : false,\n  
\"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:41:04.354385748Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Sure, I'd be happy to help! What is the specific format of the JSON object you 
would like me to 
generate?\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":1509223341,\"load_duration\":5736564,\"prompt_eval_count\":52,\"prompt_eval_duration\":236008817,\"eval_count\":27,\"eval_duration\":1266202591}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:41:04 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "f02d99a6-9cee-4e8d-bcff-7f6fd7ad3d12",
+  "persistent" : true,
+  "scenarioName" : "scenario-3-api-chat",
+  "requiredScenarioState" : "Started",
+  "newScenarioState" : "scenario-3-api-chat-2",
+  "insertionIndex" : 7
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-fceeb039-9b61-4ac5-a8c7-71a6483ea6a7.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-fceeb039-9b61-4ac5-a8c7-71a6483ea6a7.json
new file mode 100644
index 0000000000..5c3dc6018e
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-fceeb039-9b61-4ac5-a8c7-71a6483ea6a7.json
@@ -0,0 +1,24 @@
+{
+  "id" : "fceeb039-9b61-4ac5-a8c7-71a6483ea6a7",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"llama3.1:latest\",\n  \"messages\" : 
[ {\n    \"role\" : \"user\",\n    \"content\" : \"What is the name of user ID 
123?\"\n  } ],\n  \"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ 
]\n  },\n  \"stream\" : false,\n  \"tools\" : [ {\n    \"type\" : 
\"function\",\n    \"function\" : {\n      \"name\" : 
\"QueryUserDatabaseByUserID\",\n      \"description\" : \"Query user database 
by user ID\",\n      \"parameters\" : {\n        \"type\ [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"llama3.1:latest\",\"created_at\":\"2025-09-05T08:40:22.217978108Z\",\"message\":{\"role\":\"assistant\",\"content\":\"\",\"tool_calls\":[{\"function\":{\"name\":\"QueryUserDatabaseByUserID\",\"arguments\":{\"userId\":123}}}]},\"done_reason\":\"stop\",\"done\":true,\"total_duration\":8921529931,\"load_duration\":2746310489,\"prompt_eval_count\":166,\"prompt_eval_duration\":4091169742,\"eval_count\":20,\"eval_duration\":2083023029}",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:22 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "fceeb039-9b61-4ac5-a8c7-71a6483ea6a7",
+  "persistent" : true,
+  "insertionIndex" : 16
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-fe594db1-b82f-4216-a1fc-0cfdddc1b33a.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-fe594db1-b82f-4216-a1fc-0cfdddc1b33a.json
new file mode 100644
index 0000000000..08c28a1728
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_chat-fe594db1-b82f-4216-a1fc-0cfdddc1b33a.json
@@ -0,0 +1,24 @@
+{
+  "id" : "fe594db1-b82f-4216-a1fc-0cfdddc1b33a",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"orca-mini\",\n  \"messages\" : [ {\n 
   \"role\" : \"user\",\n    \"content\" : \"What is Apache Camel?\"\n  } ],\n  
\"options\" : {\n    \"temperature\" : 0.3,\n    \"stop\" : [ ]\n  },\n  
\"stream\" : false,\n  \"tools\" : [ ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"orca-mini\",\"created_at\":\"2025-09-05T08:40:29.803949147Z\",\"message\":{\"role\":\"assistant\",\"content\":\"
 Apache Camel is an open-source project that provides a framework for building 
and managing robust, distributed, and fault-tolerant systems. It allows 
developers to easily build and manage complex workflows between different 
systems, applications, and data sources. The main use cases for Apache Camel 
include routing, serialization/deserialization, and [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:40:29 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "fe594db1-b82f-4216-a1fc-0cfdddc1b33a",
+  "persistent" : true,
+  "insertionIndex" : 13
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json
new file mode 100644
index 0000000000..5d8834a132
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json
@@ -0,0 +1,24 @@
+{
+  "id" : "cc8902fc-b699-41e9-9f80-b50423fbf24c",
+  "name" : "api_embed",
+  "request" : {
+    "url" : "/api/embed",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"nomic-embed-text\",\n  \"input\" : [ 
\"Miles of Camels Car Rental - Company Information\\n\\nBUSINESS 
HOURS:\\nMonday-Friday: 8:00 AM - 6:00 PM\\nSaturday: 9:00 AM - 4:00 
PM\\nSunday: Closed\\n\\nRENTAL AGREEMENT\\n- This agreement is between Miles 
of Camels Car Rental (\\\"Company\\\") and the customer (\\\"Renter\\\").\", 
\"RENTAL POLICIES:\\n- Minimum age: 21 years old\\n- Valid driver's license 
required\\n- Credit card required for security d [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "bodyFileName" : "api_embed-cc8902fc-b699-41e9-9f80-b50423fbf24c.json",
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:39:58 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "cc8902fc-b699-41e9-9f80-b50423fbf24c",
+  "persistent" : true,
+  "insertionIndex" : 19
+}
\ No newline at end of file
diff --git 
a/integration-tests/langchain4j-agent/src/test/resources/mappings/api_embed-f208155e-5af8-4c4c-802d-8b2f5be5cb34.json
 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_embed-f208155e-5af8-4c4c-802d-8b2f5be5cb34.json
new file mode 100644
index 0000000000..dfd4323943
--- /dev/null
+++ 
b/integration-tests/langchain4j-agent/src/test/resources/mappings/api_embed-f208155e-5af8-4c4c-802d-8b2f5be5cb34.json
@@ -0,0 +1,24 @@
+{
+  "id" : "f208155e-5af8-4c4c-802d-8b2f5be5cb34",
+  "name" : "api_embed",
+  "request" : {
+    "url" : "/api/embed",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"nomic-embed-text\",\n  \"input\" : [ 
\"Describe the Miles of Camels Car Rental cancellations policy for cancelling 
24 hours before pickup. What is the refund amount?\" ]\n}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : false
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"nomic-embed-text\",\"embeddings\":[[-0.000546151,0.032465357,-0.1832982,-0.006578118,0.019952673,-0.0018667525,0.014617178,0.020668428,0.0038082553,0.018162793,-0.034445435,-0.011487866,0.039282184,-0.024556652,0.09539182,-0.02630365,0.0276438,-0.022805816,-0.04179049,0.028880822,0.006367407,-0.0022209072,-0.0902023,-0.013760107,0.022725942,0.025699575,0.052584995,0.035527404,-0.025857603,0.017433418,0.06672366,0.022350645,0.009822153,-0.07828854,-0.12301919,0.
 [...]
+    "headers" : {
+      "Date" : "Fri, 05 Sep 2025 08:39:59 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "f208155e-5af8-4c4c-802d-8b2f5be5cb34",
+  "persistent" : true,
+  "insertionIndex" : 18
+}
\ No newline at end of file
diff --git a/integration-tests/langchain4j-chat/pom.xml 
b/integration-tests/langchain4j-chat/pom.xml
index 7007e417e9..5f14db1f4b 100644
--- a/integration-tests/langchain4j-chat/pom.xml
+++ b/integration-tests/langchain4j-chat/pom.xml
@@ -123,19 +123,6 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
-                <dependency>
-                    <groupId>org.apache.camel.quarkus</groupId>
-                    
<artifactId>camel-quarkus-support-retrofit-deployment</artifactId>
-                    <version>${project.version}</version>
-                    <type>pom</type>
-                    <scope>test</scope>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>*</groupId>
-                            <artifactId>*</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
             </dependencies>
         </profile>
         <profile>
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 184bd89b52..00806e905b 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -148,6 +148,7 @@
         <module>knative</module>
         <module>kubernetes</module>
         <module>kudu</module>
+        <module>langchain4j-agent</module>
         <module>langchain4j-chat</module>
         <module>langchain4j-tokenizer</module>
         <module>langchain4j-tools</module>
diff --git a/tooling/scripts/test-categories.yaml 
b/tooling/scripts/test-categories.yaml
index a01f7451ce..9d6d72d07a 100644
--- a/tooling/scripts/test-categories.yaml
+++ b/tooling/scripts/test-categories.yaml
@@ -44,6 +44,7 @@ group-02:
   - jackson-protobuf
   - jfr
   - kafka-oauth
+  - langchain4j-agent
   - oaipmh
   - pubnub
   - protobuf


Reply via email to