LangChain Reference home pageLangChain ReferenceLangChain Reference
  • GitHub
  • Main Docs
Deep Agents
LangChain
LangGraph
Integrations
LangSmith
LangGraph
  • Web
  • Channels
  • Pregel
  • Prebuilt
  • Remote
  • Overview
  • Getting started
  • useStream
  • Selectors
  • Interrupts & headless tools
  • Subagents & subgraphs
  • Fork & edit from a checkpoint
  • Submission queue
  • Multimodal media
  • Transports
  • provideStream & context
  • Type safety
  • Migrating to v1
LangGraph SDK
  • Ui
  • Client
  • Auth
  • React
  • Logging
  • React Ui
  • Utils
  • Server
  • Stream
LangGraph Checkpoint
LangGraph Checkpoint MongoDB
LangGraph Checkpoint Postgres
  • Store
LangGraph Checkpoint Redis
  • Shallow
  • Store
LangGraph Checkpoint SQLite
LangGraph Checkpoint Validation
  • Cli
LangGraph API
LangGraph CLI
LangGraph CUA
  • Utils
LangGraph Supervisor
LangGraph Swarm
⌘I

LangChain Assistant

Ask a question to get started

Enter to send•Shift+Enter new line

Menu

LangGraph
WebChannelsPregelPrebuiltRemote
OverviewGetting starteduseStreamSelectorsInterrupts & headless toolsSubagents & subgraphsFork & edit from a checkpointSubmission queueMultimodal mediaTransportsprovideStream & contextType safetyMigrating to v1
LangGraph SDK
UiClientAuthReactLoggingReact UiUtilsServerStream
LangGraph Checkpoint
LangGraph Checkpoint MongoDB
LangGraph Checkpoint Postgres
Store
LangGraph Checkpoint Redis
ShallowStore
LangGraph Checkpoint SQLite
LangGraph Checkpoint Validation
Cli
LangGraph API
LangGraph CLI
LangGraph CUA
Utils
LangGraph Supervisor
LangGraph Swarm
Language
Theme
JavaScript@langchain/svelteMigrating to v1

Migrating to v1

Migrating from @langchain/svelte v0 to v1

@langchain/svelte v1 targets new event-based streaming. The useStream import stays the same, but the option bag, return shape, and how you subscribe to scoped data all change. Most chat apps migrate in well under an hour.

Why the breaking change

The v0 binding was built on the legacy streaming protocol and accreted a large surface of opt-in callbacks (onUpdateEvent, onCustomEvent, onDebugEvent, onCheckpointEvent, …) and derived state (history, branch, experimental_branchTree, activeSubagents, subagents) that had to be recomputed on every update — whether or not any component was rendering it.

v1 flips that around:

  • Always-on root projections. values / messages / toolCalls / interrupts are always reactive at the root with no extra subscription cost beyond the wire.
  • Selector composables for scoped data. Per-subagent / per-subgraph messages, tool calls, and media are only opened when a component actually mounts a selector (useMessages(stream, subagent)), and released on unmount.
  • Discriminated option bag. The LGP branch and the custom-adapter branch are two arms of a discriminated union. Passing LGP-only options like apiUrl, client, or fetch alongside a custom transport: AgentServerAdapter is a compile-time error.
  • Reactive threadId. Pass threadId: () => active to drive in-place thread swaps; everything else is captured at mount.
  • First-class re-attach. Remounting a component on an in-flight thread attaches to the live subscription instead of replaying from scratch.

