Moxzi Alpha 9 brings GPU learning and persistent local actors to Motoko 2.0

Hi everyone,

An actor already has an identity, private state, and a way to talk to other actors. What happens when part of that state is a model it can train?

That is one of the questions behind Moxzi Alpha 9. Alongside the move to Motoko 2.0, this update gives hosted actors GPU math, lets them share and teach models, and strengthens how their state survives crashes and upgrades.

Alpha 8 was not publicly released, so this announcement covers the work from both Alpha 8 and Alpha 9. The release notes have the full breakdown.

For anyone meeting the project for the first time: Moxzi is a Motoko compiler written in Motoko, together with runtimes for running Motoko actors on the IC, on servers, and in browsers. This update develops both sides of that story: the language we compile and what actors can do when you host them.

Motoko 2.0 across the toolchain

Moxzi now implements Motoko 2.0.0, including its syntax, persistence defaults, diagnostics, and runtime changes. Compiled canister metadata and runtime compiler-version reporting now identify that baseline correctly, too.

That means less punctuation around conditions and patterns, more convenient asynchronous function bodies, and stricter checks that catch mistakes before deployment. Several diagnostics that were warnings are now errors by default, following moc 2.0. Migration checks also reject more invalid upgrades during compilation rather than letting them fail when installed.

Moxzi keeps its additions—including Nat128, Nat256, local actors, and the off-chain runtime work—on that newer foundation. Credit to the Motoko team for the upstream 2.0 work that makes this possible.

This is a language upgrade, not just a version-label change. Existing 1.x code may need edits.

Local actors persist across upgrades by default

actor* is Moxzi’s extension for actors that live inside an ordinary actor’s container. You can give a population of entities their own state and identity without creating a separate canister for each one.

In Alpha 9, local actors follow the same persistence default as ordinary actors. Keep an instance in a stable field, and its state, identity, and handles survive compatible upgrades of the containing actor.

Here is a complete small example:

actor {
  actor* class Counter() {
    var count = 0;

    public func add() : async* Nat {
      count += 1;
      count
    };
  };

  let counter = Counter();

  public func add() : async Nat {
    await* counter.add()
  };
}

Call the outer add seven times. After a compatible upgrade, the next call should return eight—not one. The child is still the same child, with the state it accumulated.

There is no separate experimental persistence flag to turn on. If an actor should start fresh on upgrade, spell that choice explicitly with transient actor*. Likewise, putting a child in a transient parent field reconstructs that binding on upgrade; the plain let counter above is intentional.

Local calls through await* do not introduce an independent commit point. They run within the enclosing message segment; a trap rolls back its local changes together. And actor* itself remains an experimental Moxzi extension, enabled through the local-actors feature—not something stock moc compiles.

GPU training from Motoko actors

A host started with a tensor device lets its actors train and run neural networks from Motoko. On an Apple GPU, enabling the device looks like this:

moxzid -s ./state --device burn:metal

Use burn:cpu for the CPU. The GPU guide walks through building, loading, and calling a training actor.

Each hosted actor gets a private logical space for its parameters, optimizer state, and stored values. Actors can use the same parameter names without colliding. The physical device can still be shared.

Rather than shipping every intermediate tensor through actor messages, the actor submits a program describing a training step. The heavy math runs on the device, where the weights and optimizer state remain. Optimizers include AdamW, Muon, and SGD; Burn supplies a pure-Rust engine, with Metal and CPU options and feature-enabled CUDA/Vulkan builds.

This is GPU execution on an off-chain host, not GPU execution inside the IC’s replicated canisters. The device methods are exposed to hosted Motoko actors through the host’s management-canister interface. CUDA support was not yet qualified on NVIDIA hardware for this release. (But if IC or Cloud engine nodes added GPUs then this would theoretically be able to take advantage of that hardware).

Actors can share models and teach one another

An actor can publish a weight snapshot and choose who may read it. Another actor can use that snapshot read-only or combine compatible snapshots through weighted mixing. Publications are private to the publisher unless readers are granted access.

There is also model distillation: a student learns from a teacher’s predicted distribution, even when their model designs differ. That opens up experiments with several specialized learning actors, shared starting points, or a smaller student learning from a larger teacher.

Across machines, devices transfer the tensor bytes directly. Actor messages carry an expiring export URL rather than the large payload. Those URLs work once by default, expire after ten minutes, and must be reissued after a host crash. Protect the transfer endpoint with TLS on untrusted networks.

The useful abstraction here is that a model can have an owner, a lifecycle, and collaborators—the same things we already organize around actors.

Measured performance improvements

Some concrete results from the recorded workloads:

