Skip to main content

Model Gateway - Chat

The ModelGatewayService lets you send chat completions to any third-party model (OpenAI, Anthropic, and others) available through the IBM watsonx.ai Model Gateway.

Setup required: The Model Gateway must be installed and configured by an administrator before use. See Model Gateway Prerequisites.

Quick Start

ModelGatewayService service = ModelGatewayService.builder()
.baseUrl(CloudRegion.DALLAS)
.apiKey(WATSONX_API_KEY)
.modelId("gpt-4o")
.build();

ModelGatewayChatResponse response = service.chat("What is the capital of Italy?");
System.out.println(response.toAssistantMessage().content());
// → Rome is the capital of Italy.

Overview

ModelGatewayService enables you to:

  • Send synchronous and streaming chat requests to any model available through the gateway.
  • Use gateway-specific parameters such as service tier, reasoning effort, audio modalities, caching, and routing configuration.
  • Apply MessageInterceptor and ToolInterceptor for post-processing.
  • Read gateway metadata on every response: serviceTier(), systemFingerprint(), and cached().

Service Configuration

Basic Setup

ModelGatewayService service = ModelGatewayService.builder()
.baseUrl(CloudRegion.DALLAS)
.apiKey(WATSONX_API_KEY)
.modelId("gpt-4o")
.build();

Builder Parameters

ParameterTypeRequiredDescription
apiKeyStringConditionalAPI key for IBM Cloud authentication
authenticatorAuthenticatorConditionalCustom authentication (alternative to apiKey)
baseUrlString / CloudRegionYeswatsonx.ai ML endpoint
modelIdStringYesThird-party model identifier (e.g., "gpt-4o", "claude-3-5-sonnet")
parametersModelGatewayParametersNoDefault parameters applied to every request
toolsList<Tool>NoDefault tools available to the model
messageInterceptorMessageInterceptor<ModelGatewayChatRequest>NoPost-processing hook for the assistant's text content
toolInterceptorToolInterceptor<ModelGatewayChatRequest>NoPost-processing hook for function call arguments
timeoutDurationNoDefault request timeout (default: 60 seconds)
logRequestsBooleanNoEnable request logging (default: false)
logResponsesBooleanNoEnable response logging (default: false)
httpClientHttpClientNoCustom HTTP client
verifySslBooleanNoSSL certificate verification (default: true)
versionStringNoAPI version override

Either apiKey or authenticator must be provided.

Advanced Configuration

Set default parameters and tools that apply to every request:

ModelGatewayParameters defaults = ModelGatewayParameters.builder()
.temperature(0.7)
.maxCompletionTokens(1000)
.serviceTier(ServiceTier.AUTO)
.build();

ModelGatewayService service = ModelGatewayService.builder()
.baseUrl(CloudRegion.DALLAS)
.apiKey(WATSONX_API_KEY)
.modelId("gpt-4o")
.parameters(defaults)
.build();

Per-request parameters always take precedence over service-level defaults. Fields not set on the per-request parameters fall back to the defaults.


Chat operations

Simple Chat

ModelGatewayChatResponse response = service.chat("Tell me a joke");
System.out.println(response.toAssistantMessage().content());

Multi-Turn Conversation

var messages = new ArrayList<ChatMessage>();
messages.add(SystemMessage.of("You are a helpful assistant"));
messages.add(UserMessage.text("What is the capital of France?"));

ModelGatewayChatResponse response = service.chat(messages);
messages.add(response.toAssistantMessage());

messages.add(UserMessage.text("What is its population?"));
response = service.chat(messages);
System.out.println(response.toAssistantMessage().content());

With Parameters

ModelGatewayParameters parameters = ModelGatewayParameters.builder()
.temperature(0.3)
.maxCompletionTokens(200)
.build();

ModelGatewayChatResponse response = service.chat(messages, parameters);

With Tools

Tool weatherTool = Tool.of(
"get_weather",
"Get current weather for a location",
JsonSchema.object()
.property("location", JsonSchema.string("City name"))
.required("location")
.build()
);

ModelGatewayChatResponse response = service.chat(messages, parameters, List.of(weatherTool));
AssistantMessage assistant = response.toAssistantMessage();

if (assistant.hasToolCalls()) {
List<ToolMessage> toolMessages = assistant.processTools((name, args) -> {
return fetchWeather(args.get("location"));
});
messages.add(assistant);
messages.addAll(toolMessages);
response = service.chat(messages);
}

System.out.println(response.toAssistantMessage().content());

Streaming

Simple Streaming

CompletableFuture<ChatResponse> future = service.chatStreaming(
"Tell me a story",
System.out::print
);
future.join();

Streaming with ChatHandler