TL;DR checklist

  • Upgrade @langchain/svelte to ^1.0.0 and @langchain/langgraph-sdk to the matching new event-based streaming runtime.
  • Import useStream only — useStreamExperimental is not exported from this package.
  • Remove the following options — they are gone: onFinish, onUpdateEvent, onCustomEvent, onMetadataEvent, onLangChainEvent, onDebugEvent, onCheckpointEvent, onTaskEvent, onStop, onError, fetchStateHistory, throttle, filterSubagentMessages, subagentToolNames.
  • Replace transport: new FetchStreamTransport(…) with transport: new HttpAgentServerAdapter(…) from @langchain/svelte (or @langchain/langgraph-sdk). The adapter is bound to a concrete threadId.
  • Stop destructuring and reading the following from the return — they moved or were dropped: branch, setBranch, history, experimental_branchTree, getMessagesMetadata, joinStream, switchThread, queue, activeSubagents, getSubagent, getSubagentsByType, getSubagentsByMessage.
  • Read message metadata via useMessageMetadata(stream, () => msg.id) instead of stream.getMessagesMetadata(msg).
  • Read the submission queue via useSubmissionQueue(stream) instead of stream.queue.
  • Drive thread swaps by passing threadId: () => active instead of calling stream.switchThread(id).
  • Read per-subagent data with useMessages(stream, subagent) / useToolCalls(stream, subagent) / useValues(stream, subagent) instead of subagent.messages / subagent.toolCalls.
  • Remove per-submit disconnect options — onDisconnect and streamResumable are gone from submit(). Use stream.stop() (cancel, default) or stream.disconnect() (join/rejoin) instead (see recipe below).
  • Re-run svelte-check / tsc. The option bag and return shape are now strongly discriminated, so most remaining issues surface as type errors mapped to the tables below.

Option bag

v0 option v1 equivalent
assistantId same — required on the LGP branch, defaults to "_" for custom adapters
apiUrl / apiKey same
client same
threadId (static) same; also accepts a getter () => string \| null for reactive swapping
initialValues same
messagesKey same (default "messages")
onThreadId same
onCreated fires with { runId }; read the current thread from stream.threadId when needed
onCompleted convenience callback with { runId?, reason } when active streaming ends
transport now "sse" | "websocket" | an AgentServerAdapter instance. HttpAgentServerAdapter requires apiUrl and threadId.
fetch / webSocketFactory same on the LGP branch only
tools + onTool new headless-tool channel (see Headless tools)
onFinish, onError, onStop hook-level callbacks removed — observe stream.isLoading / stream.error reactively, or pass per-submit onError to submit(). Use stream.stop() / stream.disconnect() instead of onStop (see recipe below).
onDisconnect, streamResumable (on submit) removed from submit — use stream.stop() (cancel, default) or stream.disconnect() (join/rejoin) on the stream handle
onUpdateEvent, onCustomEvent, onDebugEvent, onCheckpointEvent, onTaskEvent, onMetadataEvent, onLangChainEvent removed — use useChannel for raw events or the dedicated selector composables
fetchStateHistory removed — fork / branch flows are driven by useMessageMetadata
throttle removed — the controller batches its own notifications
filterSubagentMessages, subagentToolNames removed — subagent views are per-namespace via useMessages(stream, sub)

Return-shape changes

v0 field / method v1 equivalent
values, messages, isLoading, error, interrupt, interrupts same
threadId same
isThreadLoading same — plus hydrationPromise for SvelteKit load() handlers
submit(values, options?) same — returns Promise<void>; options now include forkFrom, per-submit threadId, per-submit onError, and multitaskStrategy
stop(options?) cancels the active run server-side by default ({ cancel: true }); pass { cancel: false } or call disconnect() for join/rejoin
disconnect() new — alias for stop({ cancel: false }); agent keeps running server-side
client, assistantId same
toolCalls same — assembled tool-call rows at the root
subagents, subgraphs, subgraphsByNode new — discovery snapshots (namespaces). Use them as the target argument to selector composables
respond(response, options?) / respondAll(responsesById, options?) new — resume the agent after an interrupt (respondAll resumes several at the same checkpoint)
getThread() new — returns the bound ThreadStream for low-level protocol access
branch, setBranch removed — there is no global branch pointer with new event-based streaming. Fork flows use submit(input, { forkFrom }) and parentCheckpointId from useMessageMetadata.
history, experimental_branchTree removed — pull history via the Client directly when needed
getMessagesMetadata(msg) useMessageMetadata(stream, () => msg.id) → { parentCheckpointId }
joinStream(...) removed — useStream attaches automatically on mount
switchThread(id) pass threadId: () => active as a getter; update the underlying state
queue.* useSubmissionQueue(stream) → { entries, size, cancel, clear }
activeSubagents, getSubagent, getSubagentsByType, getSubagentsByMessage drop — read through stream.subagents (ReadonlyMap) plus selector composables

Recipes

Replace getMessagesMetadata

<!-- v0 -->
<script lang="ts">
  const meta = stream.getMessagesMetadata(msg, i);
  const parent = meta?.firstSeenState?.parent_checkpoint;
