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/svelteSubagents & subgraphs

Subagents & subgraphs

Subagents and subgraphs are discovered eagerly but streamed lazily. The root hook keeps cheap identity snapshots on stream.subagents, stream.subgraphs, and stream.subgraphsByNode. To render a subagent's content, pass its snapshot into a companion selector hook — the subscription is scoped to the subagent's namespace and reference-counted.

Learn more: For deep-agent UI patterns, see the Deep Agents frontend documentation.

Runnable examples: The streaming cookbook streaming package has subagents:*, subagent-status:*, and subgraphs:* scripts, and the a2ui app renders a Deep Agent's output live.

Discovery snapshots

Subagent / subgraph identity is always available from the root:

interface SubagentDiscoverySnapshot {
  readonly id: string; // tool-call id that spawned it
  readonly name: string; // "researcher", "writer", …
  readonly namespace: readonly string[];
  readonly parentId: string | null;
  readonly depth: number;
  readonly status: "pending" | "running" | "complete" | "error";
}

Subgraph snapshots carry the same metadata plus the producing node id:

interface SubgraphDiscoverySnapshot {
  readonly id: string;
  readonly namespace: readonly string[];
  readonly nodeId: string;
  readonly status: "pending" | "running" | "complete" | "error";
}

The root hook exposes three discovery maps:

  • stream.subagents — a ReadonlyMap of SubagentDiscoverySnapshot keyed by id.
  • stream.subgraphs — a ReadonlyMap of SubgraphDiscoverySnapshot keyed by id.
  • stream.subgraphsByNode — the same subgraph snapshots keyed by the producing graph node.

They update live as the server emits discovery events, without opening per-subagent subscriptions.

Rendering subagent content

Pass the snapshot as the target argument to any selector hook. Messages, tool calls, and values stream only for the subagents that are actively rendered:

import {
  useStream,
  useMessages,
  useToolCalls,
  useValues,
  type AnyStream,
  type SubagentDiscoverySnapshot,
} from "@langchain/svelte";

function Researchers({ stream }: { stream: AnyStream }) {
  const researchers = [...stream.subagents.values()].filter((s) => s.name === "researcher");

  return researchers.map((s) => <SubagentCard key={s.id} stream={stream} subagent={s} />);
}

function SubagentCard({
  stream,
  subagent,
}: {
  stream: AnyStream;
  subagent: SubagentDiscoverySnapshot;
}) {
  const messages = useMessages(stream, subagent);
  const toolCalls = useToolCalls(stream, subagent);
  const values = useValues<ResearcherState>(stream, subagent);

  return (
    <section>
      <header>
        {subagent.name} — {subagent.status}
      </header>
      {messages.map((m) => (
        <Bubble key={m.id} msg={m} />
      ))}
    </section>
  );
}

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 — this is the single biggest wire-cost win of the design.

Filtering subagents

To find subagents by status or name, filter the discovery map inline:

const active = [...stream.subagents.values()].filter((s) => s.status === "running");
const researcher = [...stream.subagents.values()].find((s) => s.name === "researcher");

Subgraphs

Subgraph snapshots work the same way. The subgraphsByNode map is handy for laying out nested-graph visualisations:

function NestedGraphView({ stream }: { stream: AnyStream }) {
  return [...stream.subgraphsByNode].map(([nodeId, subgraphs]) => (
    <div key={nodeId}>
      <h3>{nodeId}</h3>
      {subgraphs.map((sg) => (
        <SubgraphCard key={sg.id} stream={stream} subgraph={sg} />
      ))}
    </div>
  ));
}

function SubgraphCard({
  stream,
  subgraph,
}: {
  stream: AnyStream;
  subgraph: SubgraphDiscoverySnapshot;
}) {
  const values = useValues(stream, subgraph);
  return <pre>{JSON.stringify(values, null, 2)}</pre>;
}

API reference

Interfaces

Interface

SubagentDiscoverySnapshot

Lightweight discovery record for a subagent running inside the thread.

Interface

SubgraphDiscoverySnapshot

Lightweight discovery record for a subgraph running inside the thread.

Types

Type

InferSubagentStates

Infer the subagent → state map from a DeepAgent brand. Non-brands