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 3fb6ec5f72c7b53eb72414f436aedf0f83f6dc5e
Author: James Netherton <[email protected]>
AuthorDate: Fri Jan 30 07:27:12 2026 +0000

    Add OpenAI extension
    
    Fixes #8203
---
 catalog/pom.xml                                    |  17 ++
 docs/modules/ROOT/examples/components/openai.yml   |  13 ++
 docs/modules/ROOT/nav.adoc                         |   1 +
 .../ROOT/pages/reference/extensions/openai.adoc    |  94 +++++++++
 extensions/openai/deployment/pom.xml               |  71 +++++++
 .../openai/deployment/OpenaiProcessor.java         | 121 ++++++++++++
 extensions/openai/pom.xml                          |  39 ++++
 extensions/openai/runtime/pom.xml                  | 109 +++++++++++
 extensions/openai/runtime/src/main/doc/usage.adoc  |  50 +++++
 .../main/resources/META-INF/quarkus-extension.yaml |  33 ++++
 extensions/pom.xml                                 |   1 +
 integration-tests/openai/README.adoc               |  36 ++++
 integration-tests/openai/pom.xml                   | 173 +++++++++++++++++
 .../component/openai/it/OpenaiResource.java        | 132 +++++++++++++
 .../quarkus/component/openai/it/OpenaiRoutes.java  |  86 +++++++++
 .../quarkus/component/openai/it/model/Product.java |  49 +++++
 .../src/main/resources/application.properties      |  21 ++
 .../openai/src/main/resources/schema/product.json  |  11 ++
 .../quarkus/component/openai/it/OpenaiIT.java      |  24 +++
 .../quarkus/component/openai/it/OpenaiTest.java    | 211 +++++++++++++++++++++
 .../component/openai/it/OpenaiTestResource.java    |  94 +++++++++
 .../openai/src/test/resources/img/camel-logo.png   | Bin 0 -> 13008 bytes
 ...tions-371c2c6c-ace6-42bd-ac5d-6214ba9cdceb.json |  46 +++++
 ...tions-6424a591-8168-4708-9e85-18266a335435.json |  43 +++++
 ...tions-74689f85-f209-4129-b2c8-5e4d38c8eb54.json |  43 +++++
 ...tions-8454f54f-99d3-46a6-b443-720151e4d73a.json |  46 +++++
 ...tions-9368b026-c5a6-4dc2-ad3a-d34eaa1c149b.json |  43 +++++
 ...tions-e61cd29d-a5ff-42ad-a4de-9975902e0f87.json |  45 +++++
 ...tions-f0e11826-78d1-4bf6-988f-f6d31ae30e0b.json |  43 +++++
 ...tions-fb0a5dd7-0e7c-4aa5-9274-203c032bfac5.json |  43 +++++
 .../test/resources/prompts/whatis-camel-prompt.txt |   1 +
 integration-tests/pom.xml                          |   1 +
 poms/bom/pom.xml                                   |  21 ++
 poms/bom/src/main/generated/flattened-full-pom.xml |  21 ++
 .../src/main/generated/flattened-reduced-pom.xml   |  21 ++
 .../generated/flattened-reduced-verbose-pom.xml    |  21 ++
 tooling/scripts/test-categories.yaml               |   1 +
 37 files changed, 1825 insertions(+)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index c08330bf67..e2090b3078 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -3113,6 +3113,19 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-openai</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-openapi-java</artifactId>
@@ -4862,6 +4875,10 @@
                                 
<skipArtifactIdBase>support-.*</skipArtifactIdBase>
                                 
<skipArtifactIdBase>integration-tests?-support-.*</skipArtifactIdBase>
                             </skipArtifactIdBases>
+                            <!-- TODO: Remove this with Camel >= 4.18.0 -->
+                            <additionalExtensions>
+                                
<additionalExtension>openai</additionalExtension>
+                            </additionalExtensions>
                         </configuration>
                     </execution>
                 </executions>
diff --git a/docs/modules/ROOT/examples/components/openai.yml 
b/docs/modules/ROOT/examples/components/openai.yml
new file mode 100644
index 0000000000..6657f35bc2
--- /dev/null
+++ b/docs/modules/ROOT/examples/components/openai.yml
@@ -0,0 +1,13 @@
+# Do not edit directly!
+# This file was generated by 
camel-quarkus-maven-plugin:update-extension-doc-page
+cqArtifactId: camel-quarkus-openai
+cqArtifactIdBase: openai
+cqNativeSupported: true
+cqStatus: Stable
+cqDeprecated: false
+cqJvmSince: 3.32.0
+cqNativeSince: 3.32.0
+cqCamelPartName: openai
+cqCamelPartTitle: OpenAI
+cqCamelPartDescription: OpenAI endpoint for chat completion.
+cqExtensionPageTitle: OpenAI
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 9dfdc87ff8..f5259c0892 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -251,6 +251,7 @@
 *** xref:reference/extensions/observability-services.adoc[Observability 
Services]
 *** xref:reference/extensions/olingo4.adoc[Olingo4]
 *** xref:reference/extensions/once.adoc[Once]
+*** xref:reference/extensions/openai.adoc[OpenAI]
 *** xref:reference/extensions/openapi-java.adoc[OpenAPI Java]
 *** xref:reference/extensions/opensearch.adoc[OpenSearch]
 *** xref:reference/extensions/openstack.adoc[OpenStack]
