Known issues
Real limitations found through real testing, not a generic disclaimer
Known caveats
🧪 macOS 26 or 27; Xcode 27 to build the SDK
Until macOS 27 GA
One build runs on macOS 26 and macOS 27. On macOS 26 only the Apple on-device model is
available — Private Cloud Compute, the hosted providers, and open-weight (MLX) models
need macOS 27, and appear as disabled "Requires macOS 27" entries. Building the SDK
against 2.0 needs Xcode 27: the xcframeworks are compiled with the macOS 27
SDK, and an older Xcode fails with 'v27' is unavailable.
☁️ Private Cloud Compute needs Apple's entitlement
Mac App Store version
PCCModelProvider — Apple's Private Cloud Compute, the larger model Apple runs
on its own servers for requests the on-device model can't handle — works, but only in an
app that carries Apple's managed Private Cloud Compute entitlement, which comes with a
provisioning profile. In LocalLM Lab that will be the Mac App Store version, which isn't out yet.
The DMG doesn't carry the entitlement, so its AI Models panel doesn't list Private Cloud
Compute. Every other model works in both: Apple's on-device model,
Claude and the other hosted providers, and downloaded open-weight
(MLX) models. Building PCC into your own app: the
SDK guide, §10e.
🔀 API stability: 2.0 breaks some 1.x code, once
Expected
Through 1.x, releases were source compatible from 1.0.0-RC.1 on:
new capability arrived only as additive surface, and anything that would force you to edit
working code waited for 2.0. 2.0 is that release. It folds 1.x's leftover
overloads into single APIs (most call sites compile unchanged) and replaces a few
authorization APIs — RuleBasedToolAuthorizer,
ConfirmingToolAuthorizer's requirement: closure, and
setTrustsToolAnnotations — with per-server trust and approval. Each change,
and what to write instead, is listed under Breaking in the CHANGELOG.
2.0.0 is the new baseline. Every 2.x release is source compatible with it:
additive surface only (new optional parameters with defaults, new enum cases you handle via
@unknown default). Pin an exact LOCALLM_SDK_VERSION and rebuild
against the version you pin — this is a promise about source compatibility, not about an
already-built app picking up a newer SDK binary without recompiling.
💭 Model reasoning streams inline, not on its own channel
Post-beta
Several open-weight models emit chain-of-thought in their output
(<think>…</think> and similar). The MLX bridge streams
that through verbatim in the response text — there's no separate reasoning channel yet
(Apple's streamResponse doesn't surface incremental reasoning). Prompt
Playground's "Thinking…" pane strips the delimiters for display; from the SDK you strip
them consumer-side.
Since 1.0.0-beta.4 you can also turn the reasoning pass off entirely
for models whose chat template supports it (the Qwen3 family): pass
SessionOptions(effort: .off) to makeSession from the SDK, or
flip Prompt Playground's No thinking toggle. The model then never
opens the <think> block, which also makes it noticeably faster.
🌐 LAN access is lightly tested
BetaAPI Lab's LAN HTTPS mode (reaching the API from another machine on your network) works in our testing but hasn't been exercised across a wide range of network setups. Localhost is the well-trodden path. If LAN gives you trouble, tell us what your setup looks like.
🧰 Tools are fixed when a multi-turn conversation starts
Fix plannedIn Prompt Playground's Multi-turn mode, a conversation keeps the tools it started with. If you enable or disable a connector or MCP tool, or change a connector's Security level, partway through, the open conversation does not pick the change up — the model can't call a tool you just turned on, and can still call one you turned off. The Connectors panel shows the new setting, but nothing tells you the conversation hasn't adopted it. The cause is that a session's tool set is fixed when the session is created, and a multi-turn conversation reuses one session. Single-shot runs are not affected: each Run opens a fresh session with the current tools.
Workaround: choose your tools first, then start the conversation. If you change them mid-conversation, click New Conversation — the next Send starts a session with the current tools (the earlier turns are not carried over). Loading a configuration profile, or saving a model's tuning, already ends the open conversation for the same reason. The planned fix re-creates the session with the new tools and carries the conversation into it, so you won't lose the earlier turns.
On-device limitations (carried over)
These aren't beta bugs — they're what running a small model fully on-device looks like. Neither is fixed by server-side workarounds that quietly rewrite what the model sees or says — that would break the raw in, raw out design this app is built around.
📉 Enabling many connectors/MCP tools at once can exhaust a small context window
Guideline availableApple's on-device model has a small context window. Every connector and MCP tool you enable adds its schema to that budget before the model has even seen your prompt — with several connectors and a few MCP servers all turned on at once, the schemas alone can consume most of it, and the request fails with a context-window error rather than degrading gracefully.
Guideline: enable only what a given task actually needs — disable
unused connectors and MCP tools in the relevant panel. LocalLM Lab also gives you another lever:
route heavier turns to a model with a bigger window (a larger MLX model, or a hosted
provider) and keep the on-device model for light ones. session.contextBudget
and retryOnContextOverflow help a long session survive.
👤 Updating a Contact can occasionally set an unrequested field
Mitigated, not eliminated
When asked to change one specific field on an existing contact (e.g. "update the
organization"), the model can occasionally also set a different field to a copied value
it was never asked to change — observed live, it copied the new organization into the
contact's family name field on one run. This only affects updateContact
(the Changes level, which is the default), and only sometimes; most update requests behave correctly.
The tool's description already tells the model explicitly not to do this — "each new* field is independently optional... never copy a value from one field into another" — and that measurably reduces how often it happens, but a small on-device model doesn't follow instructions with perfect reliability, and no guardrail on our side can catch this without filtering what the model actually writes, which we've deliberately chosen not to do. If you use Contacts' write capability, it's worth glancing at the result rather than assuming only the field you asked about changed.
🔁 A hosted model can loop on a repeatedly-failing tool call
Fixed for local models · planned for hostedWhen a tool keeps rejecting the model's calls — invalid arguments, or a server-side limit like a search filter that needs a paid plan on the connected service — a capable hosted model (via API Lab or a hosted provider) will sometimes retry many times in a row rather than stopping. Observed live: a Notion search looped ~34 times before landing on a working query. Apple's on-device model caps its own tool loop, and so do locally-run (MLX) models: a turn that keeps calling tools stops after 16 model calls, with a message saying so. A hosted model routed through LocalLM Lab does not yet, so the turn just runs long. The Tool calls list in the Playground is scroll-bounded so this no longer disrupts the window.
Workaround: if a turn is taking unusually long with a growing tool-call list, cancel it and rephrase — a more specific prompt, or disabling the tool that's failing. The same per-turn limit for hosted models is planned.
Contact
Run into something not listed here? Contact neuron@thisbrain.ai or join our Discord.