Compile, publish, and test the Golem Scala SDK. Use when working on the sdks/scala/ subtree: building the SDK, publishing locally, compiling/running the example demo, regenerating the agent_guest.wasm, or debugging end-to-end deployment.
Compile, publish, and test the Golem Scala SDK. Use when working on the sdks/scala/ subtree: building the SDK, publishing locally, compiling/running the example demo, regenerating the agent_guest.wasm, or debugging end-to-end deployment.
Golem Scala SDK Development
The Golem SDK for Scala.js lives under sdks/scala/ in the Golem repository. It targets the Golem WIT API v1.5.0 and produces WASM components that run on the Golem platform via a QuickJS-based guest runtime.
Scala 3.8.2 — All Golem Scala 3 projects. Prefix sbt commands with ++3.8.2 (without ! — only golem projects with 3.8.2 in crossScalaVersions are affected).
Scala 2.13.18 — Cross-build for Scala 2 users.
Scala 2.12.21 — The SBT plugin (golemScalaSbt) only. Use ++2.12.21! (the ! forces override).
Important: sbt --client mode preserves Scala version across invocations. Always specify the version explicitly to avoid version drift.
SBT Project Names
Project
Description
core
Core agent framework, Scala.js facades (JS-only)
modelJS / modelJVM
WIT value types, RPC types
macros
Scala 3 macros (JVM only, cross-used at compile time)
Use these sbt aliases (from sdks/scala/) to run all golem-scala tests:
Alias
What it runs
sbt golemTest3
All unit tests (JVM + JS) + test-agents compile + integration tests — Scala 3
sbt golemTest2
All unit tests (JVM + JS) + test-agents compile — Scala 2 (integration tests are Scala 3 only)
sbt golemTestAll
Both of the above (Scala 3 then Scala 2)
Always run golemTestAll before considering a change complete.
Integration tests require the TypeScript SDK packages path. The GOLEM_TS_PACKAGES_PATH env var is forwarded automatically by build.sbt, but sbt --client doesn't propagate env vars. Use non-client sbt instead:
cd sdks/scala
GOLEM_TS_PACKAGES_PATH=<TS_PACKAGES_PATH> sbt golemTestAll
Compiling
From sdks/scala/:
# Compile test agents (good smoke test)
sbt "++3.8.2; testAgents/fastLinkJS"# Compile core
sbt "++3.8.2; core/compile"# Compile model
sbt "++3.8.2; modelJS/compile"
cd sdks/scala
sbt '++3.8.2; set ThisBuild / version := "0.0.0-SNAPSHOT"; set ThisBuild / packageDoc / publishArtifact := false; set every (publish / skip) := false; modelJVM/publishLocal; modelJS/publishLocal; macros/publishLocal; core/publishLocal'
The SBT plugin depends on codegen, so both must be published for Scala 2.12:
cd sdks/scala
sbt '++2.12.21!; set ThisBuild / version := "0.0.0-SNAPSHOT"; set ThisBuild / packageDoc / publishArtifact := false; set every (publish / skip) := false; codegen/publishLocal; sbtPlugin/publishLocal'
cd sdks/scala
sbt '++2.13.18; set ThisBuild / version := "0.0.0-SNAPSHOT"; set ThisBuild / packageDoc / publishArtifact := false; set every (publish / skip) := false; modelJVM/publishLocal; modelJS/publishLocal; core/publishLocal'
Note: The golemPublishLocal alias exists in build.sbt but may need set every (publish / skip) := false prepended to work correctly. The explicit commands above are the most reliable approach.
Building the Example Project
The example project at sdks/scala/example/ is a standalone sbt project (its own build.sbt, project/plugins.sbt). It depends on the SDK at 0.0.0-SNAPSHOT.
Primary: sdks/scala/wit/main.wit — The golem:agent-guest package definition.
Dependencies: sdks/scala/wit/deps/ — Copied from wit/deps/ in the Golem repo root.
TypeScript reference: sdks/scala/wit/dts/ — Generated d.ts files showing exact JS types expected by the wasm runtime. exports.d.ts is the source of truth for what the JS module must export.
Updating WIT Dependencies
WIT dependencies are managed the same way as the Rust and TypeScript SDKs — via cargo make wit from the repository root:
cargo make wit
This copies all WIT packages from wit/deps/ into sdks/scala/wit/deps/. The results are committed to the repository.
TypeScript SDK Reference
The TypeScript SDK at sdks/ts/wit/ is the reference for correct WIT definitions when in doubt.
RPC Client Architecture
The Scala SDK's remote agent call path uses async-invoke-and-await from the WIT golem:agent/host@1.5.0 interface, matching the TypeScript SDK behavior:
Host functions used
WIT function
Scala SDK usage
wasm-rpc.async-invoke-and-await
Default apply() and cancelable() — returns FutureInvokeResult, polled via subscribe() → pollable.promise() → get()
wasm-rpc.invoke
Fire-and-forget trigger()
wasm-rpc.invoke-and-await
Kept for backward compatibility but not used by generated clients
wasm-rpc.schedule-invocation
scheduleAt()
wasm-rpc.schedule-cancelable-invocation
scheduleCancelableAt()
Key files
File
Role
core/js/.../host/WasmRpcApi.scala
Scala.js @JSImport facades for WasmRpc, FutureInvokeResult (with subscribe/get/cancel)
Multiple concurrent RPC calls are possible since each uses its own FutureInvokeResult resource
trigger(), scheduleAt(), scheduleCancelableAt() remain synchronous (wrapped in Future)
Known Issue: Multi-Component App Scala.js Linking Error
When a Scala component is part of a multi-component (mixed-language) app, the build_mixed_language_app CLI test fails with:
Referring to non-existent class golem.runtime.__generated.autoregister.component_name.RegisterAgents
Root cause (two issues):
Source directory mismatch: The common build.sbt configures .in(file(".")) (root project), so sbt scans ./src/main/scala/. But in a multi-component app, Scala sources are in a subdirectory like scala-main/src/main/scala/. The SBT plugin's source generator finds zero @agentImplementation classes → RegisterAgents.scala is never generated.
Literal component_name in common template: The common build.sbt has golemBasePackage := Some("component_name"). Common templates have no ComponentName context (it's None), so the placeholder is never substituted. The module initializer references golem.runtime.__generated.autoregister.component_name.RegisterAgents but the class doesn't exist.
Impact: The Scala template works for standalone (single-language) apps because sources land at the root src/main/scala/. It fails only in multi-component apps where each language's sources are in a component subdirectory.
Fix needed: The GolemPlugin must auto-discover source directories from component subdirectories, and either auto-infer golemBasePackage from discovered sources or the template system must pass the component name to the common build.sbt.
Relevant files:
cli/golem-cli/templates/scala/common/build.sbt — template with literal component_name
cli/golem-cli/src/app/template/generator.rs — template transform logic (common templates get no ComponentName transform)
sdks/scala/sbt/src/main/scala/golem/sbt/GolemPlugin.scala — SBT plugin source generator and module initializer
sdks/scala/codegen/src/main/scala/golem/codegen/autoregister/AutoRegisterCodegen.scala — returns empty result when no impls found but module initializer still references generated class
Common Errors and Solutions
Error
Cause
Solution
Referring to non-existent class ...RegisterAgents
Multi-component app: sbt can't find sources in component subdirectory, so RegisterAgents is never generated
See "Known Issue: Multi-Component App" above
Function discover-agent-types not found in interface golem:agent/guest@1.5.0
Stale agent_guest.wasm built from old WIT
Regenerate wasm with generate-agent-guest-wasm.sh
Cannot find exported JS function guest.discoverAgentTypes
Scala.js Guest object doesn't match WIT signature
Update Guest.scala to export all 4 functions with correct v1.5.0 signatures (including principal param)
YAML deserialization error in golem.yaml about BuildCommand
Old GolemPlugin manifest format
Update GolemPlugin.scala to use v1.5.0 format (componentWasm/outputWasm)
Provided exports: (empty) after deploy
QuickJS fails to evaluate the JS module silently
JS crashes during initialization — check for ESM strict-mode issues, bundle size limits, or import path mismatches
publish / skip preventing local publish
Default setting in build.sbt
Use set every (publish / skip) := false in the sbt command
Wrong Scala 2.12 version for plugin
Alias or cached sbt version uses wrong 2.12.x
Use the explicit ++2.12.21! command to force the correct version