Skip to main content

Register backends before initializing

The plugin registry has to know which engines exist before the first model load. Register, then initialize.
Getting this backwards produces “No provider could handle the request”, which reads like a model problem and is not.

Initialize once, early

initialize() is synchronous and cheap. Call it at app launch rather than lazily on the first generation, so the background phase has time to finish before anyone needs it.

Let generation load the model

Generation auto-loads and downloads when needed. Reach for models.load when you want to control when the cost is paid, for instance warming a model behind a splash screen.

Stream anything a person waits for

A 200-token reply takes seconds. Streaming turns that into words appearing immediately.

Cap output length

maxOutputTokens is the single biggest lever on latency and heat. Set it to what the interface can actually display.

Unload what you are not using

Models hold memory for as long as they are resident. On a phone, holding a language model, a speech model, and a vision model at once is how you get .insufficientMemory.

Trim conversations

History grows until it exceeds the context window. Keep the system message and the most recent turns.

Keep system prompts short

Small models follow three concrete sentences better than a paragraph of persona. Say the format you want and the length you want, and nothing else.

Use structured output rather than asking nicely

Asking for JSON in a system prompt works most of the time, which is the problem. When you need to parse the result, use generateStructured, which validates and can repair.
.constrained is not implemented yet and throws.

Handle cancellation

Cancel the Task when a view disappears. Otherwise a generation keeps running and keeps the model resident for a screen nobody is looking at.

Check capabilities rather than assuming

A namespace existing does not mean the engine behind it is linked in your build. MLX on the simulator is the common case: MLX.register() returns false and no MLX model will load.

Test on hardware

The simulator has no arm64 native libraries for some backends and runs no MLX inference at all. Performance numbers from a simulator are meaningless.

Watch memory around images

Image generation is the heaviest operation in the SDK. Run one at a time, show progress, and allow cancellation.