1.0 Scope

This page states which parts of the LLM4S API are safe to build on ahead of a 1.0 freeze.

Until 0.4.1 all of it shipped in one core Maven artifact of roughly 84k lines — agent runtime, RAG, MCP, speech, image, knowledge graph, and eleven provider clients together. There was no way to tell from the artifact alone which parts of that surface are meant to be a long-term contract and which are still moving fast.

This page describes the target state of the in-progress modularisation programme tracked in #1126. Rows marked carved below already live in their target module; every other row still ships inside llm4s-core, and its target-module column says where it is heading, not where it lives today.

What has actually moved so far, in the build but not yet in a release:

Slice Modules carved Status
1 llm4s-rag, llm4s-knowledgegraph in the build, unpublished
2 llm4s-memory, llm4s-memory-postgres in the build, unpublished
3 llm4s-mcp, llm4s-media, llm4s-image, llm4s-speech in the build, unpublished
4 none - the provider registration SPI (ProviderDescriptor, discovered through META-INF/services) that slice 5’s modules register through in the build, unpublished
5 llm4s-ollama, llm4s-gemini, llm4s-anthropic, llm4s-openai, llm4s-openai-compatible (with Mistral and Cohere), llm4s-voyage - llm4s-core now holds no provider client in the build, unpublished
6 llm4s-observability (Langfuse, the trace collector, CostTracker); OpenTelemetryConfig joins the existing llm4s-observability-otel; llm4s-observability-prometheus (Prometheus). The tracing and metrics contracts stay in llm4s-core, which declares no observability dependency in the build, unpublished
7 llm4s-agent-tools (the built-in tools and their config), llm4s-agent (agent, assistant) in the build, unpublished