Workload Recorded change
Text generation with a key/value attention cache 1,044 → 14,681 characters/second, about 14×, sampling 129-character texts at 1,024 rows per step
An eight-expert model’s training step on Metal 2.0 seconds → 0.22 seconds, about 9×, with batched Muon updates and GPU synchronization fixes
Weight synchronization between two islands hosts behind Ray 40 seconds → about 1.2 seconds, about 33×, using direct device transfers

These are different workloads, not a universal multiplier for Motoko or every model. The attention-cache improvement, for example, comes from reusing earlier keys and values instead of recomputing the whole context for every generated character.

The device work also fixes an evaluation-memory leak that could exhaust the host during long-running training. Making a step faster is useful; keeping an experiment running is just as important.

Recovery includes the learning state

One failure made the durability work especially concrete: a nine-actor learning system was killed after its second day and came back at day zero.

The fixes cover state changes made through calls between actors and timer-driven work, not only messages arriving from outside. With durable state enabled, device recovery also restores weights, optimizer state, stored values, and publication permissions before actors receive another message.

Alpha 9 adds checkpoints based on device time, alongside the existing journal-size trigger. Previously, small training-call records could leave minutes of GPU work to replay after a crash; one observed restart replayed 341 seconds. The new default targets a checkpoint after 30 seconds of accumulated device work.

That is a replay target, not a promise of a 30-second restart. Large copies, workload size, and the safeguard against copying more often than every ten copy-durations affect recovery. GPU reconstruction can also differ in the last digits; use the CPU engine when exact repeatability is required.

Browser budgets and host reliability

The less visible work matters whenever actors run for longer or accept less-trusted input:

  • Browser execution and memory budgets. The release player enforces a ceiling of 20 million instructions per message, plus memory and actor-count limits. Fuel exhaustion rolls back the message while leaving the worker alive.
  • Consistent game validation. Invalid HUD, audio, input, lifecycle, and rendering changes are rejected before they mutate the world.
  • Working world restores and safer manifest upgrades. Alpha 9 fixes saved-world decoding and records an actor’s module alongside its durable state, so a changed manifest file is not silently run against old state.
  • Tighter host boundaries. Across the existing Dapr, Restate, Orleans, Temporal, Ray, Proto.Actor, Apache Pekko, wasmCloud, and Cloudflare Durable Objects integrations, this round hardens identity, retries, timers, storage isolation, resource limits, and recovery.
  • More reproducible setup. Generated Ray projects use hashed dependency locks; platform-runtime identities are pinned where supported. Startup checks catch occupied ports and conflicting Restate containers instead of letting every subsequent call fail mysteriously.

Release checks are stricter, too: required-build failures, timeouts, and zero-work runs prevent a release verdict. Tested artifacts are identified by hash.

If you experimented with Alpha 8 development builds, note that its broken world-save files cannot be restored by Alpha 9. The fix makes the save encoding work; it does not repair those files.

Off-chain execution still does not inherit a subnet’s consensus or certification. The host’s configuration and security boundaries remain part of the application.

Try Alpha 9

Install the version covered here:

curl -fsSL https://moxzi.ai/install.sh | MOXZI_VERSION=0.1.0-alpha.9 sh
moxzi --version

Save the counter example above as Counter.mo, then build it with local actors enabled:

moxzi build Counter.mo --experimental-local-actors 128 -o counter.wasm

For upgrades from classical persistence, the move to enhanced orthogonal persistence now requires the explicit --enhanced-orthogonal-persistence option, following Motoko 2.0. That migration is irreversible; rehearse upgrades before applying them to valuable state. This release also fixes upgrade failures involving stable regions and canisters that had previously migrated from classical persistence.

The hosts bundle now also includes a tensor-enabled moxzi-actor-host, with CPU support and Metal on macOS, so using that binary in a multi-host setup no longer requires building it from source.

Start with the installation guide, explore the GPU training example, or read the full Alpha 8 and 9 release notes. Moxzi remains alpha software and is source-available under BUSL-1.1.

We would particularly love feedback from people working on persistent simulations, many-entity applications, and learning systems:

  • Where would persistent local actors simplify your data model?
  • What would you try if a Motoko actor could own, train, and share a model?
  • Which real applications should we use to test the Motoko 2.0 migration next?

The direction is simple: let an actor keep not only its application state, but what it has learned—and make changing the software less disruptive to both.

This is interesting. Thank you for sharing your work here.

I was getting some compilation errors but after reading the documentation more carefully I was able to find my mistakes. Thanks again.

Let me know if something was confusing or if something can be easier. Aloha 10 coming this week!