SAALT Bridge
The Bridge package is the thin client SAALT Apps use to talk to the host SAALT instance. It wraps the admin API with a tiny fetch helper so custom App views can read and write configuration, call the platform LLM endpoints, and manage App-owned data without rebuilding clients by hand.
Installation
Code
Quick start
Code
Scope is bound once when you call createBridge and is fixed for the bridge's lifetime — provide agentId for an agent-scoped bridge, omit it for a standalone one.
The bridge builds a pre-authorized fetch client with the provided token and serverUrl and then exposes namespaced helpers:
data.config– store small JSON configuration blobs peragentId(get/set).data.pluginData– CRUD helpers for App data records (find, create, update, delete, count). (SDK name retained for backwards compatibility.)llm– call the platform’s text, object, image, or conversation-generation endpoints.files– read/write files in SAALT storage and parse uploaded content.knowledge– list knowledge documents for an agent and enqueue syncs.conversation– read conversation records: a single one with its messages (findFirst) or a filtered, paginated list (findMany).user– retrieve information about the current user.agent– read Agent metadata (id, name, configured LLM model).decodeToken– inspect the forwarded session token when you need user metadata.
Use these helpers directly inside your custom React routes, API handlers, or background jobs that need to coordinate with the SAALT backend.
Bridge SDK reference
The bridge is a TypeScript SDK — every helper below wraps an admin REST endpoint (see the API category) so App code can call it with normal types instead of hand-constructing HTTP requests. The signatures here are pulled directly from the published @open-agent-kit/bridge package; refer to this page rather than the REST spec when writing App code.
Exported types
Code
Tools (class) is the only value export from the package — see the tools section below. z is not re-exported; import it from zod directly (import { z } from "zod";).
createBridge
Code
Provide agentId for agent-scoped apps; omit it for a standalone bridge. Scope is bound once at construction and cannot change afterwards.
Agent-scoped vs standalone bridges
Passing agentId to createBridge yields an agent-scoped bridge; omitting it yields a standalone bridge. The chosen scope is fixed for the bridge's lifetime.
config,pluginData, andfileswork on both kinds of bridge. On a standalone bridge they are scoped per-plugin instead of per-agent.- The agent-only namespaces —
knowledge.*,conversation.findFirst/conversation.findMany,agent.getAgent, andllm.getAvailableModels— require an agent-scoped bridge. Calling any of them on a standalone bridge throws a client-side error:
This operation requires an agent-scoped bridge; create it with createBridge({ ..., agentId }).
Scope is bound once at construction (rather than passed per call) since @open-agent-kit/[email protected].
bridge.data.config
Stores small JSON configuration blobs. Wraps PUT /data/config and GET /data/config; the scope is sent as an ?agentId query param (omitted for a standalone bridge, where config is scoped per-plugin).
Code
bridge.data.pluginData
CRUD helpers for App-owned records. Records are keyed by the bridge's scope (agent or plugin) + identifier. (The namespace name pluginData is preserved from the original SDK API.)
Code
PluginDataFilter accepts where, select, orderBy, skip, take, cursor. PluginDataDeleteFilter accepts where only.
bridge.llm
Code
transcribe runs speech-to-text over an audio or video clip via Gemini (available since @open-agent-kit/[email protected]). It works on both standalone and agent-scoped bridges:
Code
generateSpeech synthesizes audio from text via Gemini TTS (available since @open-agent-kit/[email protected]):
Code
GenerateImageParams accepts an optional imageConfig and inpainting mask (available since @open-agent-kit/[email protected]):
Code
getAvailableModels reports the Agent's default model plus the full set of models it is allowed to use, so a plugin can present only valid choices. availableModels is the list of model keys; models carries the full ModelInfo for each (added in @open-agent-kit/[email protected]) — key, modelId, displayName, provider, region, tags, description, pricing, and similar metadata — so a picker can show names and badges rather than raw keys. It requires an agent-scoped bridge and throws on a standalone one. Available since @open-agent-kit/[email protected].
bridge.files
Code
data and base64 are base64-encoded file contents — the SDK does not handle raw binary. Files work on both standalone and agent-scoped bridges; on an agent-scoped bridge they are additionally namespaced per agent.
bridge.knowledge
All knowledge.* helpers require an agent-scoped bridge and throw on a standalone one.
Code
KnowledgeDocument.status is one of "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED".
bridge.conversation
Code
Both require an agent-scoped bridge; they throw on a standalone one.
findFirstreturns a single conversation matchingwhere, including its messages (each reduced to{ id, content }) — use it to load one conversation's transcript.findManyreturns a list of the agent's conversations for a Prisma-stylefilter, as a bareConversation[]underdata. It does not include message bodies (fetch those per conversation withfindFirst— they can be large).incognitoandprivateconversations (the latter captured while conversation tracking was off) are never returned, andarchivedones are excluded by default (passwhere: { archived: true }to opt in). The scope is fixed to the bridge's agent, so anagentIdin yourwhereis ignored.
ConversationFilter mirrors PluginDataFilter / KnowledgeDocumentFilter — it accepts where, select, orderBy, skip, take, cursor. A Conversation row (dates are ISO strings) is:
Code
bridge.user
Code
bridge.agent
Code
Returns the Agent record so a plugin can surface the configured LLM model or the Agent's display name (useful for "powered by …" UI chips). The model field is the model ID stored on the Agent (e.g. gpt-4o, claude-3-5-sonnet); it may be an empty string when the Agent inherits the platform default.
The agent is fixed at construction, so getAgent requires an agent-scoped bridge and throws client-side on a standalone one.
Available since @open-agent-kit/[email protected].
decodeToken
Code
Decodes the JWT payload via atob and returns the parsed object. Return shape isn't typed — treat it as the host's session claims.
Using tools inside Apps
The bridge exports a small Tools helper that lets you register executable tools with zod-validated params. Read more about tools in the tools section.
Code
The class exposes three methods:
Code
registerTooladds a tool definition with a zod schema for input validation. Throws ifidentifieris already registered.getToolsreturns the tool list in JSON Schema form — used by the host for federated tool discovery.handleToolExecutionis invoked by the host: it validatesinputagainst the tool's params, builds a bridge from the forwarded headers, and runs yourexecuteimplementation. Apps normally don't call this themselves. It builds the bridge with the tool call'sagentId, sopluginData,config, andknowledgecalls inside a tool are automatically agent-scoped.
Use this when your App exposes server-side tools that the agent can call while a custom view provides the front-end experience.
Tips for custom views
- Keep the
saalt_session_tokensecret; the bridge already sets theAuthorizationheader. - Prefer
pluginDatafor user-generated or view-specific state andconfigfor lightweight settings. - Decode the token with
decodeTokenif you need to inspect the current user inside your view logic. - Default
serverUrlishttps://oak.localhost; override it when the host provides a different origin.