This is a no-nonsense async Scala client for OpenAI API and multiple LLM providers supporting all the available endpoints and params including streaming (with a provider-neutral typed stream of text / thinking / tool-call / tool-result chunks), chat completion, responses API, agents API, tools (including MCP), graders, vision (with provider-uniform file/image attachments), batch processing, and voice routines (as defined here), provided in a single, convenient service called OpenAIService with adapters for Anthropic (incl. Bedrock and Managed Agents), Google Gemini/Vertex AI, Groq, Perplexity (incl. its decision model), TypeSafe AI (Jev), Liquid AI (d1), Microsoft Foundry (Microsoft-Decision-1), SubQ (SubQ Snap), ScaleDown (Classify), the decision models on OpenRouter and Vercel AI Gateway, and others. The supported calls are:
- Models: listModels, and retrieveModel
- Completions: createCompletion (deprecated on
OpenAIService- OpenAI shuts down its last completions models on 2026-09-28; OpenAI-compatible servers keep it viaOpenAICoreService) - Chat Completions: createChatCompletion, createChatFunCompletion (deprecated), createChatToolCompletion, and createChatWebSearchCompletion
- Edits: createEdit (deprecated - the endpoint is gone)
- Images: createImage, createImageEdit, and createImageVariation (deprecated - the endpoint is gone with dall-e-2; defaults now use
gpt-image-2) - Embeddings: createEmbeddings
- Batches: createBatch, retrieveBatch, cancelBatch, and listBatches, plus the helpers
uploadBatchFile,buildAndUploadBatchFile,buildBatchFileContent,retrieveBatchFile,retrieveBatchFileContent, andretrieveBatchResponses - Audio: createAudioTranscription, createAudioTranslation (deprecated - whisper-1, its only model, shuts down 2027-02-26), and createAudioSpeech
- Files: listFiles, uploadFile, deleteFile, retrieveFile, retrieveFileContent, and
retrieveFileContentAsSource(streamed) - Fine-tunes: createFineTune, listFineTunes, retrieveFineTune, cancelFineTune, listFineTuneEvents, listFineTuneCheckpoints, and deleteFineTuneModel
- Moderations: createModeration
⚠️ Assistants, Threads, Thread Messages, Runs and Run Steps are deprecated since 1.4.0 - OpenAI shut the Assistants API down on 2026-08-26; use the Responses API (createModelResponse/createModelResponseStreamed) instead- Assistants: createAssistant, listAssistants, retrieveAssistant, modifyAssistant, deleteAssistant, and
deleteAssistantFile - Threads: createThread, retrieveThread, modifyThread, and deleteThread
- Thread Messages: createThreadMessage, retrieveThreadMessage, modifyThreadMessage, listThreadMessages, retrieveThreadMessageFile, listThreadMessageFiles, and deleteThreadMessage
- Runs: createRun, createThreadAndRun, listRuns, retrieveRun, modifyRun, submitToolOutputs, and cancelRun
- Run Steps: listRunSteps, and retrieveRunStep
- Vector Stores: createVectorStore, listVectorStores, retrieveVectorStore, modifyVectorStore, and deleteVectorStore
- Vector Store Files: createVectorStoreFile, listVectorStoreFiles, retrieveVectorStoreFile, and deleteVectorStoreFile
- Responses: createModelResponse (with tools support), getModelResponse, deleteModelResponse, cancelModelResponse, getModelResponseInputTokenCounts, listModelResponseInputItems, and createModelResponseStreamed (typed events or
ChatChunks) - Graders: runGrader, and validateGrader
The Anthropic client additionally covers the native Messages (incl. typed stream events), Message Batches, Files, Skills, and the whole Managed Agents API surface (agents, environments and their work queue, sessions, deployments, vaults and credentials, memory stores) - see the Anthropic Managed Agents page.
Note that in order to be consistent with the OpenAI API naming, the service function names match exactly the API endpoint titles/descriptions in camelCase.
Also, we aimed for the library to be self-contained with the fewest dependencies possible. Therefore, we implemented our own generic WS client (currently with Play WS backend, which can be swapped for other engines in the future). Additionally, if dependency injection is required, we use the scala-guice library.
👉 No time to read a lengthy tutorial? Sure, we hear you! Check out the examples to see how to use the lib in practice.
👉 Follow @0xbnd on X for release announcements and LLM provider news.
In addition to OpenAI, this library supports many other LLM providers. For providers that aren't natively compatible with the chat completion API, we've implemented adapters to streamline integration (see examples).
| Provider | Structured output | Tools | Batch | Notes |
|---|---|---|---|---|
| OpenAI | Full | Yes, Responses API too | Yes | Full API support; GPT-6.1 Terra 🔥 |
| Azure OpenAI | Full | Yes, Responses API too | Yes | OpenAI on Azure |
| Anthropic | Full | Yes, MCP and Skills too | Yes | Claude models |
| Anthropic Bedrock | Full | Yes, MCP too | Yes ¹ | Claude on AWS |
| OpenAI Bedrock | Full | Yes, Responses API too | – | GPT-5.x, gpt-oss, Grok and more on AWS ² |
| Azure AI | Varies | – | – | Open-source models |
| Cerebras | Full ³ | Yes | – | Fast inference |
| Deepseek | JSON object mode only | – | – | Chinese provider; deepseek-flash is V4.1 Flash 1017 |
| FastChat | Varies | – | – | Local LLMs |
| Fireworks AI | Full | – | – | Cloud provider |
| Google Gemini | Full | Yes | Yes | Google's models; the URL context tool 🔥 |
| Google Vertex AI | Full | Yes | Yes | Gemini models; the global, EU and US endpoints 🔥 |
| Grok | Full | Yes | – | x.AI models |
| Groq | Full ³ | Yes, MCP and server-side tools too | Yes | Fast inference |
| Meta Model API | Full ⁶ | Yes | – | Muse Wonder, Muse Spark (open weights: Muse Spark Open on Together, Fireworks, OpenRouter, Vercel) ⁶ |
| MiniMax | Varies ⁴ | – | – | Chinese provider (global and China); MiniMax-M3.1-Flash 🔥 |
| Mistral | Full | – | – | Open-source leader |
| Novita | Model-dependent | – | – | Cloud provider |
| Octo AI | JSON object mode only | – | – | Cloud provider (obsolete) |
| Ollama | Varies | – | – | Local LLMs |
| OpenRouter | Model-dependent | Model-dependent | – | provider/model ids, e.g. meta/muse-wonder |
| Perplexity | Implied only | – | – | Agent API ⁵ |
| TogetherAI | Model-dependent | – | – | Cloud provider |
| Vercel AI Gateway | Model-dependent | Model-dependent | – | provider/model ids, e.g. meta/muse-spark-open |
¹ No prompt caching in batches.
² Through bedrock-mantle or bedrock-runtime.
³ Cerebras: gpt-oss-120b, qwen-3.8-27b; Groq: openai/gpt-oss-*, qwen/qwen3.x-27b.
⁴ JSON-object mode: M3 / M3.1-Flash accept strict json_schema but do not enforce it (live 2026-11-02).
⁵ Perplexity's Sonar chat completions retired on 2026-09-27 (see Services and providers).
⁶ ChatProviderSettings.meta (MODEL_API_KEY); Muse Wonder (2026-10-12) and Muse Spark live-verified with strict json_schema, tools and streams (see Services and providers).
🔥 New in 1.7.0.
Decision models give typed answers with calibrated probabilities. Two APIs serve them - TypeSafe AI's System One
(TypeSafeService.systemOne: Jev, Liquid's d1, Perplexity's decider, Microsoft-Decision-1, SubQ Snap, ScaleDown's Classify, Sarvam Prism, Bespoke's Nimble, OpenRouter, Vercel AI Gateway, llama.cpp) and OpenAI's Decisions API
(OpenAIService.createDecision: gpt-6-luna) - and the client speaks either interface to either host: asOpenAIDecisions
puts OpenAI's interface on a System One host, DecisionProviderSettings.openAI runs the System One routines (typed
decisions, re-ranking, the json_schema-only chat adapter) on OpenAI's. No tools or batch. See
Decision models.
| Provider | Models | Factory method |
|---|---|---|
| TypeSafe AI | Jev; images, bounding boxes (Jev 1.14) and long context (the factory's default 🔥) - experimental | asOpenAI() |
| Liquid AI | d1.1 (the default) 🔥, d1, images too; d1-ultra | liquidAsOpenAI() |
| llama.cpp (local) | Liquid's Open d1 (d1-3B, d1-omni-600M) once llama.cpp loads them; Julia-1, Laya, Lev, Kev, OpenJev, Nimble, Clef | asOpenAI(DecisionProviderSettings.llamaCpp) |
| Perplexity Decisions | pplx-decider-v1.2 and the 4B pplx-decider-flash-v1.2, v1.1-27b / v1-27b; images too | perplexityAsOpenAI() |
| OpenRouter | Jev, d1, Perplexity's deciders, OpenAI's Luna, Microsoft-Decision-1, Cloudflare's Clef (+ Flash, Omni), Solar Decide, Mercury Decide, Tev1, Kev 4B, NACE's Drex, Span-01, ScaleDown's Classify-1, Jev 1.14, d1-ultra, Span-02; d1.1, Baseten's Elephant-1 / Mammoth-1 and NACE's Drex Max 🔥; images too | asOpenAI(DecisionProviderSettings.openRouter) |
| OpenAI Decisions | gpt-6-luna, images too | asOpenAI(DecisionProviderSettings.openAI) |
| Vercel AI Gateway | Jev, d1 (images too), Microsoft-Decision-1, OpenAI's Luna; on the free tier Convai's Laya and ScaleDown's Classify-1, also Baseten's Elephant-1 / Mammoth-1, d1-ultra and Perplexity's v1.2 deciders 🔥 | asOpenAI(DecisionProviderSettings.vercel) |
| SubQ | SubQ Snap 1.1 (the default) 🔥 and Snap Preview (public preview; long context - 295,957 input tokens, up to 4 images) | asOpenAI(DecisionProviderSettings.subq) |
| Sarvam 🔥 | Sarvam Prism (English, ten Indian languages and Hinglish) | asOpenAI(DecisionProviderSettings.sarvam) |
| Bespoke Labs 🔥 | Nimble (nimble-latest = Nimble v4 Max, 27B; text only, at most 64 questions) |
asOpenAI(DecisionProviderSettings.bespoke) |
| ScaleDown | Classify (a constrained decoding model; text plus one document, 1M context) | asOpenAI(DecisionProviderSettings.scaleDown) |
| Microsoft Foundry | Microsoft-Decision-1 (public preview; your own deployment in a Foundry resource) | microsoftFoundryAsOpenAI() |
🔥 New in 1.7.0.
👉 For background information how the project started read an article about the lib/client on Medium.
✔️ Important: this is a "community-maintained" library and, as such, has no relation to OpenAI company.
The currently supported Scala versions are 2.12, 2.13, and 3.
To install the library, add the following dependency to your build.sbt
"io.cequence" %% "openai-scala-client" % "1.6.0"
or to pom.xml (if you use maven)
<dependency>
<groupId>io.cequence</groupId>
<artifactId>openai-scala-client_2.12</artifactId>
<version>1.6.0</version>
</dependency>
If you want streaming support, use "io.cequence" %% "openai-scala-client-stream" % "1.6.0" instead.
For a single dependency that includes all provider clients (Anthropic, Gemini, Vertex AI, Perplexity, TypeSafe AI, token counting):
"io.cequence" %% "openai-scala-all" % "1.6.0"
- Env. variables:
OPENAI_SCALA_CLIENT_API_KEYand optionally alsoOPENAI_SCALA_CLIENT_ORG_ID(if you have one) - File config (default): openai-scala-client.conf
- Streams: one frame (a server-sent event or JSON line) may take up to 32 MiB - a generated image in base64 arrives in one
event. Change the cap with
openai-scala-client.streaming.maxFrameLength(e.g.128 MiB) or the env. variableOPENAI_SCALA_CLIENT_STREAM_MAX_FRAME_LENGTH; a larger frame fails the stream with an exception naming both the setting and the variable (see the FAQ).
import io.cequence.openaiscala.domain._
import io.cequence.openaiscala.domain.settings.CreateChatCompletionSettings
import io.cequence.openaiscala.service.OpenAIServiceFactory
import scala.concurrent.ExecutionContext.Implicits.global
val service = OpenAIServiceFactory() // the key from OPENAI_SCALA_CLIENT_API_KEY
service
.createChatCompletion(
Seq(UserMessage("What is the capital of Norway? One word.")),
CreateChatCompletionSettings(model = ModelId.gpt_5_4_mini)
)
.map(response => println(response.contentHead))
.andThen { case _ => service.close() } // close a service when done with it - it owns an HTTP pool and an actor systemEvery provider in the tables above is reached the same way - through its factory's asOpenAI() (or
OpenAIChatCompletionServiceFactory(ChatProviderSettings.<provider>)), after which the calls, adapters and streams are the
same. See Services and providers.
| Page | What it covers |
|---|---|
| Services and providers | Factories, config and keys; every provider's adapter - Azure, Anthropic and Bedrock, Gemini and Vertex AI, Mistral, Groq, Grok, Cerebras, DeepSeek, Perplexity, Liquid AI, any OpenAI-compatible endpoint |
| Chat completions | Calls, JSON / structured output (schemas from case classes), failover, tools, reasoning effort, files and images |
| Responses API | Inputs and images, file / web search, function calls, MCP, multi-agent execution |
| Agents API | Durable cloud agents (beta): sessions, events, the chat adapter |
| Streaming | OpenAI-shaped and typed streams (ChatChunk), the frame cap, human approval mid-stream |
| Decision models | OpenAI's Decisions API, TypeSafe (Jev), Liquid (d1), Perplexity's decider, Microsoft-Decision-1, SubQ Snap, ScaleDown's Classify, Sarvam Prism, Bespoke's Nimble, OpenRouter, Vercel AI Gateway, llama.cpp; either API on either host, typed decisions, re-ranking, the models' execution time side by side |
| Adapters | Round robin, retry, logging, routing, batch processing, interception, guardrails |
| Sharing an HTTP engine | One engine for many services and providers; timeouts and proxies |
| Graders API | Evaluating model outputs |
| Anthropic Managed Agents | Server-hosted agents with tool-permission pauses |
| Claude Agent Client | The claude CLI as a subprocess transport |
| FAQ | Timeouts, errors, the stream frame cap, ... |
Ready-to-run examples for everything above are in openai-examples; the release notes are in CHANGELOG.md.
This library is available and published as open source under the terms of the MIT License.
This project is open-source and welcomes any contribution or feedback (here).
Development of this library has been supported by - Cequence.io -
The future of contracting
Created and maintained by Peter Banda (on X here).