LangChain Reference home pageLangChain ReferenceLangChain Reference
  • GitHub
  • Main Docs
Deep Agents
LangChain
LangGraph
Integrations
LangSmith
  • Overview
  • Getting started
  • useStream
  • Selectors
  • Interrupts & headless tools
  • Subagents & subgraphs
  • Fork & edit from a checkpoint
  • Submission queue
  • Multimodal media
  • Transports
  • Suspense
  • provideStream & context
  • Type safety
  • Migrating to v1
LangGraph SDK
  • Client
  • Auth
  • React
  • Logging
  • React Ui
  • Server
LangGraph Checkpoint
LangGraph Checkpoint MongoDB
LangGraph Checkpoint Postgres
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

OverviewGetting starteduseStreamSelectorsInterrupts & headless toolsSubagents & subgraphsFork & edit from a checkpointSubmission queueMultimodal mediaTransportsSuspenseprovideStream & contextType safetyMigrating to v1
LangGraph SDK
ClientAuthReactLoggingReact UiServer
LangGraph Checkpoint
LangGraph Checkpoint MongoDB
LangGraph Checkpoint Postgres
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/vueSelectors

Selectors

The root useStream handle exposes always-on projections (values, messages, toolCalls, interrupts, error, isLoading, discovery maps). Anything scoped to a subagent, subgraph, or namespace lives behind a companion selector composable.

Selectors are ref-counted: the first caller opens a subscription, and the last consumer's Vue scope disposal closes it. Root calls (no target) are free — they read the already-mounted root projection directly.

How targeting works

All scoped selectors accept a target argument. Valid targets are:

  • undefined (or omitted) — the root namespace. Free read.
  • A SubagentDiscoverySnapshot — as exposed via stream.subagents.value.values().
  • A SubgraphDiscoverySnapshot — as exposed via stream.subgraphs / stream.subgraphsByNode.
  • { namespace: string[] } (or a raw string[]) — an explicit namespace, useful for custom routing.
  • A ref / computed / getter over any of those — projections rebind automatically when the target changes.

Subscriptions open on mount and close when the last consumer for a given (channel, namespace) tuple unmounts. Components that don't render a subagent's content never pay for its wire traffic.

Full composable list

Composable Returns Use for
useValues(stream, target?) StateType (root) / T \| undefined (scoped) Arbitrary state / scoped snapshot.
useMessages(stream, target?) BaseMessage[] Message stream, root or scoped.
useToolCalls(stream, target?) AssembledToolCall[] Tool-call stream, with per-call status.
useMessageMetadata(stream, msgId) ComputedRef<{ parentCheckpointId } \| undefined> Powers fork / edit flows.
useSubmissionQueue(stream) { entries, size, cancel, clear } Reactive client-side submission queue.
useExtension(stream, name, target?) T \| undefined Read a named custom:<name> extension.
useChannel(stream, channels, target?, options?) Event[] Low-level raw-events escape hatch, buffered for rendering.
useChannelEffect(stream, channels, options) void Per-event side effects such as analytics; no re-render.
useAudio / useImages / useVideo / useFiles AudioMedia[] / ImageMedia[] / VideoMedia[] / FileMedia[] Assembled multimodal streams. See Multimodal.
useMediaURL(handle) string \| undefined Turns a media handle into an <img/audio/video src>.
useAudioPlayer(handle, options?) / useVideoPlayer(handle, options?) Player handles Opinionated playback helpers on top of the media hooks.

Root vs. scoped example

<script setup lang="ts">
import { computed } from "vue";
import { useStream, useMessages, useValues } from "@langchain/vue";

const stream = useStream({ assistantId: "agent", apiUrl: "/api" });

// Root projections — identical to `stream.messages` / `stream.values`.
// These calls are free: no new subscription is opened.
const rootMessages = useMessages(stream);
const rootValues = useValues(stream);

// Selector composables return refs in script.
const latestMessage = computed(() => rootMessages.value.at(-1));
const hasValues = computed(() => rootValues.value != null);
</script>

<template>
  <ThreadView :messages="rootMessages" />
  <SubagentCard
    v-for="subagent in [...stream.subagents.value.values()]"
    :key="subagent.id"
    :stream="stream"
    :subagent="subagent"
  />
</template>

Scoped reads open a namespaced subscription on mount. See Subagents for a full component example.