The latest release tag is v0.4.1, which is still a single llm4s-core (0.4.0 was the artifact rename only, #1141). The first release to publish separate module artifacts will be 0.5.0, in slice 8 (#1281); it is also the MiMa baseline. Until it is published nothing is frozen: “Frozen at 1.0” is the tier a module will hold, not a constraint on changing it now.

Maturity Legend

These definitions are shared with the Roadmap so the two pages agree.

Status Meaning
Frozen at 1.0 Source and binary compatible within the 1.x series once published under its target module. This is the compatibility promise 1.0 makes.
Beta Implemented and usable, but API, provider behavior, or docs still need hardening before v1.0.
Experimental Useful prototype or advanced feature; expect changes.
Planned Roadmap item, design, issue, or PR queue item; not a stable user contract.

Package Map

Every top-level package under modules/core/src/main/scala/org/llm4s/, its target module, and its tier.

Package Target module Tier
types llm4s-core Frozen at 1.0
error llm4s-core Frozen at 1.0
config llm4s-core Frozen at 1.0
model llm4s-core Frozen at 1.0
toolapi — the tool API: ToolFunction, ToolRegistry, schemas, execution llm4s-core Frozen at 1.0
toolapi/builtin, toolapi/tools — the built-in tools (core utilities, filesystem, HTTP, shell, Brave/DuckDuckGo/Exa search) and ToolsConfigLoader — carved llm4s-agent-tools Beta
context llm4s-core Frozen at 1.0
util llm4s-core Frozen at 1.0
syntax llm4s-core Frozen at 1.0
identity llm4s-core Frozen at 1.0
resource llm4s-core Frozen at 1.0
core llm4s-core Frozen at 1.0
http llm4s-core Frozen at 1.0
security llm4s-core Frozen at 1.0
llmconnect (API only — see provider split below) llm4s-core Frozen at 1.0
reliability llm4s-core Frozen at 1.0
agent (excludes agent/memory) — carved llm4s-agent Frozen at 1.0
assistant — carved llm4s-agent Beta
trace — the contract: Tracing, TraceEvent, TracingComposer, TracingMode, the trace/spi TracingBackend SPI, NoOpTracing, ConsoleTracing, and TracingSettings (in llmconnect/config) llm4s-core Frozen at 1.0
metrics — the contract: MetricsCollector llm4s-core Frozen at 1.0
trace — Langfuse (LangfuseTracing, its batch sender and TracingBackend), TraceCollectorTracing, trace/model, trace/store; metrics — CostTracker — carved llm4s-observability Beta
trace — OpenTelemetry (OpenTelemetryTracing, OpenTelemetryConfig) — carved llm4s-observability-otel (modules/trace-opentelemetry) Beta
metrics — Prometheus (PrometheusMetrics, PrometheusEndpoint, MetricsConfigLoader) — carved llm4s-observability-prometheus Beta
metrics — Micrometer (MicrometerMetrics), a MetricsCollector over a MeterRegistry — new llm4s-observability-micrometer Beta
llmconnect/provider — OpenAI, Azure and Requesty (the providers sharing OpenAIClient) — carved llm4s-openai Frozen at 1.0
llmconnect/provider — OpenRouter, DeepSeek, Z.ai and the generic openai-compatible provider, on one SDK-free OpenAICompatibleClient — carved llm4s-openai-compatible Frozen at 1.0
llmconnect/provider — Anthropic — carved llm4s-anthropic Frozen at 1.0
llmconnect/provider — Gemini (and Vertex AI) — carved llm4s-gemini Frozen at 1.0
llmconnect/provider — Ollama — carved llm4s-ollama Frozen at 1.0
llmconnect/provider — Mistral and Cohere, as dialects on OpenAICompatibleClient — carved llm4s-openai-compatible Beta
llmconnect/provider — Voyage AI embeddings — carved llm4s-voyage (modules/providers/voyage) Beta
llmconnect/provider — AWS Bedrock (Converse, ConverseStream) — new llm4s-bedrock (modules/providers/bedrock) Beta
llmconnect/provider — Jina AI embeddings — new llm4s-jina (modules/providers/jina) Beta
llmconnect/provider — Cohere embeddings, on Cohere’s native /v2/embed (Cohere chat is a dialect in llm4s-openai-compatible) — new llm4s-cohere (modules/providers/cohere) Beta
llmconnect/provider — IBM watsonx.ai, on the chat endpoints (never run against the live service: verification against it is still open in #1314) — new llm4s-watsonx (modules/providers/watsonx) Beta
llmconnect/provider — other community providers llm4s-openai-compatible dialects, or modules/providers/<name> Beta
jev — typed client for TypeSafe’s Jev decision model (Noul, Choice, Score); not a chat provider — new llm4s-jev (modules/providers/jev) Beta
testkit — the checks a provider module’s Llm4s<Name>ModuleSpec makes (ProviderModuleChecks, ProviderTestConfig, CredentialsRoundTrip, LocalProviderTestServer), formerly unpublished helpers in core’s test sources — new llm4s-provider-testkit (modules/provider-testkit), a test-scope dependency; requires JDK 21 (virtual threads) Beta
agent/graph/sqlite — SqliteCheckpointer, the first durable Checkpointer: threads, events and run claims in one SQLite file that survives a restart and that several processes on one host can share — new llm4s-agent-checkpoint-sqlite (modules/agent-checkpoint-sqlite); carries the SQLite JDBC driver Beta
schema — SchemaOf, a JSON schema derived from a case class with derives, and completeStructuredOf; builds core’s ObjectSchema and adds no dependency (Map, recursive types and sealed hierarchies with fields are refused at compile time; a recursion through a hand-written given that derives its type fails on first use) — new llm4s-schema-derivation (modules/schema-derivation) Experimental
testkit — a scriptable fake LLMClient for the tests of code that uses llm4s (ScriptedLLMClient, Reply, RecordedCall, UnscriptedCallError) — new llm4s-testkit (modules/testkit), a test-scope dependency Beta
agent/testkit — CheckpointerContract, the contract every Checkpointer must pass (commits, event numbering, compaction, run-claim leases and fencing, two runtimes over one store), and ManualClock — new llm4s-agent-testkit (modules/agent-testkit), a test-scope dependency; requires JDK 21 (virtual threads) Beta
build — the bill of materials that pins every published artifact to one version (no code) — new llm4s-bom (modules/bom) Beta
rag, vectorstore, chunking, reranker, eval — carved llm4s-rag Beta
extract (consolidated from rag/extract + llmconnect/extractors) and rag/embed (from llmconnect/encoding) — carved llm4s-rag Beta
agent/memory (excluding PostgresMemoryStore) — carved llm4s-memory Beta
agent/memory/PostgresMemoryStore — carved llm4s-memory-postgres Beta
mcp - carved llm4s-mcp Beta
knowledgegraph/neo4j — the Neo4j graph store (Neo4jGraphStore) llm4s-knowledgegraph-neo4j (modules/knowledgegraph-neo4j) Experimental
workspace, shared, codegen, toolapi/WorkspaceTools — containerised workspace execution: the client (ContainerisedWorkspace, WorkspaceTools, the code-generation worker) and the wire protocol it speaks to the runner image (WorkspaceAgentProtocol, WorkspaceAgentInterface) llm4s-workspace-client, llm4s-workspace-shared (modules/workspace) Experimental
media - new llm4s-media Beta
speech - carved llm4s-speech Experimental
imagegeneration, imageprocessing - carved llm4s-image Experimental
knowledgegraph — carved (knowledgegraph/graphrag ships in llm4s-rag) llm4s-knowledgegraph Experimental
javaapi — the Java facade (Llm4s, JLlmClient, JAgent, AgentStream, AgentStreamListener, StreamEvents, Answer, PendingInterrupt, InterruptKind, BreakpointPhase, ConversationBuilder, LlmResult, LlmException) — new llm4s-java-api (modules/java-api) Beta
spring — Spring Boot auto-configuration (Llm4sAutoConfiguration, Llm4sProperties, LLM4STemplate, LlmHealthIndicator) — new llm4s-spring-boot-starter (modules/spring-boot-starter) Beta
effect.cats — LLMClientIO, AgentIO (cats-effect 3, fs2) — new llm4s-effect (modules/llm4s-effect) Beta
zio — LLMClientZ, AgentZ (ZIO 2, ZIO Streams) — new llm4s-zio (modules/llm4s-zio) Beta
kotlin — coroutine API (LLMClientKt, AgentKt, AgentStreamItem); a separate Gradle build, not part of sbt or the MiMa baseline, published with each release at the release’s version (no _3 suffix; managed by llm4s-bom) — new llm4s-kotlin-api (modules/kotlin-api) Experimental
pekko — LLMClientPekko, AgentPekko (Apache Pekko Streams) — new llm4s-pekko (modules/llm4s-pekko) Beta

Notes:

  • llmconnect/provider in llm4s-core now holds only the plumbing every provider module shares - cost estimation, HTTP error mapping, metrics recording, the EmbeddingProvider trait, exchange recording - and no client. With the registration SPI in llmconnect/spi from slice 4 and the streaming and request helpers providers build on, it is a frozen provider-author SPI, public so that a provider can be published outside this repository: a provider is a ProviderDescriptor listed in its own module’s Llm4sProviderModule, so adding one adds a dependency and edits nothing in core. See Writing a provider. Helpers specific to one wire format live with it - ResponseFormatMapper and ToolCallDeserializer in llm4s-openai-compatible, OpenAI’s model-name rules in llm4s-openai - and helpers only llm4s’s own modules use, such as ProviderResultOps, are private[llm4s]. Vendor API keys (llm4s.credentials.<provider>.apiKey) are read by core’s config, but each key is bound in its provider module’s reference.conf, beside the descriptor that uses it.
  • The tracing and metrics contracts stay in llm4s-core, and they are what is frozen: llmconnect, the agent runtime and every provider module trace and record metrics through them alone. The integrations are separate modules that plug into that contract - a tracing backend is a TracingBackend registered in META-INF/services, discovered by TRACING_MODE, the way a provider is a ProviderDescriptor. They are Beta, like every integration module other than the frozen provider modules: Langfuse’s ingestion format and OpenTelemetry’s SDK move on their vendors’ schedule, not ours, and a new tracing backend should be a new module rather than a change to the frozen surface. See the migration guide.
  • Rows marked carved already live in their target sbt module. Their package names are unchanged, so this is a build-file change for users, not an import rewrite — with one exception, org.llm4s.extract, described in the migration guide.
  • org.llm4s.media is a new package, not a carve. It consolidates the three overlapping image-format enumerations llm4s-core had accumulated, so that llm4s-image and llm4s-speech carve as pure file moves rather than moves plus a vocabulary change. It is the one part of slice 3 with a source break, described in the migration guide; it is deliberate and taken now rather than after 1.0.
  • org.llm4s.extract is a new package name, not a rename of an existing one — see Slice 1 for why the two extractors were consolidated rather than just moved.
  • org.llm4s.knowledgegraph.graphrag keeps its package name but ships in llm4s-rag, not llm4s-knowledgegraph. GraphRAG and vectorstore referenced each other, which made the two modules inseparable; moving the one file that reaches into vectorstore broke the cycle. Package names track the API; module boundaries track the dependency graph, and here they disagree.
  • llm4s-memory splits in two. PostgresMemoryStore was the only file in agent/memory that needed a connection pool and a server-side driver, so it ships as llm4s-memory-postgres; keeping it with the rest would mean anyone using agent memory at all inherits HikariCP and the Postgres JDBC driver. llm4s-memory itself carries only sqlite-jdbc, for the two file-backed stores.
  • org.llm4s.vectorstore.PostgresVectorHelpers ships in llm4s-core, not in llm4s-rag with the rest of org.llm4s.vectorstore. It is a pure Array[Float] ⇄ pgvector-text codec with no JDBC types in it, and it has consumers in two modules that must not depend on each other (llm4s-rag and llm4s-memory-postgres); the module they share is core. This is the same package-versus-module disagreement as graphrag, in the other direction.
  • Vertex AI ships in llm4s-gemini. It only calls Google’s Gemini models, in the same JSON format as the Gemini API, and differs in endpoint and OAuth authentication rather than in dependencies - so bundling costs Gemini-API users nothing, whereas splitting it out after release would be a breaking move. See the migration guide.

What Frozen means

  • Source and binary compatible within 1.x. Once 0.5.0 publishes the split modules, mimaPreviousArtifacts enforces binary compatibility on every Frozen module for all subsequent 1.x releases.
  • Deprecate before removing. A Frozen API is only removed after a deprecation cycle, never dropped outright in a minor release. See the Compatibility and Deprecation Policy.
  • Beta and Experimental can move faster. They may change in a minor release, but a migration note ships with the change in the same release’s CHANGELOG.

Scala and JDK support

1.0 targets Scala 3 only (3.7.1). Scala 2.13 support is deferred to post-1.0 and, if it happens, would target the frozen spine (llm4s-core, llm4s-agent, and the frozen provider modules) rather than the full tree. The tracing and metrics contracts are part of llm4s-core; the observability integration modules are not in the spine. JDK 21 is used in CI; the JDK each artifact needs is below.

See #1126 for the reasoning behind the Scala-3-only decision.

JDK. The supported minimum is JDK 21 for every artifact, and CI runs only JDK 21. For llm4s-core and everything that depends on it, which is every artifact but two, JDK 21 is also a hard requirement, for the reasons in the table. Whether some artifacts will get a lower floor before 1.0 is an open decision (#1493); until it is made, this table is what the code needs today.

Artifacts Minimum JDK Tested on Why
llm4s-agent, and the modules that depend on it: llm4s-java-api, llm4s-kotlin-api, llm4s-spring-boot-starter, llm4s-effect, llm4s-zio, llm4s-agent-testkit 21 21 llm4s-agent depends on Ox, whose jars are compiled for JDK 21 (class-file version 65), and it starts virtual threads (Thread.ofVirtual). The Java and Kotlin facades start their own as well: AgentStream in llm4s-java-api, and AgentKt’s stream completion in llm4s-kotlin-api (#1678), and llm4s-agent-testkit’s CheckpointerContract runs its cases on virtual threads
llm4s-core and every module that depends on it 21 21 ToolRegistry starts a virtual thread (Thread.ofVirtual), a JDK 21 API, so llm4s-core does not compile against an older JDK
llm4s-provider-testkit 21 21 its interruption checks and LocalProviderTestServer run on virtual threads (#1582)
llm4s-media, llm4s-workspace-shared 21 (supported) 21 neither depends on llm4s-core: they use no JDK 21 API, and their newest dependency class files are version 55 (uJson), so they may well load on an older JDK, but only JDK 21 is tested and supported

No build setting pins a bytecode level (no -release, -java-output-version or javacOptions target), so the bytecode level alone does not tell you which JDK you need: the requirement comes from the APIs and the dependencies above. The Scala compiler emits class-file version 52 for the llm4s Scala sources. The few Java sources (the @Stable and @Experimental annotations in llm4s-core, the enums and value types of llm4s-java-api) are compiled by javac at the level of the JDK that builds them, which is version 65 for artifacts built on CI’s JDK 21. The Gradle-built llm4s-kotlin-api targets JVM 17 bytecode (version 61) and still needs JDK 21 to run.

Programme status

For current progress against this target structure, see the tracking issue #1126 and its slice sub-issues.