From 8470e7649c00df7b92d7ecba883fa100e554ee06 Mon Sep 17 00:00:00 2001
From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com>
Date: Fri, 24 Apr 2026 12:27:50 +0000
Subject: [PATCH 1/4] Initial plan
From 88af79cbc60efc0e77f20724264571fc67a1a5d6 Mon Sep 17 00:00:00 2001
From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com>
Date: Fri, 24 Apr 2026 12:32:10 +0000
Subject: [PATCH 2/4] feat: Add Mistral AI provider configuration and factory
implementation
Agent-Logs-Url: https://github.com/camunda/connectors/sessions/18d0503b-96c1-4358-9761-e6057ccb1f3b
Co-authored-by: mathieu-stennier <1794533+mathieu-stennier@users.noreply.github.com>
---
connectors/agentic-ai/pom.xml | 4 +
.../langchain4j/ChatModelFactoryImpl.java | 28 ++++
.../MistralProviderConfiguration.java | 127 ++++++++++++++++++
.../provider/ProviderConfiguration.java | 3 +
4 files changed, 162 insertions(+)
create mode 100644 connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/MistralProviderConfiguration.java
diff --git a/connectors/agentic-ai/pom.xml b/connectors/agentic-ai/pom.xml
index 2a18f444760..a8b2b58f2fb 100644
--- a/connectors/agentic-ai/pom.xml
+++ b/connectors/agentic-ai/pom.xml
@@ -124,6 +124,10 @@
dev.langchain4j
langchain4j-open-ai
+
+ dev.langchain4j
+ langchain4j-mistral-ai
+
dev.langchain4j
langchain4j-vertex-ai-gemini
diff --git a/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryImpl.java b/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryImpl.java
index a648cfb17ce..bc3fe5067b5 100644
--- a/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryImpl.java
+++ b/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryImpl.java
@@ -13,6 +13,7 @@
import dev.langchain4j.model.bedrock.BedrockChatModel;
import dev.langchain4j.model.bedrock.BedrockChatRequestParameters;
import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.mistralai.MistralAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatRequestParameters;
import dev.langchain4j.model.vertexai.gemini.VertexAiGeminiChatModel;
@@ -24,6 +25,7 @@
import io.camunda.connector.agenticai.aiagent.model.request.provider.BedrockProviderConfiguration;
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration;
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiAuthentication.ServiceAccountCredentialsAuthentication;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OpenAiCompatibleAuthentication;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiProviderConfiguration;
@@ -69,6 +71,7 @@ public ChatModel createChatModel(ProviderConfiguration providerConfiguration) {
case BedrockProviderConfiguration bedrock -> createBedrockChatModelBuilder(bedrock).build();
case GoogleVertexAiProviderConfiguration vertexAi ->
createGoogleVertexAiChatModelBuilder(vertexAi).build();
+ case MistralProviderConfiguration mistral -> createMistralChatModelBuilder(mistral).build();
case OpenAiProviderConfiguration openai -> createOpenaiChatModelBuilder(openai).build();
case OpenAiCompatibleProviderConfiguration openaiCompatible ->
createOpenaiCompatibleChatModelBuilder(openaiCompatible).build();
@@ -260,6 +263,31 @@ protected OpenAiChatModel.OpenAiChatModelBuilder createOpenaiChatModelBuilder(
return builder;
}
+ protected MistralAiChatModel.MistralAiChatModelBuilder createMistralChatModelBuilder(
+ MistralProviderConfiguration configuration) {
+ final var connection = configuration.mistral();
+
+ final var builder =
+ MistralAiChatModel.builder()
+ .apiKey(connection.authentication().apiKey())
+ .modelName(connection.model().model())
+ .timeout(deriveTimeoutSetting(connection.timeouts()))
+ .httpClientBuilder(proxySupport.createJdkHttpClientBuilder());
+
+ Optional.ofNullable(connection.endpoint()).ifPresent(builder::baseUrl);
+
+ final var modelParameters = connection.model().parameters();
+ if (modelParameters != null) {
+ Optional.ofNullable(modelParameters.maxTokens()).ifPresent(builder::maxTokens);
+ Optional.ofNullable(modelParameters.temperature()).ifPresent(builder::temperature);
+ Optional.ofNullable(modelParameters.topP()).ifPresent(builder::topP);
+ Optional.ofNullable(modelParameters.safePrompt()).ifPresent(builder::safePrompt);
+ Optional.ofNullable(modelParameters.randomSeed()).ifPresent(builder::randomSeed);
+ }
+
+ return builder;
+ }
+
protected OpenAiChatModel.OpenAiChatModelBuilder createOpenaiCompatibleChatModelBuilder(
OpenAiCompatibleProviderConfiguration configuration) {
final var connection = configuration.openaiCompatible();
diff --git a/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/MistralProviderConfiguration.java b/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/MistralProviderConfiguration.java
new file mode 100644
index 00000000000..80e8c553f1c
--- /dev/null
+++ b/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/MistralProviderConfiguration.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
+ * under one or more contributor license agreements. Licensed under a proprietary license.
+ * See the License.txt file for more information. You may not use this file
+ * except in compliance with the proprietary license.
+ */
+package io.camunda.connector.agenticai.aiagent.model.request.provider;
+
+import static io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MISTRAL_ID;
+
+import io.camunda.connector.agenticai.aiagent.model.request.provider.shared.HttpUrl;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.shared.TimeoutConfiguration;
+import io.camunda.connector.generator.java.annotation.FeelMode;
+import io.camunda.connector.generator.java.annotation.TemplateProperty;
+import io.camunda.connector.generator.java.annotation.TemplateSubType;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+@TemplateSubType(id = MISTRAL_ID, label = "Mistral AI")
+public record MistralProviderConfiguration(@Valid @NotNull MistralConnection mistral)
+ implements ProviderConfiguration {
+
+ @TemplateProperty(ignore = true)
+ public static final String MISTRAL_ID = "mistral";
+
+ public record MistralConnection(
+ @HttpUrl
+ @TemplateProperty(
+ group = "provider",
+ label = "Base URL",
+ description =
+ "The Mistral API base URL. Default: https://api.mistral.ai/v1",
+ type = TemplateProperty.PropertyType.String,
+ feel = FeelMode.optional,
+ defaultValue = "https://api.mistral.ai/v1",
+ defaultValueType = TemplateProperty.DefaultValueType.String,
+ optional = true)
+ String endpoint,
+ @Valid @NotNull MistralAuthentication authentication,
+ @Valid TimeoutConfiguration timeouts,
+ @Valid @NotNull MistralModel model) {}
+
+ public record MistralAuthentication(
+ @NotBlank
+ @TemplateProperty(
+ group = "provider",
+ label = "Mistral API key",
+ type = TemplateProperty.PropertyType.String,
+ feel = FeelMode.optional,
+ constraints = @TemplateProperty.PropertyConstraints(notEmpty = true))
+ String apiKey) {
+
+ @Override
+ public String toString() {
+ return "MistralAuthentication{apiKey=[REDACTED]}";
+ }
+ }
+
+ public record MistralModel(
+ @NotBlank
+ @TemplateProperty(
+ group = "model",
+ label = "Model",
+ description =
+ "Specify the model ID. Popular models: mistral-large-latest, mistral-small-latest, mistral-medium-latest, codestral-latest, open-mistral-nemo, pixtral-large-latest. Details in the documentation.",
+ type = TemplateProperty.PropertyType.String,
+ feel = FeelMode.optional,
+ defaultValue = "mistral-large-latest",
+ defaultValueType = TemplateProperty.DefaultValueType.String,
+ constraints = @TemplateProperty.PropertyConstraints(notEmpty = true))
+ String model,
+ @Valid MistralModel.MistralModelParameters parameters) {
+
+ public record MistralModelParameters(
+ @Min(0)
+ @TemplateProperty(
+ group = "model",
+ label = "Maximum tokens",
+ tooltip =
+ "The maximum number of tokens to generate in the completion.
Details in the documentation.",
+ type = TemplateProperty.PropertyType.Number,
+ feel = FeelMode.required,
+ optional = true)
+ Integer maxTokens,
+ @Min(0)
+ @TemplateProperty(
+ group = "model",
+ label = "Temperature",
+ tooltip =
+ "What sampling temperature to use, between 0.0 and 1.0. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
Details in the documentation.",
+ type = TemplateProperty.PropertyType.Number,
+ feel = FeelMode.required,
+ optional = true)
+ Double temperature,
+ @Min(0)
+ @TemplateProperty(
+ group = "model",
+ label = "top P",
+ tooltip =
+ "Nucleus sampling probability. Recommended for advanced use cases only (you usually only need to use temperature).
Details in the documentation.",
+ type = TemplateProperty.PropertyType.Number,
+ feel = FeelMode.required,
+ optional = true)
+ Double topP,
+ @TemplateProperty(
+ group = "model",
+ label = "Safe prompt",
+ tooltip =
+ "Whether to inject a safety prompt before all conversations.
Details in the documentation.",
+ type = TemplateProperty.PropertyType.Boolean,
+ feel = FeelMode.optional,
+ optional = true)
+ Boolean safePrompt,
+ @Min(0)
+ @TemplateProperty(
+ group = "model",
+ label = "Random seed",
+ tooltip =
+ "The seed to use for random sampling. If set, different calls will generate deterministic results.
Details in the documentation.",
+ type = TemplateProperty.PropertyType.Number,
+ feel = FeelMode.required,
+ optional = true)
+ Integer randomSeed) {}
+ }
+}
diff --git a/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/ProviderConfiguration.java b/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/ProviderConfiguration.java
index 098b0bece37..0fe3ac53692 100644
--- a/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/ProviderConfiguration.java
+++ b/connectors/agentic-ai/src/main/java/io/camunda/connector/agenticai/aiagent/model/request/provider/ProviderConfiguration.java
@@ -10,6 +10,7 @@
import static io.camunda.connector.agenticai.aiagent.model.request.provider.AzureOpenAiProviderConfiguration.AZURE_OPENAI_ID;
import static io.camunda.connector.agenticai.aiagent.model.request.provider.BedrockProviderConfiguration.BEDROCK_ID;
import static io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GOOGLE_VERTEX_AI_ID;
+import static io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MISTRAL_ID;
import static io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OPENAI_COMPATIBLE_ID;
import static io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiProviderConfiguration.OPENAI_ID;
@@ -23,6 +24,7 @@
@JsonSubTypes.Type(value = BedrockProviderConfiguration.class, name = BEDROCK_ID),
@JsonSubTypes.Type(value = AzureOpenAiProviderConfiguration.class, name = AZURE_OPENAI_ID),
@JsonSubTypes.Type(value = GoogleVertexAiProviderConfiguration.class, name = GOOGLE_VERTEX_AI_ID),
+ @JsonSubTypes.Type(value = MistralProviderConfiguration.class, name = MISTRAL_ID),
@JsonSubTypes.Type(value = OpenAiProviderConfiguration.class, name = OPENAI_ID),
@JsonSubTypes.Type(
value = OpenAiCompatibleProviderConfiguration.class,
@@ -39,5 +41,6 @@ public sealed interface ProviderConfiguration
BedrockProviderConfiguration,
AzureOpenAiProviderConfiguration,
GoogleVertexAiProviderConfiguration,
+ MistralProviderConfiguration,
OpenAiProviderConfiguration,
OpenAiCompatibleProviderConfiguration {}
From 3561bb6f0da41eb276a2b45c684f86d01a6276ea Mon Sep 17 00:00:00 2001
From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com>
Date: Fri, 24 Apr 2026 12:34:06 +0000
Subject: [PATCH 3/4] test: Add Mistral provider configuration and factory
tests
Agent-Logs-Url: https://github.com/camunda/connectors/sessions/18d0503b-96c1-4358-9761-e6057ccb1f3b
Co-authored-by: mathieu-stennier <1794533+mathieu-stennier@users.noreply.github.com>
---
.../langchain4j/ChatModelFactoryTest.java | 137 ++++++++++++++++++
.../request/ProviderConfigurationTest.java | 48 ++++++
2 files changed, 185 insertions(+)
diff --git a/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryTest.java b/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryTest.java
index be7c5348d2a..50c4468e876 100644
--- a/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryTest.java
+++ b/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/framework/langchain4j/ChatModelFactoryTest.java
@@ -32,6 +32,8 @@
import dev.langchain4j.model.bedrock.BedrockChatModel;
import dev.langchain4j.model.bedrock.BedrockChatRequestParameters;
import dev.langchain4j.model.chat.request.ChatRequestParameters;
+import dev.langchain4j.model.mistralai.MistralAiChatModel;
+import dev.langchain4j.model.mistralai.MistralAiChatModel.MistralAiChatModelBuilder;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel.OpenAiChatModelBuilder;
import dev.langchain4j.model.openai.OpenAiChatRequestParameters;
@@ -58,6 +60,11 @@
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiConnection;
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiModel;
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiModel.GoogleVertexAiModelParameters;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralAuthentication;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralConnection;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralModel;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralModel.MistralModelParameters;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OpenAiCompatibleConnection;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OpenAiCompatibleModel.OpenAiCompatibleModelParameters;
@@ -868,6 +875,136 @@ static Stream nullModelParameters() {
}
}
+ @Nested
+ class MistralChatModelFactoryTest {
+
+ private static final String MISTRAL_API_KEY = "mistralApiKey";
+ private static final String MISTRAL_MODEL = "mistral-large-latest";
+ private static final String CUSTOM_ENDPOINT = "https://mistral.custom.local/v1";
+
+ private static final MistralModelParameters DEFAULT_MODEL_PARAMETERS =
+ new MistralModelParameters(1000, 0.7, 0.9, true, 42);
+
+ @Test
+ void createsMistralChatModel() {
+ final var providerConfig =
+ new MistralProviderConfiguration(
+ new MistralConnection(
+ null,
+ new MistralAuthentication(MISTRAL_API_KEY),
+ MODEL_TIMEOUT,
+ new MistralModel(MISTRAL_MODEL, DEFAULT_MODEL_PARAMETERS)));
+
+ testMistralChatModelBuilder(
+ providerConfig,
+ (builder) -> {
+ verify(builder).timeout(MODEL_TIMEOUT.timeout());
+ verify(builder).apiKey(MISTRAL_API_KEY);
+ verify(builder).modelName(MISTRAL_MODEL);
+ verify(builder, never()).baseUrl(any());
+ verify(builder).maxTokens(DEFAULT_MODEL_PARAMETERS.maxTokens());
+ verify(builder).temperature(DEFAULT_MODEL_PARAMETERS.temperature());
+ verify(builder).topP(DEFAULT_MODEL_PARAMETERS.topP());
+ verify(builder).safePrompt(DEFAULT_MODEL_PARAMETERS.safePrompt());
+ verify(builder).randomSeed(DEFAULT_MODEL_PARAMETERS.randomSeed());
+ });
+ }
+
+ @Test
+ void createsMistralChatModelWithCustomEndpoint() {
+ final var providerConfig =
+ new MistralProviderConfiguration(
+ new MistralConnection(
+ CUSTOM_ENDPOINT,
+ new MistralAuthentication(MISTRAL_API_KEY),
+ MODEL_TIMEOUT,
+ new MistralModel(MISTRAL_MODEL, DEFAULT_MODEL_PARAMETERS)));
+
+ testMistralChatModelBuilder(
+ providerConfig,
+ (builder) -> {
+ verify(builder).timeout(MODEL_TIMEOUT.timeout());
+ verify(builder).apiKey(MISTRAL_API_KEY);
+ verify(builder).modelName(MISTRAL_MODEL);
+ verify(builder).baseUrl(CUSTOM_ENDPOINT);
+ verify(builder).maxTokens(DEFAULT_MODEL_PARAMETERS.maxTokens());
+ verify(builder).temperature(DEFAULT_MODEL_PARAMETERS.temperature());
+ verify(builder).topP(DEFAULT_MODEL_PARAMETERS.topP());
+ verify(builder).safePrompt(DEFAULT_MODEL_PARAMETERS.safePrompt());
+ verify(builder).randomSeed(DEFAULT_MODEL_PARAMETERS.randomSeed());
+ });
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "io.camunda.connector.agenticai.aiagent.framework.langchain4j.ChatModelFactoryTest#defaultTimeoutYieldingConfigs")
+ void shouldUseDefaultTimeout(TimeoutConfiguration timeoutConfiguration) {
+ final var providerConfig =
+ new MistralProviderConfiguration(
+ new MistralConnection(
+ null,
+ new MistralAuthentication(MISTRAL_API_KEY),
+ timeoutConfiguration,
+ new MistralModel(MISTRAL_MODEL, DEFAULT_MODEL_PARAMETERS)));
+
+ testMistralChatModelBuilder(
+ providerConfig,
+ (builder) -> {
+ verify(builder)
+ .timeout(createDefaultConfigurationProperties().aiagent().chatModel().api().defaultTimeout());
+ });
+ }
+
+ @ParameterizedTest
+ @MethodSource("nullModelParameters")
+ void shouldHandleNullModelParameters(MistralModelParameters modelParameters) {
+ final var providerConfig =
+ new MistralProviderConfiguration(
+ new MistralConnection(
+ null,
+ new MistralAuthentication(MISTRAL_API_KEY),
+ MODEL_TIMEOUT,
+ new MistralModel(MISTRAL_MODEL, modelParameters)));
+
+ testMistralChatModelBuilder(
+ providerConfig,
+ (builder) -> {
+ verify(builder).timeout(MODEL_TIMEOUT.timeout());
+ verify(builder).apiKey(MISTRAL_API_KEY);
+ verify(builder).modelName(MISTRAL_MODEL);
+ verify(builder, never()).maxTokens(anyInt());
+ verify(builder, never()).temperature(anyDouble());
+ verify(builder, never()).topP(anyDouble());
+ verify(builder, never()).safePrompt(any());
+ verify(builder, never()).randomSeed(anyInt());
+ });
+ }
+
+ private void testMistralChatModelBuilder(
+ MistralProviderConfiguration providerConfig,
+ ThrowingConsumer builderAssertions) {
+ final var chatModelBuilder = spy(MistralAiChatModel.builder());
+ final var chatModelResultCaptor = new ResultCaptor();
+ doAnswer(chatModelResultCaptor).when(chatModelBuilder).build();
+
+ try (MockedStatic chatModelMock =
+ mockStatic(MistralAiChatModel.class, Answers.CALLS_REAL_METHODS)) {
+ chatModelMock.when(MistralAiChatModel::builder).thenReturn(chatModelBuilder);
+
+ final var chatModel = chatModelFactory.createChatModel(providerConfig);
+ assertThat(chatModel).isNotNull().isInstanceOf(MistralAiChatModel.class);
+ assertThat(chatModel).isSameAs(chatModelResultCaptor.getResult());
+
+ verify(proxySupport).createJdkHttpClientBuilder();
+ builderAssertions.accept(chatModelBuilder);
+ }
+ }
+
+ static Stream nullModelParameters() {
+ return Stream.of(new MistralModelParameters(null, null, null, null, null));
+ }
+ }
+
@Nested
class OpenAiCompatibleChatModelFactoryTest {
diff --git a/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/model/request/ProviderConfigurationTest.java b/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/model/request/ProviderConfigurationTest.java
index cde2d8a156d..dbc3ec52321 100644
--- a/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/model/request/ProviderConfigurationTest.java
+++ b/connectors/agentic-ai/src/test/java/io/camunda/connector/agenticai/aiagent/model/request/ProviderConfigurationTest.java
@@ -24,6 +24,9 @@
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiConnection;
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiModel;
import io.camunda.connector.agenticai.aiagent.model.request.provider.GoogleVertexAiProviderConfiguration.GoogleVertexAiModel.GoogleVertexAiModelParameters;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralAuthentication;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralConnection;
+import io.camunda.connector.agenticai.aiagent.model.request.provider.MistralProviderConfiguration.MistralModel;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OpenAiCompatibleAuthentication;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OpenAiCompatibleConnection;
import io.camunda.connector.agenticai.aiagent.model.request.provider.OpenAiCompatibleProviderConfiguration.OpenAiCompatibleModel;
@@ -321,6 +324,51 @@ private static GoogleVertexAiConnection createConnectionWithServiceAccountCreden
}
}
+ @Nested
+ class MistralConnectionTest {
+
+ @ParameterizedTest
+ @MethodSource(
+ "io.camunda.connector.agenticai.aiagent.model.request.ProviderConfigurationTest#validHttpUrls")
+ void shouldAcceptValidEndpoint(String endpoint) {
+ var connection =
+ new MistralConnection(
+ endpoint,
+ new MistralAuthentication("key"),
+ TIMEOUT,
+ new MistralModel("mistral-large-latest", null));
+ assertThat(validator.validate(connection)).isEmpty();
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "io.camunda.connector.agenticai.aiagent.model.request.ProviderConfigurationTest#invalidHttpUrls")
+ void shouldRejectInvalidUrlEndpoint(String endpoint) {
+ var connection =
+ new MistralConnection(
+ endpoint,
+ new MistralAuthentication("key"),
+ TIMEOUT,
+ new MistralModel("mistral-large-latest", null));
+ assertThat(validator.validate(connection))
+ .extracting(ConstraintViolation::getMessage)
+ .contains(HTTP_URL_VALIDATION_MESSAGE);
+ }
+
+ @ParameterizedTest
+ @NullSource
+ void shouldAcceptNullEndpoint(String endpoint) {
+ // Null endpoint is allowed for Mistral (defaults to https://api.mistral.ai/v1)
+ var connection =
+ new MistralConnection(
+ endpoint,
+ new MistralAuthentication("key"),
+ TIMEOUT,
+ new MistralModel("mistral-large-latest", null));
+ assertThat(validator.validate(connection)).isEmpty();
+ }
+ }
+
@Nested
class AgentCoreMemoryConfigurationTest {
From 0d5cefc727fdacceb8ea8af98dd1b9903895f1b3 Mon Sep 17 00:00:00 2001
From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com>
Date: Fri, 24 Apr 2026 12:58:24 +0000
Subject: [PATCH 4/4] docs: Add element template generation instructions for
Mistral provider
Agent-Logs-Url: https://github.com/camunda/connectors/sessions/db95f3ec-7aef-42b9-ab45-cccee72c0c5c
Co-authored-by: mathieu-stennier <1794533+mathieu-stennier@users.noreply.github.com>
---
ELEMENT_TEMPLATE_GENERATION.md | 64 ++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 ELEMENT_TEMPLATE_GENERATION.md
diff --git a/ELEMENT_TEMPLATE_GENERATION.md b/ELEMENT_TEMPLATE_GENERATION.md
new file mode 100644
index 00000000000..109657797e8
--- /dev/null
+++ b/ELEMENT_TEMPLATE_GENERATION.md
@@ -0,0 +1,64 @@
+# Element Template Generation Instructions
+
+## Issue
+The Mistral AI provider configuration was added to the code, but the element templates were not regenerated to include it in the UI dropdown.
+
+## Solution
+
+The element templates are automatically generated from Java annotations using the `element-template-generator-maven-plugin`. To regenerate them after adding a new provider:
+
+### Step 1: Generate Element Templates
+
+Run the following Maven command from the root of the repository:
+
+```bash
+mvn clean compile io.camunda.connector:element-template-generator-maven-plugin:generate-templates -pl connectors/agentic-ai
+```
+
+Or run a full build which will trigger the generator:
+
+```bash
+mvn clean install -DskipTests
+```
+
+### Step 2: Verify the Changes
+
+After generation, check that the element templates in `connectors/agentic-ai/element-templates/` include Mistral AI:
+
+1. **agenticai-aiagent-outbound-connector.json** - Should include "Mistral AI" in the provider dropdown
+2. **agenticai-aiagent-job-worker.json** - Should be updated by the Groovy transform script
+3. **hybrid/agenticai-aiagent-outbound-connector-hybrid.json** - Should include Mistral AI
+
+### Step 3: Verify Provider Configuration
+
+The generated template should include:
+- Mistral AI in the provider dropdown choices
+- Conditional properties for Mistral configuration:
+ - `provider.mistral.endpoint` (optional base URL)
+ - `provider.mistral.authentication.apiKey` (required API key)
+ - `provider.mistral.model.model` (required model name)
+ - `provider.mistral.model.parameters.maxTokens` (optional)
+ - `provider.mistral.model.parameters.temperature` (optional)
+ - `provider.mistral.model.parameters.topP` (optional)
+ - `provider.mistral.model.parameters.safePrompt` (optional)
+ - `provider.mistral.model.parameters.randomSeed` (optional)
+
+### What Was Added
+
+The following files were modified to support Mistral AI:
+
+1. **MistralProviderConfiguration.java** - New provider configuration with `@TemplateProperty` annotations
+2. **ProviderConfiguration.java** - Added Mistral to the sealed interface and `@JsonSubTypes`
+3. **ChatModelFactoryImpl.java** - Added `createMistralChatModelBuilder()` method
+4. **pom.xml** - Added `langchain4j-mistral-ai` dependency
+
+All the necessary annotations are in place (`@TemplateSubType`, `@TemplateProperty`, etc.), so the plugin should automatically generate the correct element template entries.
+
+## Why This is Needed
+
+The element template generator reads the Java annotations on the provider configuration classes and generates JSON element templates that:
+1. Add provider options to dropdowns in the Camunda Modeler
+2. Define conditional properties that appear when a provider is selected
+3. Set up proper data bindings for the BPMN process variables
+
+Without regenerating the templates, users won't see "Mistral AI" as an option in the provider dropdown, even though the backend code fully supports it.