watsonx.ai
This integration is built on top of the IBM watsonx.ai Java SDK. Every model described below wraps one of its services. When you need details on a behavior that is not specific to LangChain4j - token caching, retries, HTTP client tuning - the SDK documentation is the reference.
Maven Dependency
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-watsonx</artifactId>
<version>1.23.0-beta33</version>
</dependency>
Authentication
Watsonx.ai supports authentication via the Authenticator interface.
This allows you to use different authentication mechanisms depending on your deployment:
- IBMCloudAuthenticator – authenticates with IBM Cloud using an API key. This is the simplest approach and is used when you provide the
apiKey(...)builder method. - CP4DAuthenticator – authenticates with Cloud Pak for Data deployments.
- Custom authenticators – any implementation of the
Authenticatorinterface can be used.
The WatsonxChatModel, WatsonxStreamingChatModel, and other service builders accept either a shortcut via .apiKey(...) or a full Authenticator instance via .authenticator(...).
Token caching and renewal are handled transparently. A token is fetched on the first request, cached, and refreshed before it expires, so you never manage its lifecycle. Passing the same Authenticator instance to several models lets them share a single cached token. See the SDK authentication guide for the full list of authenticators and their parameters.
Example
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.watsonx.WatsonxChatModel;
import com.ibm.watsonx.ai.core.auth.cp4d.CP4DAuthenticator;
import com.ibm.watsonx.ai.core.auth.cp4d.AuthMode;
import com.ibm.watsonx.ai.CloudRegion;
WatsonxChatModel.builder()
.baseUrl(CloudRegion.FRANKFURT)
.apiKey("your-api-key") // Simple IBM Cloud authentication
.projectId("your-project-id")
.modelName("ibm/granite-4-h-small")
.build();
WatsonxChatModel.builder()
.baseUrl("https://my-instance-url")
.authenticator( // For Cloud Pak for Data deployments
CP4DAuthenticator.builder()
.baseUrl("https://my-instance-url")
.username("username")
.apiKey("api-key")
.authMode(AuthMode.LEGACY)
.build()
)
.projectId("my-project-id")
.modelName("ibm/granite-4-h-small")
.build();
Custom HttpClient and SSL Configuration
Using a custom HttpClient
All services and authenticators support a custom HttpClient instance through the builder pattern. This is particularly useful for Cloud Pak for Data environments where you may need to configure custom TLS/SSL settings, proxy configuration, or other HTTP client properties.
HttpClient httpClient = HttpClient.newBuilder()
.sslContext(createCustomSSLContext())
.executor(ExecutorProvider.ioExecutor())
.build();
EmbeddingModel embeddingModel = WatsonxEmbeddingModel.builder()
.baseUrl("https://my-instance-url")
.modelName("ibm/granite-embedding-278m-multilingual")
.projectId("project-id")
.httpClient(httpClient) // Custom HttpClient
.authenticator(
CP4DAuthenticator.builder()
.baseUrl("https://my-instance-url")
.username("username")
.apiKey("api-key")
.httpClient(httpClient) // Custom HttpClient
.build()
)
.build();
Note: When using a custom
HttpClientwith Cloud Pak for Data, make sure to set it on both the service builder and the authenticator builder to ensure consistent HTTP behavior across all requests.
🔗 SDK guide to the HTTP client, including how to build an
SSLContextfrom a private truststore.
Disabling SSL verification
If you only need to disable SSL certificate verification, you can use the verifySsl(false) option instead of providing a custom HttpClient:
EmbeddingModel embeddingModel = WatsonxEmbeddingModel.builder()
.baseUrl("https://my-instance-url")
.modelName("ibm/granite-embedding-278m-multilingual")
.projectId("project-id")
.verifySsl(false) // Disable SSL verification
.authenticator(
CP4DAuthenticator.builder()
.baseUrl("https://my-instance-url")
.username("username")
.apiKey("api-key")
.verifySsl(false) // Disable SSL verification
.build()
)
.build();
How to create an IBM Cloud API Key
You can create an API key at https://cloud.ibm.com/iam/apikeys by clicking Create +.
How to find your Project ID
- Visit https://dataplatform.cloud.ibm.com/projects/?context=wx
- Open your project
- Go to the Manage tab
- Copy the Project ID from the Details section
WatsonxChatModel
The WatsonxChatModel class allows you to create an instance of the ChatModel interface fully encapsulated within LangChain4j.
To create an instance, you must specify the mandatory parameters:
baseUrl(...)– IBM Cloud endpoint URL (asString,URI, orCloudRegion)apiKey(...)– IBM Cloud IAM API keyprojectId(...)– IBM Cloud Project ID (or usespaceId(...))modelName(...)– Foundation model ID for inference
You can authenticate using either
.apiKey(...)or a fullAuthenticatorinstance via.authenticator(...).
To call a model you have deployed on-demand, use
WatsonxDeploymentChatModelinstead.
Example
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.watsonx.WatsonxChatModel;
import com.ibm.watsonx.ai.CloudRegion;
ChatModel chatModel = WatsonxChatModel.builder()
.baseUrl(CloudRegion.FRANKFURT)
.apiKey("your-api-key")
.projectId("your-project-id")
.modelName("ibm/granite-4-h-small")
.temperature(0.7)
.maxOutputTokens(0)
.build();
String answer = chatModel.chat("Hello from watsonx.ai");
System.out.println(answer);
WatsonxStreamingChatModel
The WatsonxStreamingChatModel provides streaming support for IBM watsonx.ai within LangChain4j. It's useful when you want to process tokens as they are generated, ideal for real-time applications such as chat UIs or long text generation.
Streaming uses the same configuration structure and parameters as the non-streaming WatsonxChatModel. The main difference is that responses are delivered incrementally through a handler interface.
To call a model you have deployed on-demand, use
WatsonxDeploymentStreamingChatModelinstead.
Example
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.chat.StreamingChatResponseHandler;
import dev.langchain4j.model.chat.ChatResponse;
import dev.langchain4j.model.watsonx.WatsonxStreamingChatModel;
import com.ibm.watsonx.ai.CloudRegion;
StreamingChatModel model = WatsonxStreamingChatModel.builder()
.baseUrl(CloudRegion.FRANKFURT)
.apiKey("your-api-key")
.projectId("your-project-id")
.modelName("ibm/granite-4-h-small")
.maxOutputTokens(0)
.build();
model.chat("What is the capital of Italy?", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
System.out.println("Partial: " + partialResponse);
}
@Override
public void onCompleteResponse(ChatResponse completeResponse) {
System.out.println("Complete: " + completeResponse);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});
Deployed models (on-demand deployment)
IBM watsonx.ai allows you to deploy foundation models on-demand on dedicated hardware for exclusive use by your organization. These deployed models are addressed by their deploymentId and are served by a different watsonx.ai endpoint than the foundation-model catalog, so LangChain4j exposes them through their own pair of classes, WatsonxDeploymentChatModel and WatsonxDeploymentStreamingChatModel.
To create an instance, you must specify:
baseUrl(...)– IBM Cloud endpoint URL (asString,URI, orCloudRegion)apiKey(...)– IBM Cloud IAM API keydeploymentId(...)– Deployment ID of the on-demand deployed model
A deployment already targets a specific model within a project or space, so these builders expose neither modelName(...) nor projectId(...)/spaceId(...). Every other generation parameter (temperature, maxOutputTokens, thinking, tools, responseFormat, …) works exactly as it does on WatsonxChatModel.
Note:
deploymentIdis a connection-level setting fixed when the model is built - it selects the deployment endpoint, so it cannot be overridden per request throughWatsonxChatRequestParameters.
WatsonxDeploymentChatModel
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.watsonx.WatsonxDeploymentChatModel;
import com.ibm.watsonx.ai.CloudRegion;
ChatModel chatModel = WatsonxDeploymentChatModel.builder()
.baseUrl(CloudRegion.FRANKFURT)
.apiKey("your-api-key")
.deploymentId("your-deployment-id")
.temperature(0.7)
.maxOutputTokens(0)
.build();
String answer = chatModel.chat("Hello from watsonx.ai");
System.out.println(answer);
WatsonxDeploymentStreamingChatModel
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.chat.StreamingChatResponseHandler;
import dev.langchain4j.model.chat.ChatResponse;
import dev.langchain4j.model.watsonx.WatsonxDeploymentStreamingChatModel;
import com.ibm.watsonx.ai.CloudRegion;
StreamingChatModel model = WatsonxDeploymentStreamingChatModel.builder()
.baseUrl(CloudRegion.FRANKFURT)
.apiKey("your-api-key")
.deploymentId("your-deployment-id")
.maxOutputTokens(0)
.build();
model.chat("What is the capital of Italy?", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
System.out.println("Partial: " + partialResponse);
}
@Override
public void onCompleteResponse(ChatResponse completeResponse) {
System.out.println("Complete: " + completeResponse);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});
Model Gateway
The IBM watsonx.ai Model Gateway exposes an OpenAI-compatible chat endpoint that can route requests to models hosted by multiple providers (for example OpenAI, Anthropic, or third-party providers you register) behind a single watsonx.ai entry point. LangChain4j integrates with it through WatsonxGatewayChatModel and WatsonxGatewayStreamingChatModel.
Note: the gateway must be configured by an administrator before use - each
modelNameyou pass must be an id already registered in the gateway.