service.chatStreaming(
messages,
new ChatHandler() {
@Override
public void onPartialResponse(String text, PartialChatResponse partial) {
System.out.print(text);
}

@Override
public void onCompleteResponse(ChatResponse response) {
System.out.println("\nTotal tokens: " + response.usage().totalTokens());
}

@Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}
}
);

Model Gateway Parameters

ModelGatewayParameters extends the common BaseChatParameters with fields specific to the Model Gateway.

Builder Reference

Inherited from BaseChatParameters

ParameterTypeRangeDescription
modelIdString-Override the model for this request
maxCompletionTokensInteger≥ 0Maximum tokens in the response. 0 is treated as a literal zero - it does not mean "model max" as it does for ChatService and DeploymentService.
temperatureDouble0.0 – 2.0Sampling randomness (0.0 = deterministic)
topPDouble0.0 – 1.0Nucleus sampling threshold
frequencyPenaltyDouble-2.0 – 2.0Discourage frequent tokens
presencePenaltyDouble-2.0 – 2.0Encourage new topics
stopList<String>Max 4Stop sequences to end generation
seedIntegerAnyRandom seed for reproducibility
nInteger≥ 1Number of completions to generate
logprobsBoolean-Return log probabilities
topLogprobsInteger≥ 1Top token log probs (requires logprobs=true)
logitBiasMap<String, Integer>-Adjust token probabilities
timeLimitDurationAnyMaximum generation time
toolChoiceOptionToolChoiceOptionAUTO, REQUIRED, NONETool selection strategy
toolChoiceStringTool nameForce a specific tool call
responseFormat--Use responseAsText(), responseAsJson(), responseAsJsonSchema()
transactionIdString-Request tracking ID

Gateway-only

ParameterTypeDescription
serviceTierServiceTier / StringLatency tier: AUTO, DEFAULT, FLEX, PRIORITY
reasoningEffortReasoningEffort / StringReasoning budget for reasoning models: LOW, MEDIUM, HIGH
parallelToolCallsBooleanEnable or disable parallel function calls during tool use
modalitiesList<String>Requested output modalities, e.g. ["text"], ["text","audio"]
audioMap<String, String>Audio output parameters
metadataMap<String, String>Developer-defined tags for filtering completions
storeBooleanStore output for model distillation or evals
predictionPredictionPredicted-output configuration for generation speed-up
streamOptionsStreamOptionsStreaming options (auto-set when streaming is active)
routerRouterRouting and cache configuration
userStringEnd-user identifier for abuse monitoring

Service Tier

Controls the latency and resource class for a request:

ModelGatewayParameters.builder()
.serviceTier(ServiceTier.AUTO) // let the gateway choose
.serviceTier(ServiceTier.FLEX) // flexible, variable latency
.serviceTier(ServiceTier.PRIORITY) // lower latency tier
.build();

Reasoning Effort

For reasoning models (e.g., o3, o1), controls how many internal reasoning steps the model uses:

ModelGatewayParameters.builder()
.reasoningEffort(ReasoningEffort.HIGH)
.build();

Accepted values: LOW, MEDIUM, HIGH.

Router and Caching

The Router record wraps a Cache configuration. Caching is only honored for non-streaming requests:

ModelGatewayParameters.builder()
.router(new Router(
new Cache(
true, // enabled
null, // no filter
0.95 // similarity threshold for a cache hit
)
))
.build();

When a cached response is returned, ModelGatewayChatResponse.cached() is true.


Gateway Response

ModelGatewayChatResponse extends TextChatResponse (which itself extends ChatResponse) and adds three gateway-specific fields:

MethodTypeDescription
serviceTier()StringTier actually used to serve the request
systemFingerprint()StringBackend snapshot identifier - changes indicate a backend update that may affect determinism
cached()Booleantrue if the response was served from the semantic cache
ModelGatewayChatResponse response = service.chat("Hello");

System.out.println("Content: " + response.toAssistantMessage().content());
System.out.println("Service tier: " + response.serviceTier());
System.out.println("Fingerprint: " + response.systemFingerprint());
System.out.println("Cached: " + response.cached());
System.out.println("Total tokens: " + response.usage().totalTokens());

Interceptors

Interceptors work identically to how they work in ChatService - see the Chat Service - Interceptors section for the full description of MessageInterceptor, ToolInterceptor, and InterceptorContext.

ModelGatewayService service = ModelGatewayService.builder()
.baseUrl(CloudRegion.DALLAS)
.apiKey(WATSONX_API_KEY)
.modelId("gpt-4o")
.messageInterceptor((ctx, message) -> message == null ? "" : message.strip())
.toolInterceptor((ctx, functionCall) -> {
var args = functionCall.arguments();
return args != null && args.startsWith("\"")
? functionCall.withArguments(Json.fromJson(args, String.class))
: functionCall;
})
.build();