SNA

Streaming completions

Three ways to stream text from one-shot prompts.

SNA exposes streaming for one-shot calls in three flavors. Pick by host (in-process vs network) and shape (text-only vs full events).

1. In-process, text-only: completion({ onDelta })

Cheapest, simplest. Used for autocomplete previews and typewriter UX where you just need the text deltas.

import { completion } from "@sna-sdk/core";

await completion({
  prompt: "Draft a commit message for: ...",
  provider: "claude-code",
  model: "claude-haiku-4-5",
  onDelta: (chunk) => process.stdout.write(chunk),
});

The Promise still resolves with the final concatenated text plus usage; onDelta is a side channel, not a replacement.

Wired for claude-code, codex, opencode, grok-build, and cursor. OpenCode switches to prompt_async plus the event stream when onDelta is present; without it, complete() keeps the lower-overhead sync SDK path.

2. In-process, full event stream: runOnce({ onEvent })

When you need tool_use / thinking / permission_needed events on a one-shot run.

import { runOnce } from "@sna-sdk/core/server";

await runOnce(sessionManager, {
  message: "List the markdown files and summarize each.",
  provider: "codex",
  onEvent: (event) => {
    if (event.type === "assistant_delta") render(event.delta);
    if (event.type === "tool_use") showToolCard(event);
  },
});

A onDelta-only variant is also accepted if you don't care about non-text events.

3. Network: runOnceStream over SSE

For browser / Electron renderer / remote clients that can't import @sna-sdk/core directly.

for await (const event of client.agent.runOnceStream({
  message: "Draft a commit message for: ...",
})) {
  if (event.type === "assistant_delta") write(event.delta as string);
  if (event.type === "complete") console.log("usage", event.data);
}

Backed by POST /agent/run-once/stream (Server-Sent Events). The stream closes after the run's terminal complete / error event.

Which one should I use?

SituationAPI
Same process as the SNA server, text onlycompletion({ onDelta })
Same process, full event streamrunOnce({ onEvent })
Remote (browser, separate Node host)runOnceStream()
Long-running multi-turn UIOpen a session and use WS agent.subscribe instead

On this page