Core Server APIs
Server-side entry points exported from `@sna-sdk/core/server`.
Core Server APIs
Use these APIs when you want to host SNA inside your own server process. The server package exposes the HTTP app, WebSocket attachment, session manager, local port discovery route, and direct one-shot/completion helpers.
| Surface | Purpose |
|---|---|
createSnaApp(options?) | Creates the SNA HTTP application. |
attachWebSocket(server, sessionManager, options?) | Attaches the SNA WebSocket protocol to an existing HTTP server. |
generateSnaAuthToken() | Generates a bearer token for protected HTTP and WebSocket routes. |
SessionManager | Manages server-side agent sessions and lifecycle events. |
snaPortRoute | Exposes the current SNA port for browser auto-discovery. |
runOnce, completion | Direct server-side helpers also re-exported from this entry point. |
Deprecated compatibility route modules under @sna-sdk/core/server/routes/* remain exportable, but new integrations should prefer the server entry point and the generated API reference.
Minimal host example
import { serve } from "@hono/node-server";
import { createSnaApp, attachWebSocket, generateSnaAuthToken, SessionManager } from "@sna-sdk/core/server";
const sessionManager = new SessionManager({ maxSessions: 10 });
const authToken = generateSnaAuthToken();
const app = await createSnaApp({ sessionManager, authToken });
const server = serve({ fetch: app.fetch, port: 3099, hostname: "127.0.0.1" }) as unknown as import("node:http").Server;
attachWebSocket(server, sessionManager, { authToken });Keep the server entry point close to the process that owns the agent lifecycle. Browser clients should connect through @sna-sdk/client or @sna-sdk/react instead of importing server modules.
createSnaApp(options?)
declare function createSnaApp(options?: {
sessionManager?: SessionManager;
authToken?: string;
allowedOrigins?: string[];
unsafeDisableAuth?: boolean;
}): Promise<Hono>;Creates the Hono HTTP application that exposes SNA routes. It delegates to the OpenAPI app factory, so the returned app includes generated OpenAPI metadata and Swagger UI at /docs.
If sessionManager is omitted, the server creates one. Pass your own manager when HTTP routes and WebSocket clients must share the same session state, or when the host needs direct access to lifecycle events.
Authentication is enabled by default. Pass authToken or set
SNA_AUTH_TOKEN; only GET /health remains public. Use
unsafeDisableAuth only for isolated tests or docs generation, never for
a host app. allowedOrigins filters browser Origin values before token
validation, while native clients that send no Origin are allowed.
attachWebSocket(server, sessionManager, options?)
const wss = attachWebSocket(httpServer, sessionManager, { authToken, allowedOrigins });Attaches a WebSocket server to the /ws upgrade path of an existing Node HTTP server. Use the same SessionManager passed to createSnaApp; otherwise HTTP commands and WebSocket subscriptions will observe different session state.
Pass the same authToken and allowedOrigins used by createSnaApp.
The TypeScript client authenticates browser upgrades with ?token=...;
native clients can also send Authorization: Bearer ... or
X-SNA-Token.
The WebSocket server:
| Push | When it is sent |
|---|---|
sessions.snapshot | Immediately on connect and after lifecycle, state, or metadata changes. |
session.lifecycle | When an agent starts, exits, crashes, or is killed. |
session.state-changed | When a session moves between idle, busy, waiting, and permission states. |
session.config-changed | When model, permission mode, or related runtime config changes. |
agent.event | After a client subscribes to a session. |
permission.request | After a client subscribes to permission prompts. |
SessionManager
SessionManager coordinates server-side session records, runtimes, event buffers, persisted history, and lifecycle callbacks.
const sessionManager = new SessionManager({ maxSessions: 10 });Important concepts:
| Concept | Meaning |
|---|---|
| Session record | Durable SNA session metadata: id, label, cwd, meta, config, message counts, and timestamps. |
| Runtime session | The runtime process or runtime handle currently attached to a session. A session can have a runtime chain when config changes require respawn. |
SessionInfo | Public snapshot shape returned to clients. It includes alive, state, agentStatus, cwd, config, counts, last message, and optional runtime chain. |
SessionState | Server state such as idle, processing, waiting, or permission. |
AgentStatus | UI-oriented state: idle, busy, or disconnected. |
Most hosts should let createSnaApp and attachWebSocket use the manager. Reach for the manager directly when the host needs custom lifecycle policy, diagnostics, or coordinated shutdown via killAll().
snaPortRoute
snaPortRoute is a small handler for browser-side discovery:
import { snaPortRoute } from "@sna-sdk/core/server";
app.get("/api/sna-port", snaPortRoute);It reads .sna/sna-api.port from the current working directory and returns { port }. If the file is missing, it responds with HTTP 503 and { port: null, error: "SNA API not running" }.
React integrations use this route when SnaProvider is mounted without an explicit snaUrl.