</script>

<!-- v1 -->
<script lang="ts">
  import { useMessageMetadata } from "@langchain/svelte";
  const meta = useMessageMetadata(stream, () => msg.id);
</script>
Parent: {meta.current?.parentCheckpointId ?? "root"}

Replace stream.queue

<script lang="ts">
  import { useSubmissionQueue } from "@langchain/svelte";
  const queue = useSubmissionQueue(stream);
</script>

{#if queue.size > 0}
  <p>{queue.size} run(s) pending</p>
  <button onclick={() => queue.clear()}>Clear</button>
{/if}

Replace stream.switchThread(id)

<script lang="ts">
  let active = $state<string | null>(null);
  const stream = useStream({
    assistantId: "agent",
    apiUrl: "http://localhost:2024",
    threadId: () => active,
  });
</script>

<button onclick={() => (active = crypto.randomUUID())}>New thread</button>

Passing null clears the thread; the next submit() creates a fresh one.

Replace onDisconnect / join-rejoin stop

<!-- v0 — disconnect policy on submit -->
<script lang="ts">
  await stream.submit(input, { onDisconnect: "continue", streamResumable: true });
  // stream.stop() only aborted the client
</script>

<!-- v1 — explicit stop vs disconnect -->
<script lang="ts">
  await stream.submit(input);
  await stream.stop();        // chat cancel (server + client)
  await stream.disconnect();  // join/rejoin (client only)
</script>

runs.cancel is issued only once onCreated has provided a runId.

Replace custom transports

<script lang="ts">
  import { HttpAgentServerAdapter, useStream } from "@langchain/svelte";

  const stream = useStream({
    transport: new HttpAgentServerAdapter({
      apiUrl: "/api/agent",
      threadId: "thread-123",
      defaultHeaders: { Authorization: `Bearer ${token}` },
    }),
  });
</script>

When transport is an AgentServerAdapter, LGP-specific options like client, apiUrl, apiKey, fetch, and webSocketFactory are not accepted on the useStream option bag; the adapter owns those details. assistantId remains optional for adapters that multiplex internally.

Multitask strategies

"rollback" remains the default. "reject" errors client-side when a run is already in flight, and "enqueue" records the submission in the client queue exposed by useSubmissionQueue(stream). "interrupt" is accepted by the type surface and currently falls back to "rollback" until server-side interrupt semantics land.

Replace subagent fan-out

<!-- v0 -->
{#each stream.activeSubagents as sub (sub.id)}
  {#each sub.messages as msg (msg.id)}
    <div>{msg.content}</div>
  {/each}
{/each}

<!-- v1 -->
<script lang="ts">
  import { useMessages } from "@langchain/svelte";
</script>
{#each [...stream.subagents.values()] as sub (sub.namespace.join("/"))}
  {@const subMessages = useMessages(stream, sub)}
  {#each subMessages.current as msg (msg.id)}
    <div>{msg.content}</div>
  {/each}
{/each}

Each mounted useMessages(stream, sub) opens a ref-counted namespace subscription on demand and releases it on unmount.

provideStream / getStream

Share one useStream handle across a subtree with Svelte context:

<!-- ChatContainer.svelte -->
<script lang="ts">
  import { provideStream } from "@langchain/svelte";

  provideStream({
    assistantId: "agent",
    apiUrl: "http://localhost:2024",
  });
</script>

<ChatHeader />
<MessageList />
<!-- MessageList.svelte -->
<script lang="ts">
  import { getStream, useMessages } from "@langchain/svelte";

  const stream = getStream();
  const messages = useMessages(stream);
</script>

{#each messages.current as msg (msg.id)}
  <div>{msg.content}</div>
{/each}

Call provideStream during component initialisation (top-level <script>). Descendants read the shared handle with getStream().

Type helpers

Helper Use
UseStreamReturn<T> Fully-resolved return type of useStream<T>.
AnyStream Type-erased handle (UseStreamReturn<any, any, any>) for components that only forward the stream to selector composables.
UseStreamOptions Discriminated options union (LGP branch vs custom AgentServerAdapter); rarely needed at call sites.
InferStateType<T> Unwraps a compiled graph / agent brand into its state shape.
UseSubmissionQueueReturn Return shape of useSubmissionQueue(stream) (entries, size, cancel, clear).