OpenAiChatModel
A ChatModel that calls a model through the Chat Completions API of OpenAI. Many other servers have the same API, among them Ollama, LM Studio, vLLM, Groq and OpenRouter, so this one class reaches the models of OpenAI and models that run on your own machine. It is built on Ktor, so it runs on every Kotlin target.
val client = HttpClient()
// OpenAI
val model = OpenAiChatModel(client, apiKey = System.getenv("OPENAI_API_KEY"), model = "gpt-5")
// A model of Ollama on this machine. It needs no key.
val local = OpenAiChatModel.ollama(client, model = "llama3.2")
// Any other server with this API: give the address that ends before "/chat/completions".
val hosted = OpenAiChatModel(client, apiKey = key, model = "llama-3.3-70b-versatile", baseUrl = "https://api.groq.com/openai/v1")
val agent = toolAgent(model, tools = listOf(forecast))HttpClient() uses the Ktor engine among your dependencies, for example ktor-client-okhttp on Android, ktor-client-darwin on iOS or ktor-client-js in a browser. The client is yours: share one between models, and close it when your app is done with it.
A call may take five minutes, whatever limits the client and its engine have: the CIO engine, for one, ends a request after 15 seconds. Change the limit with timeout.
chat returns when the model has finished, and stream delivers the text while the model writes it. A toolAgent uses stream when its run is collected with stream. What a server wants back unchanged with a tool call, such as a thought signature of Gemini, travels in ChatMessage.Assistant.providerContent.
Tools need a model that can call them. A small local model may answer in text where a larger one would call a tool.
Never ship an app that contains a key of yours: a key in an app can be read by everyone who has the app. Send the requests through a server of your own, or let each user enter their key.
Parameters
the Ktor client that sends the requests.
the key, sent as a bearer token. null for a server that needs none.
the id of the model, for example gpt-5.
more fields for the body of every request, such as temperature, max_completion_tokens, reasoning_effort or tool_choice. A field given here replaces the one this class would send.
more headers for every request, such as OpenAI-Organization.
where the API lives, up to and including the version: this class adds /chat/completions to it.
how long one call may take, from the request to the end of the answer, and how long it may wait for the next piece of the answer. It replaces the limits of client and of its engine for the requests of this model. null leaves those limits in place.
Throws
if timeout is not positive.
Constructors
Functions
Sends request to the Chat Completions API and returns the model's answer.