Public release notes for SAALT packages. Versions follow semver. Entries use the Keep a Changelog format.
SAALT Core
Release notes for the core SAALT platform — the web app, REST API, App runtime, and built-in features. These are the developer-facing technical notes; the in-app What's New covers the same releases at a higher, user-facing level.
v1.4.2 — 2026-09-16
Fixed
- The New Agent view could crash right after the creation animation when using Custom Setup, from an effect callback whose return value was mistaken for a cleanup function.
v1.4.1 — 2026-09-16
Fixed
- A permission check on
/app/<id>/*App sub-paths was checking every request, when only/admin,/user,/knowledgeand/standaloneare meant to require a SAALT session. Everything else under an App's path — its own API routes, OAuth callbacks, inbound webhooks — is meant to authenticate itself (API keys, OAuthstate, signatures), which is the contract Apps were built against before v1.4.0. Unauthenticated and third-party calls into those routes were rejected with 401 until this was scoped back correctly. - A globally-enabled App did not run for user-owned personal Agents, because
getAgentIdsForPluginexcluded them from the "global" set while the tool-availability check that decides whether an Agent runs the App's tools did not — so a personal Agent could call the App's tools but the bridge token'sagentIdallowlist did not include it, and every agent-targeted call 403'd. Global now means every Agent, personal ones included.
v1.4.0 — 2026-09-15
Added
- Skills marketplace — Skills now carry a provenance:
skill.source(CUSTOM,DEFAULTorMARKETPLACE),skill.providerandskill.sourceId, plusskill.creatorType(SAALTorUSER) andskill.creatorId. Marketplace Skills are installed by scoping a published Skill to a Space or Agent throughskill_availabilityrather than by copying it, and uninstalling removes that availability. Marketplace entries are archived instead of deleted, a Skill's live version is pinned by anactiveVersionIdforeign key ontoskill_version, duplicate Skill names are rejected, and a zip import is fetched through the safe-fetch path. The default code-execution Skills are seeded locally at startup. See Skills. - Speech input in chat — dictate a message instead of typing it, with the transcript streaming into the composer as it is recognised.
- Model security tiers — every model resolves to one of three tiers, ordered most to least trusted:
secure(SAALT's own hosting region),eu-hosted(any other EU region) andus-cloud(everything else). The tier is taken from an explicitsecurityTiersupplied by the config API and otherwise inferred fromregion; anything unclassifiable fails closed tous-cloud. Capability tags such asdeep_researchare never consulted. The model selector shows the tier, warns when a switch moves to a less-trusted one, and displays a price indicator in euro.ModelInfoalso gained a freeformlocationLabelfor display, which must not be used for classification — see the Bridge reference. - Remote sandbox driver for code execution —
SANDBOX_DRIVERnow acceptsremotealongsidedocker,kubernetesandopenshift, so sandboxes can run on a dedicated host instead of the cluster that runs SAALT. The switch falls back to the container-appsAPP_CONTAINER_DRIVERfor deployments that already schedule containers, and the sandbox stays dormant unless a driver is set. Limits (CPU, disk, idle and hard timeouts, image) are configured per deployment. - Permission-group membership is managed inside the group — members can be added and removed from the group's own screen instead of only per user.
Changed
- Compaction now also runs mid-stream, not only between turns;
conversation.firstKeptPartIndexrecords the boundary inside a partially kept message, so a long single response can be compacted without discarding the whole turn. - Search jumps to the point in the conversation where the match occurs instead of opening it at the top, and the dialog gained a default height and a debounce.
- More than three files returned by a code-execution sandbox render as a table rather than a list, and the sidebar's collapsed state is remembered in a cookie.
Fixed
- Newly created Agents could be locked out of every App with a 403. The plugin-token allowlist was cached in Redis under a key with no expiry, so an Agent created after the cache was populated never appeared in it. The cache is now invalidated whenever an Agent is created or deleted.
- Social login failed with
account_not_linkedfor existing users. SAALT has no email-verification flow, souser.emailVerifiednever carried meaning, but Better Auth refuses to implicitly link a trusted Google or Microsoft account to an unverified user. Existing users are backfilled as verified.
v1.3.5 — 2026-09-09
No functional changes. This release carries deployment configuration only; the platform behaves identically to v1.3.4.
v1.3.4 — 2026-09-07
Changed
- Failed document conversions report with structured diagnostic context. When a document cannot be parsed, the error report now carries the document id, file name, extension and whether an LLM was configured for the run — and, where the converter chain itself raises the failure, one entry per converter that was tried, each with its own error type and message. Reports are fingerprinted on the converter chain, so repeat failures of the same kind group together instead of arriving as unrelated errors. Reporting requires a Sentry DSN to be configured; nothing changes about how documents are parsed.
v1.3.3 — 2026-09-02
Fixed
- Cached input tokens are priced more accurately in the usage figures. The cost shown in usage reporting is derived from the token counts on
llm_invocation. Providers reportinputTokensas the full total, with cached reads already counted inside it, so applying the standard input price to that total and then adding the cached portion on top overstated the calculated cost. The standard price now applies only to the non-cached remainder. Where a model's config carries no explicitcachedInputprice, cached reads fall back to 10% of the input price — in line with how providers such as Anthropic price prompt caching — rather than the full input price.
v1.3.2 — 2026-09-01
Added
- Conversation context compaction — long conversations are summarised into a durable checkpoint instead of being rebuilt on every turn.
conversation.firstKeptMessageIdmarks the boundary between the summarised prefix and the messages still sent verbatim; the checkpoint is written once when the conversation exceeds its token budget and reused by every later turn, and attachments before the boundary are replaced by a note. This replaces the previous background job that regenerated a rolling summary after each reply, so the request prefix stays stable and remains eligible for provider prompt caching between turns. The migration clears all legacyconversation.summaryvalues. Compaction attempts are tracked alongside the stream. - Delete a single message from an Agent's conversation history, from the conversation detail view in the Agent's space.
- Chat shows a note while conversation tracking is active, so a user can see when an Agent admin is able to review the conversation. Suppressed for incognito conversations, which are not retained at all. See Chat.
- Superadmins can delete their own account, behind a danger confirmation and a sign-out flow. A new guard (
superAdminGuard.server.ts) prevents removing the last superadmin, or stripping theglobal.super_adminscope from the last permission group that grants it. - Invitations record who sent them —
invitation.invitedById, nulled if that user is later deleted.
Changed
- Search — hits render their markdown instead of showing raw syntax, the dialog was reworked with skeleton loading and mobile styles, and single-character queries no longer run.
- Spaces and Agents carry a shared or private label in the overview, and subagents inside a space now appear in the Integration Availability overview.
- The default Agent system prompt was trimmed, and new Agents get a short default description instead of an empty one.
- App settings modals are wider, the sidebar collapse is animated, password inputs have a show/hide toggle, and the browser's native
window.confirmwas replaced by the in-app confirm dialog.
v1.3.1 — 2026-08-25
Changed
- Attachments that are neither images nor PDFs download directly instead of opening in a new tab.
- Tool-call groups show truncated labels with improved taglines, updated labels for code tool calls, and more room in the message body.
streamTexttelemetry is reported when a Sentry DSN is configured.
Fixed
- Chat scrolling and jumping — the long-message clamp is relative to the viewport, the view no longer resets after streaming finishes, a spacer keeps message height consistent, height is recalculated once the on-screen keyboard has settled on iOS, and a small jump on tool calls in Safari is gone.
- The loading indicator is hidden once streaming starts and no longer disappears in some states; the typewriter effect is back.
v1.3.0 — 2026-08-19
Added
- Skills — a reusable, versioned procedure an Agent follows for a recurring task: the instructions plus the templates and files it needs. Backed by
skill,skill_versionandskill_blobtables with aSkillStatuslifecycle and per-provider references (skill_version_provider_reference);skill_availabilityrows scope which Agents may use a Skill. Uploaded resources are stored as blobs and handed to the Agent at execution time. - Code execution — Agents can run code over uploaded files and larger datasets in an isolated sandbox and return the result as a table, chart or report. Execution state is tracked per conversation in
conversation.codeExecutionState. - Container Apps — an App can ship as a container image instead of only a proxied URL.
installed_pluginsgains atypediscriminator (PluginType) pluscontainerImage,containerPortandlastError; registry credentials live in the newcontainer_registry_credentialstable. See Apps. - Usage attribution and reset countdown —
llm_invocation.isIncludedUsageseparates subscription-covered calls from billable ones, and the usage limit now shows when the current window resets.
Changed
- A new model selector in chat, and an updated analytics page.
- The browser's native file API is used where available, with a fallback otherwise.
- Cloning an Agent carries its full configuration, and per-Agent model overrides apply consistently.
Fixed
- Cross-user conversation disclosure in the generate endpoints — a supplied conversation id is now validated against the requesting user. Previously an id belonging to another user, or an arbitrary id against a public Agent, could read back that conversation's history.
- Provider reasoning-item references are stripped when a turn is trimmed from history, so OpenAI-family models no longer fail on a truncated reasoning chain.
- Token usage is recorded for streamed conversations.
v1.2.4 — 2026-08-10
Fixed
- Editing an App's URL now invalidates the cache across all replicas, instead of only the one that served the edit.
- Provider-specific tool metadata is stripped from message history before it is replayed to a model.
v1.2.3 — 2026-08-10
Added
- Time-based usage quotas — per-user usage windows (
user.usageWindowStartedAt) with weekly limits and reported overage. - Sampling controls (
temperature,top_p,top_k) can be disabled per Agent.
Changed
- Personal Agents save a model change automatically.
- Memory is not applied to API-driven streaming conversations; that path stays a raw model call.
Fixed
generateTextandgenerateObjectin the core API rejectsystem-role messages instead of accepting them silently. See the API reference.- Spacing around rendered tool calls in chat.
v1.2.2 — 2026-08-03
Added
- Instances running without outbound connectivity fetch a default configuration.
Fixed
- An App's identifier is updated on refresh, so a renamed App keeps resolving.
v1.2.1 — 2026-08-03
Added
- Mermaid diagrams render in chat. See Chat.
- MCP re-authentication — expired MCP OAuth grants are detected and surfaced, with error handling around the OAuth status check.
- An App's URL can be edited after installation. See Apps.
Fixed
- Aborted response streams are handled without leaving the turn in a broken state.
- Image-generation cost is reported correctly in usage analytics.
v1.2.0 — 2026-07-03
Added
- Memory — durable per-Agent, per-user facts carried across conversations, so answers stay relevant without re-explaining context each time. Personal (per-user) and shared (agent-wide) memories are stored separately and capped per bucket, gated by the Agent's
memoryEnabled/sharedMemoryEnabledsettings; a background pass consolidates and safety-screens entries before they are stored. See Memory. - Standalone Apps — Apps can run agent-less and full-page as their own destination, rather than always attached to an Agent's chat. Declared with
standalone: trueplus a stableidin the App's/meta, served under/app/{id}, and given a standalone-scoped Bridge (noagentId— agent-targeted Bridge calls are rejected). See Standalone apps. - OpenAI-compatible API — a gateway at
/api/openai/v1that speaks the OpenAI format, so existing OpenAI SDKs and tools work against SAALT with minimal changes. Implementschat/completions(streaming, tool calls, and token usage),models, andembeddings, plus a SAALT-specificrerankextension. Authenticate with an API key viaAuthorization: Bearerorx-api-key. See OpenAI-compatible API. - Personal agents — user-owned Agents (
isPersonal) scoped to a single user, alongside shared team Spaces; each user gets a personal chat Agent scaffolded automatically. - Conversation API — REST endpoints to list and continue conversations and read their messages:
GET/POST /llm/{agentId}/conversationandGET /llm/{agentId}/conversation/{conversationId}/messages. Conversation search is backed by Postgres trigram and full-text indexes. See the API reference.
Changed
- Rewritten Chat experience — an in-chat Agent switcher, drag-and-drop / paste file uploads, conversation search, per-Agent model preference, and deep-research progress indicators. Chat routing moved to
/space/{spaceId}/agent/{agentId}; the legacy/chat/{agentId}path redirects. See Chat.
This is the first published SAALT Core release entry. Full historical core release notes will follow. For the current API contract, see the API reference.
Bridge — @open-agent-kit/bridge
Release notes for the TypeScript SDK that Apps use to talk to SAALT Core. See Bridge SDK reference for the current method surface.
v1.2.0 — 2026-08-03
First stable 1.2.0 release — the standalone-bridge rework: bind-once scope, transcription, agent-less LLM generation, and conversation listing. Install with npm i @open-agent-kit/bridge. Changes below are relative to the previous stable release, v1.0.8.
Breaking
createBridgenow binds scope once at construction —createBridge({ token, serverUrl, agentId? }). Per-callagentIdarguments were removed fromconfig,pluginData,knowledge,conversation,agent, andllm.getAvailableModels; the scope is taken from the bridge instance instead.- Agent-only namespaces (
knowledge,conversation,agent,llm.getAvailableModels) throw on a standalone (agent-less) bridge.
Added
- Standalone (agent-less) bridge support — omit
agentIdwhen constructing to talk to SAALT Core without an Agent scope. - Exported
BridgeScopetype:{ type: "agent"; agentId } | { type: "standalone" }. llm.transcribe(params)— speech-to-text over an audio/video clip via Gemini. Params:model,audioBase64,mimeType, optionalprompt; returns{ text }. Works on both standalone and agent-scoped bridges.llm.generateText,generateObject, andgenerateImagenow run on a standalone bridge (no agent required); the model resolves to the instance-wide default.conversation.findMany(filter)— list an agent's conversations with an optional Prisma-style filter (where/select/orderBy/skip/take/cursor), returning a bareConversation[]. Message bodies are not included (usefindFirstper conversation, as they can be large); incognito and private conversations are never returned, and archived ones are excluded by default. Requires an agent-scoped bridge. See thebridge.conversationreference.llm.getAvailableModelsnow also returnsmodels: ModelInfo[]alongsidedefaultModelandavailableModels— the full metadata (key,modelId,displayName,provider,region,tags,pricing, …) for each allowed model, so a picker can show names and badges instead of raw keys.
Changed
- Forwarded proxy headers renamed:
oak_session_token/oak_server_url→saalt_session_token/saalt_server_url(plus a newsaalt_base_path). - The SDK's admin API base path moved to
/api/v1/bridge. The legacy/api/v1/adminbase path 307-redirects for backwards compatibility.
v1.0.8 — 2026-06-26
Added
bridge.llm.generateSpeech(params)— text-to-speech via Gemini TTS. Returns{ base64, mimeType }for the synthesized audio. Supports a single prebuiltvoiceNameor a multi-speakerspeakersarray (up to 2 speakers, each mapping a speaker label to a voice).
Breaking
- None.
v1.0.7 — 2026-06-25
Added
bridge.llm.getAvailableModels(agentId)— returns{ defaultModel, availableModels }for the Agent so Apps can gate model selection to what the Agent actually allows.
Changed
bridge.llm.generateImagenow accepts an optionalimageConfig(aspectRatio— one of1:1,4:3,3:4,16:9,9:16;resolution—1K,2K, or4K) and an optional inpaintingmask(a data URL). Existing calls without these fields are unchanged.
Breaking
- None.
v1.0.6 — 2026-05-26
Added
bridge.agent.getAgent(agentId)— returns{ id, name, model }for the given Agent so Apps can render the configured LLM model or display name. Token-scoped: the call returns403if the App's bearer token does not include the requestedagentId.
Breaking
- None.
v1.0.5 — 2026-05-26
Changed
- Raised the undici dispatcher
headersTimeoutfrom 30 minutes to 60 minutes so long-running LLM and file-parse calls don't time out at the SDK transport layer.
Breaking
- None.
v1.0.4 — 2026-05-08
Added
bridge.knowledge.attachTagToDocument(agentId, documentId, tagId)— attach an existing knowledge tag to a document.bridge.knowledge.removeTagFromDocument(agentId, documentId, tagId)— detach a knowledge tag from a document.
Breaking
- None.
v1.0.3 — 2026-05-08
Added
bridge.knowledge.createTag(agentId, tag)— create a knowledge tag for an agent.bridge.knowledge.listTags(agentId)— list knowledge tags for an agent.bridge.knowledge.updateTag(agentId, tagId, updates)— update a knowledge tag's name or color.bridge.knowledge.deleteTag(agentId, tagId)— delete a knowledge tag.- Types:
KnowledgeTag,KnowledgeTagInput,KnowledgeTagUpdate.
Breaking
- None.
v1.0.2 — 2026-04-01
Changed
- HTTP requests now use a custom
undiciAgentdispatcher with a 30-minute headers timeout, so long-running LLM calls aren't cut off by Node's default fetch timeout.
Added
undici ^7.24.6runtime dependency. Node 18+ ships with undici, but Apps must allow it as a transitive dep.
Breaking
- None.
v1.0.1 — 2026-03-25
Added
- Package
README.mdwith installation snippet and a namespace reference table.
No code or API changes in this release.
Breaking
- None.
v1.0.0 — 2026-02-09
Initial public release of @open-agent-kit/bridge.
Added
createBridge({ token, serverUrl })factory andOAKBridgereturn type.decodeToken(token)helper for inspecting the forwarded session token.Toolsclass for registering an App's Tools, with exportedToolandToolExecuteParamstypes.- Bridge namespaces:
bridge.data.config,bridge.data.pluginData,bridge.llm,bridge.files,bridge.knowledge,bridge.conversation,bridge.user. PluginMetatype and re-exportedFilePart/ImagePart/TextPartfrom@ai-sdk/provider-utils.- Runtime dependencies:
zod,zod-from-json-schema,zodex.
Breaking
- None (initial release).