diff --git a/docs/modules/ROOT/pages/reference/extensions/openai.adoc 
b/docs/modules/ROOT/pages/reference/extensions/openai.adoc
new file mode 100644
index 0000000000..66a29dbfa3
--- /dev/null
+++ b/docs/modules/ROOT/pages/reference/extensions/openai.adoc
@@ -0,0 +1,94 @@
+// Do not edit directly!
+// This file was generated by 
camel-quarkus-maven-plugin:update-extension-doc-page
+[id="extensions-openai"]
+= OpenAI
+:linkattrs:
+:cq-artifact-id: camel-quarkus-openai
+:cq-native-supported: true
+:cq-status: Stable
+:cq-status-deprecation: Stable
+:cq-description: OpenAI endpoint for chat completion.
+:cq-deprecated: false
+:cq-jvm-since: 3.32.0
+:cq-native-since: 3.32.0
+
+ifeval::[{doc-show-badges} == true]
+[.badges]
+[.badge-key]##JVM since##[.badge-supported]##3.32.0## [.badge-key]##Native 
since##[.badge-supported]##3.32.0##
+endif::[]
+
+OpenAI endpoint for chat completion.
+
+[id="extensions-openai-maven-coordinates"]
+== Maven coordinates
+
+https://{link-quarkus-code-generator}/?extension-search=camel-quarkus-openai[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>
+    <groupId>org.apache.camel.quarkus</groupId>
+    <artifactId>camel-quarkus-openai</artifactId>
+</dependency>
+----
+ifeval::[{doc-show-user-guide-link} == true]
+Check the xref:user-guide/index.adoc[User guide] for more information about 
writing Camel Quarkus applications.
+endif::[]
+
+[id="extensions-openai-usage"]
+== Usage
+[id="extensions-openai-usage-structured-output-with-output-class-in-native-mode"]
+=== Structured output with output class in native mode
+
+When using structured output with the `outputClass` option in native mode, you 
must ensure that the target class is registered for reflection.
+
+This can be done with the `@RegisterForReflection` annotation or configuration 
property `quarkus.camel.native.reflection.include-patterns`. For example:
+
+[source,java]
+----
+@RegisterForReflection
+public class MyStructuredOutputClass {
+    ...
+}
+----
+
+[source,java]
+----
+public class Routes extends RouteBuilder {
+    @Override
+    public void configure() {
+        from("direct:chat")
+            .to("openai:chat-completion?outputClass=" + 
MyStructuredOutputClass.class.getName());
+    }
+}
+----
+
+[id="extensions-openai-usage-structured-output-with-json-schema-from-classpath-resource-in-native-mode"]
+=== Structured output with JSON schema from classpath resource in native mode
+
+When loading JSON schema classpath resources in native mode, you must ensure 
the resource is included in the native application.
+
+For example, given a route like the following.
+
+[source,java]
+----
+public class Routes extends RouteBuilder {
+    @Override
+    public void configure() {
+        from("direct:chat")
+            
.to("openai:chat-completion?jsonSchema=resource:classpath:schemas/mySchema.json");
+    }
+}
+----
+
+Add the following to `application.properties`.
+
+[source,properties]
+----
+quarkus.native.resources.includes=schemas/mySchema.json
+----
+
+Refer to the xref:user-guide/native-mode.adoc#reflection[Native mode] user 
guide for more information.
+
diff --git a/extensions/openai/deployment/pom.xml 
b/extensions/openai/deployment/pom.xml
new file mode 100644
index 0000000000..ddcbe4c1e2
--- /dev/null
+++ b/extensions/openai/deployment/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-openai-parent</artifactId>
+        <version>3.32.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-openai-deployment</artifactId>
+    <name>Camel Quarkus :: OpenAI :: Deployment</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-core-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-swagger-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jackson-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-openai</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>io.quarkus</groupId>
+                            
<artifactId>quarkus-extension-processor</artifactId>
+                            <version>${quarkus.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git 
a/extensions/openai/deployment/src/main/java/org/apache/camel/quarkus/component/openai/deployment/OpenaiProcessor.java
 
b/extensions/openai/deployment/src/main/java/org/apache/camel/quarkus/component/openai/deployment/OpenaiProcessor.java
new file mode 100644
index 0000000000..61cc735a7e
--- /dev/null
+++ 
b/extensions/openai/deployment/src/main/java/org/apache/camel/quarkus/component/openai/deployment/OpenaiProcessor.java
@@ -0,0 +1,121 @@
+/*
+ * 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.openai.deployment;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.openai.core.JsonField;
+import com.openai.core.JsonValue;
+import com.openai.models.chat.completions.ChatCompletion;
+import com.openai.models.chat.completions.ChatCompletionChunk;
+import io.quarkus.deployment.Capabilities;
+import io.quarkus.deployment.Capability;
+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.RemovedResourceBuildItem;
+import 
io.quarkus.deployment.builditem.nativeimage.NativeImageResourcePatternsBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import 
io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem;
+import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
+import io.quarkus.jackson.deployment.IgnoreJsonDeserializeClassBuildItem;
+import io.quarkus.maven.dependency.ArtifactKey;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.Type;
+
+class OpenaiProcessor {
+    private static final String FEATURE = "camel-openai";
+
+    @BuildStep
+    FeatureBuildItem feature() {
+        return new FeatureBuildItem(FEATURE);
+    }
+
+    @BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
+    IndexDependencyBuildItem indexDependencies() {
+        return new IndexDependencyBuildItem("com.openai", "openai-java-core");
+    }
+
+    @BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
+    void registerForReflection(
+            Capabilities capabilities,
+            CombinedIndexBuildItem combinedIndex,
+            BuildProducer<IgnoreJsonDeserializeClassBuildItem> 
ignoredJsonDeserializeClass,
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+            BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy,
+            BuildProducer<NativeImageResourcePatternsBuildItem> 
nativeResourcePatterns) {
+
+        reflectiveHierarchy.produce(ReflectiveHierarchyBuildItem
+                .builder(Type.create(ChatCompletion.class)).ignoreNested(false)
+                .build());
+
+        reflectiveHierarchy.produce(ReflectiveHierarchyBuildItem
+                
.builder(Type.create(ChatCompletionChunk.class)).ignoreNested(false)
+                .build());
+
+        // Make quarkus-kotlin optional since not everything it provides is 
required
+        if (capabilities.isMissing(Capability.KOTLIN)) {
+            Stream.of(JsonField.class.getName(), JsonValue.class.getName())
+                    .map(DotName::createSimple)
+                    .forEach(className -> {
+                        // Suppress quarkus-jackson adding its own reflective 
config for JsonDeserialize so we can add our own
+                        ignoredJsonDeserializeClass.produce(new 
IgnoreJsonDeserializeClassBuildItem(className));
+                        
reflectiveHierarchy.produce(ReflectiveHierarchyBuildItem
+                                .builder(Type.create(className, 
Type.Kind.CLASS)).ignoreNested(false)
+                                .build());
+                    });
+
+            Set<String> openAIModelClassNames = combinedIndex.getIndex()
+                    .getKnownClasses()
+                    .stream()
+                    .map(ClassInfo::name)
+                    .map(DotName::toString)
+                    .filter(className -> 
className.startsWith("com.openai.models"))
+                    .collect(Collectors.toSet());
+
+            
reflectiveClass.produce(ReflectiveClassBuildItem.builder(openAIModelClassNames.toArray(new
 String[0]))
+                    .fields()
+                    .methods()
+                    .build());
+
+            
nativeResourcePatterns.produce(NativeImageResourcePatternsBuildItem.builder()
+                    .includeGlobs("META-INF/**/*.kotlin_module",
+                            "META-INF/services/kotlin.reflect.*",
+                            "**/*.kotlin_builtins")
+                    .build());
+        }
+    }
+
+    @BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
+    RemovedResourceBuildItem excludeNativeImageDirectives() {
+        // Remove all native-image directives from openai-java-core as it's 
mostly redundant & inaccurate for Quarkus
+        return new RemovedResourceBuildItem(
+                ArtifactKey.fromString("com.openai:openai-java-core"),
+                Set.of(
+                        "META-INF/native-image/jni-config.json",
+                        "META-INF/native-image/predefined-classes-config.json",
+                        "META-INF/native-image/proxy-config.json",
+                        "META-INF/native-image/reflect-config.json",
+                        "META-INF/native-image/resource-config.json",
+                        "META-INF/native-image/serialization-config.json"));
+    }
+}
diff --git a/extensions/openai/pom.xml b/extensions/openai/pom.xml
new file mode 100644
index 0000000000..5db4d58503
--- /dev/null
+++ b/extensions/openai/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-extensions</artifactId>
+        <version>3.32.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-openai-parent</artifactId>
+    <name>Camel Quarkus :: OpenAI</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>deployment</module>
+        <module>runtime</module>
+    </modules>
+</project>
diff --git a/extensions/openai/runtime/pom.xml 
b/extensions/openai/runtime/pom.xml
new file mode 100644
index 0000000000..1f27c1edde
--- /dev/null
+++ b/extensions/openai/runtime/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-openai-parent</artifactId>
+        <version>3.32.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-openai</artifactId>
+    <name>Camel Quarkus :: OpenAI :: Runtime</name>
+    <description>OpenAI endpoint for chat completion.</description>
+
+    <properties>
+        <camel.quarkus.jvmSince>3.32.0</camel.quarkus.jvmSince>
+        <camel.quarkus.nativeSince>3.32.0</camel.quarkus.nativeSince>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-swagger</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-openai</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>io.quarkus</groupId>
+                <artifactId>quarkus-extension-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>io.quarkus</groupId>
+                            
<artifactId>quarkus-extension-processor</artifactId>
+                            <version>${quarkus.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+    <profiles>
+        <profile>
+            <id>full</id>
+            <activation>
+                <property>
+                    <name>!quickly</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.camel.quarkus</groupId>
+                        <artifactId>camel-quarkus-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>update-extension-doc-page</id>
+                                <goals>
+                                    <goal>update-extension-doc-page</goal>
+                                </goals>
+                                <phase>process-classes</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/extensions/openai/runtime/src/main/doc/usage.adoc 
b/extensions/openai/runtime/src/main/doc/usage.adoc
new file mode 100644
index 0000000000..6312e4bbc5
--- /dev/null
+++ b/extensions/openai/runtime/src/main/doc/usage.adoc
@@ -0,0 +1,50 @@
+=== Structured output with output class in native mode
+
+When using structured output with the `outputClass` option in native mode, you 
must ensure that the target class is registered for reflection.
+
+This can be done with the `@RegisterForReflection` annotation or configuration 
property `quarkus.camel.native.reflection.include-patterns`. For example:
+
+[source,java]
+----
+@RegisterForReflection
+public class MyStructuredOutputClass {
+    ...
+}
+----
+
+[source,java]
+----
+public class Routes extends RouteBuilder {
+    @Override
+    public void configure() {
+        from("direct:chat")
+            .to("openai:chat-completion?outputClass=" + 
MyStructuredOutputClass.class.getName());
+    }
+}
+----
+
+=== Structured output with JSON schema from classpath resource in native mode
+
+When loading JSON schema classpath resources in native mode, you must ensure 
the resource is included in the native application.
+
+For example, given a route like the following.
+
+[source,java]
+----
+public class Routes extends RouteBuilder {
+    @Override
+    public void configure() {
+        from("direct:chat")
+            
.to("openai:chat-completion?jsonSchema=resource:classpath:schemas/mySchema.json");
+    }
+}
+----
+
+Add the following to `application.properties`.
+
+[source,properties]
+----
+quarkus.native.resources.includes=schemas/mySchema.json
+----
+
+Refer to the xref:user-guide/native-mode.adoc#reflection[Native mode] user 
guide for more information.
diff --git 
a/extensions/openai/runtime/src/main/resources/META-INF/quarkus-extension.yaml 
b/extensions/openai/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000000..96712fbf2a
--- /dev/null
+++ 
b/extensions/openai/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+# This is a generated file. Do not edit directly!
+# To re-generate, run the following command from the top level directory:
+#
+#   mvn -N cq:update-quarkus-metadata
+#
+---
+name: "Camel OpenAI"
+description: "OpenAI endpoint for chat completion"
+metadata:
+  icon-url: 
"https://raw.githubusercontent.com/apache/camel-website/main/antora-ui-camel/src/img/logo-d.svg";
+  sponsor: "Apache Software Foundation"
+  guide: 
"https://camel.apache.org/camel-quarkus/latest/reference/extensions/openai.html";
+  categories:
+  - "integration"
+  status:
+  - "stable"
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 633ea293de..7816c06180 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -219,6 +219,7 @@
         <module>ognl</module>
         <module>olingo4</module>
         <module>once</module>
+        <module>openai</module>
         <module>openapi-java</module>
         <module>openstack</module>
         <module>opentelemetry</module>
diff --git a/integration-tests/openai/README.adoc 
b/integration-tests/openai/README.adoc
new file mode 100644
index 0000000000..97bc3d5edf
--- /dev/null
+++ b/integration-tests/openai/README.adoc
@@ -0,0 +1,36 @@
+== Camel Quarkus OpenAI Integration Tests
+
+By default, the OpenAI integration tests use WireMock to stub the API 
interactions.
+
+=== Testing with OpenAI
+
+To run the `camel-quarkus-openai` integration tests against the real OpenAI 
APIs, you must first create a OpenAI developer account 
https://developers.openai.com/.
+Or if you are already registered for ChatGPT, then you can use your account 
credentials to log in to the developer area.
+
+With access to the developer area you can create a new project together with 
an API key for use in the required environment variables as shown below.
+
+[source,shell]
+----
+export OPENAI_API_KEY=your-openai-api-key
+----
+
+This will test with model `gpt-5` against the default API endpoint of 
https://api.openai.com/v1.
+
+=== Testing with alternate OpenAI compatible providers
+
+Alternatively, you can test against any OpenAI compatible API by configuring 
the endpoint URL.
+
+[source,shell]
+----
+export OPENAI_API_KEY=fake-key
+export OPENAI_BASE_URL=https://you-api-endpoint/v1
+export OPENAI_MODEL=your-model-name
+----
+
+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/openai/pom.xml b/integration-tests/openai/pom.xml
new file mode 100644
index 0000000000..aa5252c102
--- /dev/null
+++ b/integration-tests/openai/pom.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-build-parent-it</artifactId>
+        <version>3.32.0-SNAPSHOT</version>
+        <relativePath>../../poms/build-parent-it/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-integration-test-openai</artifactId>
+    <name>Camel Quarkus :: Integration Tests :: OpenAI</name>
+    <description>Integration tests for Camel Quarkus OpenAI 
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-file</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-openai</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-seda</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</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>
+        <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>
+        <profile>
+            <id>virtualDependencies</id>
+            <activation>
+                <property>
+                    <name>!noVirtualDependencies</name>
+                </property>
+            </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-file-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-openai-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-seda-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
+</project>
diff --git 
a/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiResource.java
 
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiResource.java
new file mode 100644
index 0000000000..4b69253890
--- /dev/null
+++ 
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiResource.java
@@ -0,0 +1,132 @@
+/*
+ * 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.openai.it;
+
+import java.io.File;
+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.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.CamelContext;
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.openai.OpenAIConstants;
+import org.apache.camel.util.ObjectHelper;
+
+@Path("/openai")
+@ApplicationScoped
+public class OpenaiResource {
+    @Inject
+    ProducerTemplate producerTemplate;
+
+    @Inject
+    ConsumerTemplate consumerTemplate;
+
+    @Inject
+    CamelContext context;
+
+    @Path("/chat")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public String chat(
+            @QueryParam("userMessage") String userMessage,
+            String chatMessageContent) {
+        return doChat(userMessage, chatMessageContent);
+    }
+
+    @Path("/chat/streaming")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    public void chat(String chatMessageContent) {
+        producerTemplate.sendBody("direct:chatStreaming", chatMessageContent);
+    }
+
+    @Path("/chat/image")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public String chatWithImage(@QueryParam("userMessage") String userMessage, 
String imagePath) {
+        return doChat(userMessage, new File(imagePath));
+    }
+
+    @Path("/chat/memory")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public String chatWithMemory(String chatMessageContent) {
+        return producerTemplate.requestBody("direct:chatWithMemory", 
chatMessageContent, String.class);
+    }
+
+    @Path("/chat/structured/schema")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String chatWithStructuredOutputWithSchema(String 
chatMessageContent) {
+        return 
producerTemplate.requestBody("direct:chatStructuredOutputWithSchema", 
chatMessageContent, String.class);
+    }
+
+    @Path("/chat/structured/class")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String chatWithStructuredOutputWithClass(String chatMessageContent) 
{
+        return 
producerTemplate.requestBody("direct:chatStructuredOutputWithClass", 
chatMessageContent, String.class);
+    }
+
+    @Path("/chat/results")
+    @GET
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public String chatResults(@QueryParam("endpointUri") String endpointUri) {
+        return consumerTemplate.receiveBody(endpointUri, 10000, String.class);
+    }
+
+    @Path("/routes/{routeId}/{operation}")
+    @POST
+    public void routeOperations(
+            @PathParam("routeId") String routeId,
+            @PathParam("operation") String operation) throws Exception {
+
+        if (operation.equals("start")) {
+            context.getRouteController().startRoute(routeId);
+        } else if (operation.equals("stop")) {
+            context.getRouteController().stopRoute(routeId);
+        } else {
+            throw new IllegalArgumentException("Unknown operation: " + 
operation);
+        }
+    }
+
+    private String doChat(String userMessage, Object chatMessageContent) {
+        Map<String, Object> headers = new HashMap<>();
+
+        if (ObjectHelper.isNotEmpty(userMessage)) {
+            headers.put(OpenAIConstants.USER_MESSAGE, userMessage);
+        }
+
+        return producerTemplate.requestBodyAndHeaders("direct:chat", 
chatMessageContent, headers, String.class);
+    }
+}
diff --git 
a/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
 
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
new file mode 100644
index 0000000000..a8eb914d21
--- /dev/null
+++ 
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
@@ -0,0 +1,86 @@
+/*
+ * 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.openai.it;
+
+import java.util.List;
+
+import com.openai.models.chat.completions.ChatCompletionChunk;
+import com.openai.models.chat.completions.ChatCompletionChunk.Choice;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.component.openai.it.model.Product;
+import org.apache.camel.util.ObjectHelper;
+
+public class OpenaiRoutes extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("direct:chat")
+                .to("openai:chat-completion")
+                .log("Chat response: ${body}");
+
+        from("direct:chatStreaming")
+                .to("openai:chat-completion?streaming=true")
+                .split(body())
+                .streaming()
+                .process(new Processor() {
+                    @Override
+                    public void process(Exchange exchange) throws Exception {
+                        Message message = exchange.getMessage();
+                        ChatCompletionChunk chunk = 
message.getBody(ChatCompletionChunk.class);
+                        List<Choice> choices = chunk.choices();
+                        if (!choices.isEmpty()) {
+                            Choice choice = choices.get(0);
+                            choice.delta().content().ifPresent(content -> {
+                                if (ObjectHelper.isNotEmpty(content) && 
!content.equals("\n")) {
+                                    message.setBody(content);
+                                } else {
+                                    message.setBody(null);
+                                }
+                            });
+                        } else {
+                            message.setBody(null);
+                        }
+                    }
+                })
+                .filter().simple("${body} != null")
+                .log("Streaming chat chunk: ${body}")
+                .wireTap("seda:chatStreamingResult");
+
+        from("direct:chatStructuredOutputWithSchema")
+                
.to("openai:chat-completion?jsonSchema=resource:classpath:schema/product.json")
+                .log("Structured output with schema chat response: ${body}");
+
+        from("direct:chatStructuredOutputWithClass")
+                .to("openai:chat-completion?outputClass=" + 
Product.class.getName())
+                .log("Structured output with class chat response: ${body}");
+
+        
from("file:target/prompts?noop=true").routeId("file-prompts").autoStartup(false)
+                .to("openai:chat-completion")
+                .log("File prompt chat response: ${body}")
+                .to("seda:filePromptResults");
+
+        from("direct:chatWithMemory")
+                .to("openai:chat-completion?conversationMemory=true")
+                .log("Chat response 1: ${body}")
+                .setBody(constant("What is my Camel species?"))
+                .to("openai:chat-completion?conversationMemory=true")
+                .log("Chat response 2: ${body}");
+    }
+}
diff --git 
a/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/model/Product.java
 
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/model/Product.java
new file mode 100644
index 0000000000..be10f8848f
--- /dev/null
+++ 
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/model/Product.java
@@ -0,0 +1,49 @@
+/*
+ * 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.openai.it.model;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
+public class Product {
+    private String name;
+    private Double price;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Double getPrice() {
+        return price;
+    }
+
+    public void setPrice(Double price) {
+        this.price = price;
+    }
+
+    @Override
+    public String toString() {
+        return "{"
+                + "\"name\":\"" + name + "\","
+                + "\"price\":" + price
+                + "}";
+    }
+}
diff --git a/integration-tests/openai/src/main/resources/application.properties 
b/integration-tests/openai/src/main/resources/application.properties
new file mode 100644
index 0000000000..f376a66421
--- /dev/null
+++ b/integration-tests/openai/src/main/resources/application.properties
@@ -0,0 +1,21 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# The LLM may time a long time to respond
+quarkus.http.test-timeout=120S
+
+quarkus.native.resources.includes=schema/product.json
diff --git a/integration-tests/openai/src/main/resources/schema/product.json 
b/integration-tests/openai/src/main/resources/schema/product.json
new file mode 100644
index 0000000000..3ec778a8eb
--- /dev/null
+++ b/integration-tests/openai/src/main/resources/schema/product.json
@@ -0,0 +1,11 @@
+{
+  "type": "object",
+  "properties": {
+    "name": {
+      "type": "string"
+    },
+    "price": {
+      "type": "number"
+    }
+  }
+}
diff --git 
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
 
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
new file mode 100644
index 0000000000..b30598ff66
--- /dev/null
+++ 
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
@@ -0,0 +1,24 @@
+/*
+ * 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.openai.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class OpenaiIT extends OpenaiTest {
+
+}
diff --git 
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTest.java
 
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTest.java
new file mode 100644
index 0000000000..464c22ede1
--- /dev/null
+++ 
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.openai.it;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import io.restassured.response.Response;
+import org.apache.camel.util.FileUtil;
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@QuarkusTestResource(OpenaiTestResource.class)
+@QuarkusTest
+class OpenaiTest {
+    @Test
+    void simpleChat() {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("In one sentence, what is Apache Camel?")
+                .post("/openai/chat")
+                .then()
+                .statusCode(200)
+                .body(containsStringIgnoringCase("integration framework"));
+    }
+
+    @Test
+    void chatWithImage() throws IOException {
+        Path path = Paths.get("target/camel-log.png");
+
+        try (InputStream stream = 
OpenaiTest.class.getResourceAsStream("/img/camel-logo.png")) {
+            if (stream == null) {
+                throw new IllegalStateException("Failed loading 
camel-logo.png");
+            }
+
+            try (OutputStream out = new FileOutputStream(path.toFile())) {
+                stream.transferTo(out);
+            }
+
+            RestAssured.given()
+                    .queryParam("userMessage", "Describe what you see in this 
image")
+                    .body("target/camel-log.png")
+                    .post("/openai/chat/image")
+                    .then()
+                    .statusCode(200)
+                    .body(
+                            containsStringIgnoringCase("camel"),
+                            containsStringIgnoringCase("silhouette"),
+                            containsStringIgnoringCase("logo"));
+        } finally {
+            if (FileUtil.isWindows()) {
+                // File may be locked by the Quarkus process, so clean up on 
VM exit
+                path.toFile().deleteOnExit();
+            } else {
+                Files.deleteIfExists(path);
+            }
+        }
+    }
+
+    @Test
+    void chatInitiatedFromFileConsumer() throws IOException {
+        Path prompts = Paths.get("target/prompts");
+        Path prompt = prompts.resolve("whatis-camel-prompt.txt");
+        Files.createDirectories(prompts);
+
+        try (InputStream stream = 
OpenaiTest.class.getResourceAsStream("/prompts/whatis-camel-prompt.txt")) {
+            if (stream == null) {
+                throw new IllegalStateException("Failed loading 
whatis-camel-prompt.txt");
+            }
+
+            try (OutputStream out = new FileOutputStream(prompt.toFile())) {
+                stream.transferTo(out);
+            }
+
+            // Start the file-prompts route
+            RestAssured.given()
+                    .post("/openai/routes/file-prompts/start")
+                    .then()
+                    .statusCode(204);
+
+            
Awaitility.await().pollDelay(Duration.ofSeconds(1)).atMost(Duration.ofMinutes(1)).untilAsserted(()
 -> {
+                RestAssured.given()
+                        .queryParam("endpointUri", "seda:filePromptResults")
+                        .get("/openai/chat/results")
+                        .then()
+                        .statusCode(200)
+                        .body(containsStringIgnoringCase("integration 
framework"));
+            });
+        } finally {
+            // Stop the file-prompts route
+            RestAssured.given()
+                    .post("/openai/routes/file-prompts/stop")
+                    .then()
+                    .statusCode(204);
+
+            if (FileUtil.isWindows()) {
+                // File may be locked by the Quarkus process, so clean up on 
VM exit
+                prompt.toFile().deleteOnExit();
+            } else {
+                Files.deleteIfExists(prompt);
+            }
+        }
+    }
+
+    @Test
+    void chatWithMemory() {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("I am a Camel and my species is Camelus Dromedarius.")
+                .post("/openai/chat/memory")
+                .then()
+                .statusCode(200)
+                .body(containsStringIgnoringCase("Camelus Dromedarius"));
+    }
+
+    @Test
+    void streamingChat() {
+        // Send the streaming request
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("Stream the numbers 1 to 10 on a new line each time and 
nothing else.")
+                .post("/openai/chat/streaming")
+                .then()
+                .statusCode(204);
+
+        // Assert the streamed results
+        Set<String> receivedNumbers = new HashSet<>();
+        Awaitility.await()
+                .atMost(Duration.ofMinutes(1))
+                .pollInterval(Duration.ofMillis(200))
+                .until(() -> {
+                    Response response = RestAssured.given()
+                            .queryParam("endpointUri", 
"seda:chatStreamingResult")
+                            .get("/openai/chat/results");
+
+                    if (response.getStatusCode() == 200) {
+                        String result = response.getBody().asString();
+                        if (result != null && !result.isBlank()) {
+                            receivedNumbers.add(result.trim());
+                        }
+                    }
+                    return receivedNumbers.size() >= 10;
+                });
+
+        Set<String> expectedNumbers = IntStream.rangeClosed(1, 10)
+                .mapToObj(String::valueOf)
+                .collect(Collectors.toSet());
+
+        assertEquals(expectedNumbers, receivedNumbers);
+    }
+
+    @Test
+    void structuredOutputWithSchemaResource() {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("Create an example product description.")
+                .post("/openai/chat/structured/schema")
+                .then()
+                .statusCode(200)
+                .body(
+                        "name", notNullValue(),
+                        "price", greaterThan(0.0F));
+    }
+
+    @Test
+    void structuredOutputWithOutputClass() {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("Create an example product for a product named 
'Bluetooth Headphones'.")
+                .post("/openai/chat/structured/class")
+                .then()
+                .statusCode(200)
+                .body(
+                        "name", is("Bluetooth Headphones"),
+                        "price", greaterThan(0.0F));
+    }
+}
diff --git 
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
 
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
new file mode 100644
index 0000000000..550e3fb992
--- /dev/null
+++ 
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
@@ -0,0 +1,94 @@
+/*
+ * 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.openai.it;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
+import com.github.tomakehurst.wiremock.common.FileSource;
+import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import com.github.tomakehurst.wiremock.extension.Parameters;
+import com.github.tomakehurst.wiremock.extension.StubMappingTransformer;
+import com.github.tomakehurst.wiremock.http.HttpHeader;
+import com.github.tomakehurst.wiremock.http.HttpHeaders;
+import com.github.tomakehurst.wiremock.http.ResponseDefinition;
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
+import com.openai.core.ClientOptions;
+import 
org.apache.camel.quarkus.test.wiremock.WireMockTestResourceLifecycleManager;
+import org.apache.camel.util.ObjectHelper;
+
+public class OpenaiTestResource extends WireMockTestResourceLifecycleManager {
+    private static final String OPENAI_API_URL = ClientOptions.PRODUCTION_URL;
+    private static final String OPENAI_ENV_API_KEY = "OPENAI_API_KEY";
+    private static final String OPENAI_ENV_BASE_URL = "OPENAI_BASE_URL";
+    private static final String OPENAI_ENV_MODEL = "OPENAI_MODEL";
+
+    @Override
+    public Map<String, String> start() {
+        Map<String, String> configuration = super.start();
+        String wiremockUrl = configuration.get("wiremock.url");
+        if (ObjectHelper.isNotEmpty(wiremockUrl)) {
+            configuration.put("camel.component.openai.baseUrl", wiremockUrl);
+        } else {
+            configuration.put("camel.component.openai.baseUrl", 
OPENAI_API_URL);
+        }
+
+        configuration.put("camel.component.openai.model", 
envOrDefault(OPENAI_ENV_MODEL, "gpt-5"));
+        configuration.put("camel.component.openai.apiKey", 
envOrDefault(OPENAI_ENV_API_KEY, "test-key"));
+        return configuration;
+    }
+
+    @Override
+    protected String getRecordTargetBaseUrl() {
+        return envOrDefault(OPENAI_ENV_BASE_URL, OPENAI_API_URL);
+    }
+
+    @Override
+    protected boolean isMockingEnabled() {
+        return !envVarsPresent(OPENAI_ENV_API_KEY);
+    }
+
+    @Override
+    protected void customizeWiremockConfiguration(WireMockConfiguration 
config) {
+        // Removes openai-project header from saved mappings
+        config.extensions(new StubMappingTransformer() {
+            @Override
+            public String getName() {
+                return "camel-quarkus-openai-transformer";
+            }
+
+            @Override
+            public StubMapping transform(StubMapping stubMapping, FileSource 
fileSource, Parameters parameters) {
+                ResponseDefinition original = stubMapping.getResponse();
+                HttpHeaders originalHeaders = original.getHeaders();
+                List<HttpHeader> filteredHeaders = 
originalHeaders.all().stream()
+                        .filter(h -> !h.keyEquals("openai-project"))
+                        .collect(Collectors.toList());
+
+                HttpHeaders newHeaders = new HttpHeaders(filteredHeaders);
+                ResponseDefinition newResponse = 
ResponseDefinitionBuilder.like(original)
+                        .withHeaders(newHeaders)
+                        .build();
+
+                stubMapping.setResponse(newResponse);
+                return stubMapping;
+            }
+        });
+    }
+}
diff --git a/integration-tests/openai/src/test/resources/img/camel-logo.png 
b/integration-tests/openai/src/test/resources/img/camel-logo.png
new file mode 100644
index 0000000000..e5d56708dc
Binary files /dev/null and 
b/integration-tests/openai/src/test/resources/img/camel-logo.png differ
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-371c2c6c-ace6-42bd-ac5d-6214ba9cdceb.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-371c2c6c-ace6-42bd-ac5d-6214ba9cdceb.json
new file mode 100644
index 0000000000..3c9b3bb9fb
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-371c2c6c-ace6-42bd-ac5d-6214ba9cdceb.json
@@ -0,0 +1,46 @@
+{
+  "id" : "371c2c6c-ace6-42bd-ac5d-6214ba9cdceb",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":\"In one sentence, what is 
Apache Camel?\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"temperature\":1.0}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2add3YmiXdwEboHVOpiUIdoDfjbC\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509865,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"Apache 
Camel is an open-source integration framework that implements Enterprise 
Integration Patterns to route, transform, and mediate messages between systems 
using a wide range of connectors and [...]
+    "headers" : {
+      "x-request-id" : "req_9815d7db45994ed687d0e50c1d2c280e",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c479411eb3333fe-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499988",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:08 GMT",
+      "x-ratelimit-reset-tokens" : "1ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=T9eL.pfXGoicZCWWEh3JoIymqHyonP3NQT3ybqP5uJM-1769509868-1.0.1.1-g2IwAYQcOxKWsbEzb7JAeW.eqCmgd9b5OPcIIR2gpybdiMZ9hfcWbci81tG3Y9OKz95.XJYEwHI7EXofta4vzn3Dqb6HwvtJmtUWbtCKaCs;
 path=/; expires=Tue, 27-Jan-26 11:01:08 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=jlzIJcuAOE7EBxWLG.y39y8a2dsoeSRKDgnVZOcJbQc-1769509868234-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "2648",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "application/json"
+    }
+  },
+  "uuid" : "371c2c6c-ace6-42bd-ac5d-6214ba9cdceb",
+  "persistent" : true,
+  "scenarioName" : "scenario-1-chat-completions",
+  "requiredScenarioState" : "Started",
+  "newScenarioState" : "scenario-1-chat-completions-2",
+  "insertionIndex" : 6
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-6424a591-8168-4708-9e85-18266a335435.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-6424a591-8168-4708-9e85-18266a335435.json
new file mode 100644
index 0000000000..1719fedf5a
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-6424a591-8168-4708-9e85-18266a335435.json
@@ -0,0 +1,43 @@
+{
+  "id" : "6424a591-8168-4708-9e85-18266a335435",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":\"Stream the numbers 1 to 
10 on a new line each time and nothing 
else.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"temperature\":1.0,\"stream\":true}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "data: 
{\"id\":\"chatcmpl-D2aeAjgif1gBVAPu9GH45QUEeM595\",\"object\":\"chat.completion.chunk\",\"created\":1769509898,\"model\":\"gpt-5-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"finish_reason\":null}],\"obfuscation\":\"OawGDTE\"}\n\ndata:
 
{\"id\":\"chatcmpl-D2aeAjgif1gBVAPu9GH45QUEeM595\",\"object\":\"chat.completion.chunk\",\"created\":1769509898,\"mo
 [...]
+    "headers" : {
+      "x-request-id" : "req_999fb5204cd840dda154e7ce979d509f",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c4794deaab51179-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499981",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:39 GMT",
+      "x-ratelimit-reset-tokens" : "2ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=FmQ83ZDP77tCY4DWrYu6kHtDgQAtDbHaX9X39W3RA5I-1769509899-1.0.1.1-0gvxDpfDmIUPFkcyK2r6Vw0PR6ZThH5aQb0z__jSaAy4LYoesF7vy_Isp7uHr7y_tlwKjXgvfDAGGizzfdwx5Yjj2Tf05D6NVj.emhrSwfc;
 path=/; expires=Tue, 27-Jan-26 11:01:39 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=vHD0D_Dm6mz2b1mEwlY0Ys8AbDU.LOG17CtwdT860Xc-1769509899926-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "1749",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "text/event-stream; charset=utf-8"
+    }
+  },
+  "uuid" : "6424a591-8168-4708-9e85-18266a335435",
+  "persistent" : true,
+  "insertionIndex" : 2
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-74689f85-f209-4129-b2c8-5e4d38c8eb54.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-74689f85-f209-4129-b2c8-5e4d38c8eb54.json
new file mode 100644
index 0000000000..7d93275d04
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-74689f85-f209-4129-b2c8-5e4d38c8eb54.json
@@ -0,0 +1,43 @@
+{
+  "id" : "74689f85-f209-4129-b2c8-5e4d38c8eb54",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":\"I am a Camel and my 
species is Camelus 
Dromedarius.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"temperature\":1.0}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2acuKCizPKhRtRg7za2XobaULzIZ\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509820,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"Hello, 
noble dromedary (Camelus dromedarius)! The one‑humped desert 
specialist.\\n\\nQuick facts:\\n- Adapted to heat: can lose ~25% body water and 
rehydrate fast (up to ~100 liters).\\n- Hump st [...]
+    "headers" : {
+      "x-request-id" : "req_235a97c40a5946a2b4f47c7cac94fb73",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c4792f3f89ec16b-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499985",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:30:40 GMT",
+      "x-ratelimit-reset-tokens" : "1ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=33byza1OYC15qC511TZS_ytkkbXGjCsihf2Va75m_C8-1769509840-1.0.1.1-sWlxikX3h1CzbG8teJ.NIMKqaY9olMkhsGOwWTdUQ11VE9fnrHXw1pyHz7.VvD_de8N3UMVBNPkCtPBQR9wbiMwCJ.9XvESHkoDQf3RQli0;
 path=/; expires=Tue, 27-Jan-26 11:00:40 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=kpNFQ_OqqCEUnWomGoWgeWYqAfsLVf9zPWIQ5NXN2S4-1769509840956-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "20843",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "application/json"
+    }
+  },
+  "uuid" : "74689f85-f209-4129-b2c8-5e4d38c8eb54",
+  "persistent" : true,
+  "insertionIndex" : 8
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-8454f54f-99d3-46a6-b443-720151e4d73a.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-8454f54f-99d3-46a6-b443-720151e4d73a.json
new file mode 100644
index 0000000000..cad37f5f3e
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-8454f54f-99d3-46a6-b443-720151e4d73a.json
@@ -0,0 +1,46 @@
+{
+  "id" : "8454f54f-99d3-46a6-b443-720151e4d73a",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":[{\"text\":\"Describe what 
you see in this 
image\",\"type\":\"text\"},{\"image_url\":{\"url\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIgAAACACAYAAADQ6SE/AAAKomlDQ1BJQ0MgUHJvZmlsZQAASImVlwdQk9kWx+/3pYeElhA6hN6ktwBSQg+9NxshCRBKDAlBxa4sruBaEBEBRdBVEQXXAogdUWyLgGLXDbKIKOtiQVRU3gcMYXffvPfmnZkz9zf/nHvuuXfu/eYEALIiWyjMghUByBbkiqICvOkJiUl03CsAAQKQBwrAiM0RC5kRESEAsZnx7/bxHhKN2B3LyVz//vt/NSUuT8wBAIpAOIUr5mQjfBLxYY5QlAsAai+iGyzJFU5yO8JUEVI
 [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2ae3F39KqqvDYmRCB8ytK4uivhk8\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509891,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"A 
minimalist logo showing a white camel silhouette inside an orange circle. The 
background has orange and brown shapes resembling desert dunes.\",\n        
\"refusal\": null,\n        \"annotatio [...]
+    "headers" : {
+      "Server" : "cloudflare",
+      "x-ratelimit-reset-input-images" : "1ms",
+      "x-ratelimit-reset-tokens" : "93ms",
+      "x-ratelimit-limit-input-images" : "50000",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-remaining-input-images" : "49999",
+      "Set-Cookie" : [ 
"__cf_bm=zPu326k25_oKkl.tdR0o6S90RsNw8nGm2ksOXYvBjfo-1769509897-1.0.1.1-cKkSZO6QVoyyYzU4QsH2XebZbyXWrXpGgFVAGzALvH1n5vZw0bCGw_W1DQOv8pkRGWIZs9u8SZO2zmihgfjxwJ_1wDsdfpNlrVHh5qC6ES0;
 path=/; expires=Tue, 27-Jan-26 11:01:37 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=tVCs6wDcvX6z0mZeIFCM18FQ4sgbX.5Ie78JUwxAxMY-1769509897907-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "Content-Type" : "application/json",
+      "x-request-id" : "req_53c5adcfb8b049c68382a8ba1ae8f23c",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c4794b6f86fbd74-LHR",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499224",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:37 GMT",
+      "access-control-expose-headers" : "X-Request-ID",
+      "x-ratelimit-limit-requests" : "500",
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "6049",
+      "alt-svc" : "h3=\":443\"; ma=86400"
+    }
+  },
+  "uuid" : "8454f54f-99d3-46a6-b443-720151e4d73a",
+  "persistent" : true,
+  "insertionIndex" : 3
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-9368b026-c5a6-4dc2-ad3a-d34eaa1c149b.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-9368b026-c5a6-4dc2-ad3a-d34eaa1c149b.json
new file mode 100644
index 0000000000..31026d3387
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-9368b026-c5a6-4dc2-ad3a-d34eaa1c149b.json
@@ -0,0 +1,43 @@
+{
+  "id" : "9368b026-c5a6-4dc2-ad3a-d34eaa1c149b",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":\"Create an example product 
description.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"response_format\":{\"json_schema\":{\"name\":\"camel_schema\",\"schema\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"price\":{\"type\":\"number\"}}}},\"type\":\"json_schema\"},\"temperature\":1.0}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2adkRbYAuoCLZFmOSbydHCztd0Jx\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509872,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": 
\"{\\\"name\\\":\\\"Aurora Smart Mug (12 oz, 
Temperature-Controlled)\\\",\\\"price\\\":129.99}\",\n        \"refusal\": 
null,\n        \"annotations\": []\n      },\n      \"finish_reason\": \"stop 
[...]
+    "headers" : {
+      "x-request-id" : "req_c8cd80a34c514cf39a913625256dfb9c",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c479440789735ca-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499988",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:31 GMT",
+      "x-ratelimit-reset-tokens" : "1ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=d0AxkyftuYYziAnrqHz..8QdV9pLr63OWpq5cUnC.7k-1769509891-1.0.1.1-KGITVe8dMxwpFIZC5yByRG51C4L_Mvs81l7kheCwI5Q7oSbeGn8R5L3pHCwkISkMbWHsL4m115KnxUGo1h9kfgUvGUHrcbObZ3wpq0xza.M;
 path=/; expires=Tue, 27-Jan-26 11:01:31 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=nMBpOA30JgxvHJZTVFpzf1SoQBJnneKeAZaEPqHIrTg-1769509891388-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "18380",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "application/json"
+    }
+  },
+  "uuid" : "9368b026-c5a6-4dc2-ad3a-d34eaa1c149b",
+  "persistent" : true,
+  "insertionIndex" : 4
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-e61cd29d-a5ff-42ad-a4de-9975902e0f87.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-e61cd29d-a5ff-42ad-a4de-9975902e0f87.json
new file mode 100644
index 0000000000..b4181c6e27
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-e61cd29d-a5ff-42ad-a4de-9975902e0f87.json
@@ -0,0 +1,45 @@
+{
+  "id" : "e61cd29d-a5ff-42ad-a4de-9975902e0f87",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":\"In one sentence, what is 
Apache Camel?\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"temperature\":1.0}",
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2adh1LgAqGNfZ25hExQ533tA6821\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509869,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"Apache 
Camel is an open-source integration framework that implements Enterprise 
Integration Patterns, providing a lightweight routing and mediation engine with 
a DSL and many components to connec [...]
+    "headers" : {
+      "x-request-id" : "req_fd57ef25ac39465dad43036765d84e03",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c47942b8b1fc418-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499988",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:12 GMT",
+      "x-ratelimit-reset-tokens" : "1ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=ymu_2KZQC_t.c3L3JOAbeixy9wtmC2xyPxxr7APetmw-1769509872-1.0.1.1-rN7ays_witJLb0asu6T5a747LRHyO5hFxHCe7upipi_vI.KVjQ26v8i7jnpXhmFN.j6Uh6mWCRV8Lw9mo58NAhs1mTkYS3KoDvMVFj2krfg;
 path=/; expires=Tue, 27-Jan-26 11:01:12 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=MjSpddawvuLLIbFr1xePQ9B9VzLv1KFPhYOcvPeQYq4-1769509872549-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "2914",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "application/json"
+    }
+  },
+  "uuid" : "e61cd29d-a5ff-42ad-a4de-9975902e0f87",
+  "persistent" : true,
+  "scenarioName" : "scenario-1-chat-completions",
+  "requiredScenarioState" : "scenario-1-chat-completions-2",
+  "insertionIndex" : 5
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-f0e11826-78d1-4bf6-988f-f6d31ae30e0b.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-f0e11826-78d1-4bf6-988f-f6d31ae30e0b.json
new file mode 100644
index 0000000000..dba12c5c4d
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-f0e11826-78d1-4bf6-988f-f6d31ae30e0b.json
@@ -0,0 +1,43 @@
+{
+  "id" : "f0e11826-78d1-4bf6-988f-f6d31ae30e0b",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : 
"{\"messages\":[{\"role\":\"assistant\",\"content\":\"Hello, noble dromedary 
(Camelus dromedarius)! The one‑humped desert specialist.\\n\\nQuick facts:\\n- 
Adapted to heat: can lose ~25% body water and rehydrate fast (up to ~100 
liters).\\n- Hump stores fat for energy; not water.\\n- Three-chambered foregut 
fermenter; eats tough, thorny plants.\\n- Long lashes and closable nostrils 
keep out sand.\\n- Top speed ~65 km/h; good endurance around 40 km/h.\\n- 
Gestation ~ [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2adFTDPvRuxRRcmU1pPQDGGiQxyL\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509841,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"I 
can’t tell without a photo or details, but here’s a quick way to identify 
it—answer these and I’ll confirm:\\n\\n1) How many humps?\\n- One hump → 
Dromedary (Camelus dromedarius)\\n- Two humps  [...]
+    "headers" : {
+      "x-request-id" : "req_3edf3b20977140a2a68d78a29f6307dd",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c47937afc62946b-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499841",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:05 GMT",
+      "x-ratelimit-reset-tokens" : "19ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=nfCEMBx8kR84HbjzNLM4sadXOLDwgVdaOpvzXlaK.8A-1769509865-1.0.1.1-v7K1nUcOBZQ1IWz1eA0rxZEGtUcrt7pfmwHkvwPSCZGofgLjDeLQNAwyAnAt6O73_fz2EVYXMEhEWUc8UPlnWSJLrecbC.CEYtqXKlsXC6Q;
 path=/; expires=Tue, 27-Jan-26 11:01:05 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=Hwb3.ovfE31QNem57HVJNi3IvP9FuaLFzSpTz1ziU2M-1769509865016-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "23727",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "application/json"
+    }
+  },
+  "uuid" : "f0e11826-78d1-4bf6-988f-f6d31ae30e0b",
+  "persistent" : true,
+  "insertionIndex" : 7
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/mappings/chat_completions-fb0a5dd7-0e7c-4aa5-9274-203c032bfac5.json
 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-fb0a5dd7-0e7c-4aa5-9274-203c032bfac5.json
new file mode 100644
index 0000000000..0f80f03477
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/mappings/chat_completions-fb0a5dd7-0e7c-4aa5-9274-203c032bfac5.json
@@ -0,0 +1,43 @@
+{
+  "id" : "fb0a5dd7-0e7c-4aa5-9274-203c032bfac5",
+  "name" : "chat_completions",
+  "request" : {
+    "url" : "/chat/completions",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\"messages\":[{\"content\":\"Create an example product 
for a product named 'Bluetooth 
Headphones'.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"response_format\":{\"json_schema\":{\"name\":\"json-schema-from-Product\",\"schema\":{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"price\":{\"type\":\"number\"}},\"required\":[\"name\",\"price\"],\"additionalProperties\":false},\"strict\":t
 [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : "{\n  \"id\": \"chatcmpl-D2aeDT44NmI7quPk6EKQySXbjfQlS\",\n  
\"object\": \"chat.completion\",\n  \"created\": 1769509901,\n  \"model\": 
\"gpt-5-2025-08-07\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      
\"message\": {\n        \"role\": \"assistant\",\n        \"content\": 
\"{\\\"name\\\":\\\"Bluetooth Headphones\\\",\\\"price\\\":79.99}\",\n        
\"refusal\": null,\n        \"annotations\": []\n      },\n      
\"finish_reason\": \"stop\"\n    }\n  ],\n  \"usage\": [...]
+    "headers" : {
+      "x-request-id" : "req_2e8d1220dad145129e1a39c5c335393b",
+      "x-ratelimit-limit-tokens" : "500000",
+      "openai-organization" : "user-nvrq0gduw4i0ooapnshoh6gw",
+      "CF-RAY" : "9c4794f4aad30c3c-LHR",
+      "Server" : "cloudflare",
+      "X-Content-Type-Options" : "nosniff",
+      "x-ratelimit-reset-requests" : "120ms",
+      "x-openai-proxy-wasm" : "v0.1",
+      "x-ratelimit-remaining-tokens" : "499980",
+      "cf-cache-status" : "DYNAMIC",
+      "x-ratelimit-remaining-requests" : "499",
+      "Date" : "Tue, 27 Jan 2026 10:31:54 GMT",
+      "x-ratelimit-reset-tokens" : "2ms",
+      "access-control-expose-headers" : "X-Request-ID",
+      "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; 
preload",
+      "x-ratelimit-limit-requests" : "500",
+      "Set-Cookie" : [ 
"__cf_bm=_CXULdvnKtnj9mqc9nBMXgAv1ZF0JvPIl2.yqy2x6Ng-1769509914-1.0.1.1-Z.jsxl9BYlVStT0t5pO.eqC96zSPgQ9oUz_urB.d4M9SVnMPyYC8F3A34RyVkw4SQAEg1ECSBfE15qCaAuLTLyh9mAp0Nl18Gx6CNk0lZIg;
 path=/; expires=Tue, 27-Jan-26 11:01:54 GMT; domain=.api.openai.com; HttpOnly; 
Secure; SameSite=None", 
"_cfuvid=2mwBW9xXw_VpeLnnP2tddDnAAab82LNgca4NBHc8Gl8-1769509914516-0.0.1.1-604800000;
 path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None" ],
+      "openai-version" : "2020-10-01",
+      "openai-processing-ms" : "12820",
+      "alt-svc" : "h3=\":443\"; ma=86400",
+      "Content-Type" : "application/json"
+    }
+  },
+  "uuid" : "fb0a5dd7-0e7c-4aa5-9274-203c032bfac5",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git 
a/integration-tests/openai/src/test/resources/prompts/whatis-camel-prompt.txt 
b/integration-tests/openai/src/test/resources/prompts/whatis-camel-prompt.txt
new file mode 100644
index 0000000000..af2a069b25
--- /dev/null
+++ 
b/integration-tests/openai/src/test/resources/prompts/whatis-camel-prompt.txt
@@ -0,0 +1 @@
+In one sentence, what is Apache Camel?
\ No newline at end of file
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 3b69f8d01f..f69ff0e2ce 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -190,6 +190,7 @@
         <module>ognl</module>
         <module>olingo4</module>
         <module>once</module>
+        <module>openai</module>
         <module>openapi-java</module>
         <module>openstack</module>
         <module>opentelemetry</module>
diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml
index cd5a466b2a..1ad268527d 100644
--- a/poms/bom/pom.xml
+++ b/poms/bom/pom.xml
@@ -2400,6 +2400,17 @@
                 <artifactId>camel-once</artifactId>
                 <version>${camel.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-openai</artifactId>
+                <version>${camel.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>io.swagger.core.v3</groupId>
+                        <artifactId>swagger-annotations</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-openapi-java</artifactId>
@@ -5720,6 +5731,16 @@
                 <artifactId>camel-quarkus-once-deployment</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-openai</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-openai-deployment</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
                 <artifactId>camel-quarkus-openapi-java</artifactId>
diff --git a/poms/bom/src/main/generated/flattened-full-pom.xml 
b/poms/bom/src/main/generated/flattened-full-pom.xml
index a6735d2948..6ba6f94950 100644
--- a/poms/bom/src/main/generated/flattened-full-pom.xml
+++ b/poms/bom/src/main/generated/flattened-full-pom.xml
@@ -2316,6 +2316,17 @@
         <artifactId>camel-once</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>4.17.0</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-openai</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.17.0</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <exclusions>
+          <exclusion>
+            <groupId>io.swagger.core.v3</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+            <artifactId>swagger-annotations</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+          </exclusion>
+        </exclusions>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-openapi-java</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -5608,6 +5619,16 @@
         <artifactId>camel-quarkus-once-deployment</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.32.0-SNAPSHOT</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-openai</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.32.0-SNAPSHOT</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-openai-deployment</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.32.0-SNAPSHOT</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-quarkus-openapi-java</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
diff --git a/poms/bom/src/main/generated/flattened-reduced-pom.xml 
b/poms/bom/src/main/generated/flattened-reduced-pom.xml
index 30d11c038b..556e2330f2 100644
--- a/poms/bom/src/main/generated/flattened-reduced-pom.xml
+++ b/poms/bom/src/main/generated/flattened-reduced-pom.xml
@@ -2306,6 +2306,17 @@
         <artifactId>camel-once</artifactId>
         <version>4.17.0</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-openai</artifactId>
+        <version>4.17.0</version>
+        <exclusions>
+          <exclusion>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-annotations</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-openapi-java</artifactId>
@@ -5587,6 +5598,16 @@
         <artifactId>camel-quarkus-once-deployment</artifactId>
         <version>3.32.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-openai</artifactId>
+        <version>3.32.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-openai-deployment</artifactId>
+        <version>3.32.0-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId>
         <artifactId>camel-quarkus-openapi-java</artifactId>
diff --git a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml 
b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
index 7d46431840..0b7706ef5c 100644
--- a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
+++ b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
@@ -2306,6 +2306,17 @@
         <artifactId>camel-once</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>4.17.0</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-openai</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.17.0</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <exclusions>
+          <exclusion>
+            <groupId>io.swagger.core.v3</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+            <artifactId>swagger-annotations</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+          </exclusion>
+        </exclusions>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-openapi-java</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -5587,6 +5598,16 @@
         <artifactId>camel-quarkus-once-deployment</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.32.0-SNAPSHOT</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-openai</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.32.0-SNAPSHOT</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-openai-deployment</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.32.0-SNAPSHOT</version><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-quarkus-openapi-java</artifactId><!-- 
org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
diff --git a/tooling/scripts/test-categories.yaml 
b/tooling/scripts/test-categories.yaml
index 57ea78b9ad..c3dcb50302 100644
--- a/tooling/scripts/test-categories.yaml
+++ b/tooling/scripts/test-categories.yaml
@@ -136,6 +136,7 @@ group-07:
   - lumberjack
   - ognl
   - olingo4
+  - openai
   - optaplanner
   - pg-replication-slot
   - splunk-hec

Reply via email to