useMessageMetadata

Returns { parentCheckpointId } (and undefined while loading). Use it to drive fork / edit UIs:

<script setup lang="ts">
import { HumanMessage, type BaseMessage } from "@langchain/core/messages";
import { useMessageMetadata, type AnyStream } from "@langchain/vue";

const props = defineProps<{ stream: AnyStream; message: BaseMessage }>();
const metadata = useMessageMetadata(props.stream, () => props.message.id);

function edit() {
  const forkFrom = metadata.value?.parentCheckpointId;
  if (!forkFrom) return;
  void props.stream.submit({ messages: [new HumanMessage("...revised prompt...")] }, { forkFrom });
}
</script>

<template>
  <button :disabled="!metadata?.parentCheckpointId" @click="edit">Edit from here</button>
</template>

See Fork & edit from a checkpoint for the full flow.

useChannel

Escape hatch to the raw protocol event stream. Subscribe to one or more channels and get the buffered events as an array:

const events = useChannel(stream, ["values", "updates"]);

Pass target (subagent / subgraph / { namespace }) to scope. Useful for bespoke reducers that can't be expressed through useValues / useMessages.

useExtension

Read a single custom extension (wire-level custom:<name> channel) as a reactive snapshot:

const telemetry = useExtension<Telemetry>(stream, "telemetry");

Runnable example: The a2ui app in the streaming cookbook drives a generative UI with useExtension(stream, "a2ui"); the streaming package's custom-transformer:* scripts show the server side.

Per-event side effects via useChannelEffect

useChannel is for events you render. When you instead want to react to each event — fire analytics, write a log — use useChannelEffect. It invokes onEvent once per event and returns nothing, so it never re-renders the component:

<script setup lang="ts">
import { useChannelEffect } from "@langchain/vue";

useChannelEffect(stream, ["lifecycle", "tools"], {
  replay: false,
  onEvent(event) {
    sendAnalytics(event);
  },
  onError(error) {
    logger.error(error);
  },
});
</script>

channels, target, and enabled accept refs / getters so reactive state re-binds the subscription. The subscription is shared (ref-counted) with any matching useChannel, so you only pay for one server subscription per channel set. replay defaults to false (live-only); events buffered before the effect attaches are not re-delivered.

useProjection — building your own selector

useProjection is the low-level primitive every built-in selector is composed from. Reach for it only when you need a custom projection that the built-in hooks don't express. It acquires a ref-counted projection from the stream's channel registry and binds it to the current Vue scope:

import { useProjection } from "@langchain/vue";
import { STREAM_CONTROLLER } from "@langchain/vue"; // low-level access key
import { valuesProjection } from "@langchain/langgraph-sdk/stream";

function useScoredValues<T>(stream: AnyStream, namespace: readonly string[]) {
  const registry = stream[STREAM_CONTROLLER].registry;
  return useProjection<T | undefined>(
    registry,
    () => valuesProjection<T>(namespace, "messages"),
    `values|${namespace.join(">")}`,
    undefined,
  );
}

The first read returns initialValue. Subsequent updates read from the acquired store. When the calling Vue scope is disposed (component unmount, effectScope.stop(), etc.), the reference count drops; when the last consumer of a given key unmounts, the underlying server subscription is released automatically. Most apps never need this — prefer useValues / useMessages / useToolCalls / useChannel.

API reference

Functions

Function

useValues

Subscribe to a scoped values stream — the most recent state

Function

useMessages

Subscribe to a scoped messages stream.

Function

useToolCalls

Subscribe to a scoped tools (tool-call) stream. Same target and

Function

useMessageMetadata

Read metadata recorded for a specific message id — today exposes

Function

useSubmissionQueue

Function

useExtension

Subscribe to a custom:<name> stream extension — the most-recent

Function

useChannel

Function

useChannelEffect

Side-effect counterpart to useChannel. Instead of returning a

Function

useProjection

Vue primitive that composes ChannelRegistry.acquire with

Interfaces

Interface

UseSubmissionQueueReturn

Reactive handle on the server-side submission queue.

Interface

SubmissionQueueEntry

Queued submission entry mirrored from the server-side run queue.

Types

Type

SelectorTarget

What a selector composable can be targeted at. Callers can pass:

Type

SubmissionQueueSnapshot

Read-only snapshot of the queue. The queue store hands this out