Glassly Miniapp SDK betaThe SDK is in beta, so its APIs may change before general availability.Developing on Mentra Live? We recommend using the
Glassly Bluetooth SDK.The developer tools are available in the Glassly App under Settings →
Miniapp Developer Settings.Share feedback with an in-app bug report, on
Discord, or by email at
[email protected].
session.ai runs LLM completions through the Glassly platform. Your miniapp
ships no API key and never sees a provider credential: the platform picks the
provider, holds the key, and pays the bill.
AI permission in your
manifest. Without it every call
rejects with PERMISSION_NOT_DECLARED. session.ai.hasPermission reports
whether you declared it.
Tiers, not models
A request never names a provider or a model. It says how much model the call deserves:
The phone resolves each tier to a concrete provider and model from the user’s
Settings > AI Models dropdowns, or automatically from whichever keys they saved.
Your miniapp keeps working unchanged when models or the user’s preferences move.
If the user has saved their own key for the provider that served a call
(Settings > API Keys), the platform uses that key and the call isn’t metered
against their plan.
billedToUserKey on the result says which happened.
Completions
complete(request) runs one turn.
The result:
prompt(text, opts?) is the single-shot convenience wrapper, taking
{system, maxTokens, jsonMode, tier} and resolving to a string. It throws on a
refusal so callers that just want text don’t have to remember that one.
The tool loop
Passtools and the model may ask you to run one. That comes back as
stopReason: "tool_use" with the calls to execute. Append the assistant turn
carrying toolCalls plus a user turn carrying your toolResults, then call
again.
inputSchema in the lowercase JSON Schema dialect ("object",
"string"); Gemini’s uppercase OpenAPI dialect is translated for you. Set
isError: true on a tool result when the tool failed, so the model can recover
instead of hanging.
The platform holds no conversation state. The whole
messages array
round-trips on every call, and nothing else will stop a runaway loop, so bound
it yourself.Web search
webSearch: true lets the model search the web when live data would help. It’s
a grant, not a command: the model may answer from knowledge, and a provider with
no server-side search tool (OpenAI today) ignores the flag. Searches run inside
the same call, so there’s no extra round-trip and no tool loop on your side, and
webSearchCount on the result reports how many actually ran. Platform-funded
searches add a small per-search surcharge on top of tokens.
Visual generation
generate(request, opts?) is a separate, long-running call: the cloud drives an
agentic provider loop with server-side web search, code execution, and file
retrieval, then returns text plus rendered images. Anthropic-only by design, and
markedly more expensive than a completion, so call it deliberately.
onProgress ticks with a coarse activity — "thinking", "searching",
"drawing", "finishing" today. Treat an unknown value as "thinking": the
platform may refine the labels without a new SDK, and hosts that predate the
progress surface complete the call normally and just never tick.
generate rejects with QUOTA_EXCEEDED when the account’s AI credit is spent,
and with INTERNAL when the host predates the request type or the cloud has the
surface disabled.
What this surface doesn’t do
Streaming, and provider server-side tools other than web search (Anthropic’scode_execution, the Files API). Those are vendor-specific, so exposing them
would make the contract non-portable. A miniapp that needs them calls the
provider directly with a key from
session.keys.
