CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-langchain--langgraph

Low-level orchestration framework for building stateful, multi-actor applications with LLMs

Overview
Eval results
Files

graph-construction-full.mddocs/api/

Graph Construction

Graph construction in LangGraph involves defining workflows using StateGraph or Graph classes, along with the Annotation system for type-safe state management. These APIs enable building complex, stateful workflows with nodes, edges, and conditional routing.

Core Classes

StateGraph

High-level graph API with automatic state management through channels. StateGraph provides typed state management where nodes communicate by reading from and writing to shared state channels.

class StateGraph<
  StateDefinition,
  S = StateType<StateDefinition>,
  U = UpdateType<StateDefinition>,
  N extends string = typeof START,
  InputDefinition = StateDefinition,
  OutputDefinition = StateDefinition,
  ContextDefinition = StateDefinition,
  NodeReturnType = unknown,
  InterruptType = unknown,
  WriterType = unknown
> {
  constructor(
    state: AnnotationRoot<StateDefinition> | InteropZodObject,
    options?: {
      context?: ContextDefinition | AnnotationRoot<ContextDefinition>;
      input?: InputDefinition | AnnotationRoot<InputDefinition>;
      output?: OutputDefinition | AnnotationRoot<OutputDefinition>;
      interrupt?: InterruptType;
      writer?: WriterType;
      nodes?: N[];
    }
  );

  addNode<K extends string>(
    key: K,
    action: RunnableLike<S, U>,
    options?: StateGraphAddNodeOptions
  ): StateGraph<StateDefinition, S, U, N | K, InputDefinition, OutputDefinition, ContextDefinition, NodeReturnType>;

  addNode<K extends string>(
    nodes: Record<K, RunnableLike<S, U>>
  ): StateGraph<StateDefinition, S, U, N | K, InputDefinition, OutputDefinition, ContextDefinition, NodeReturnType>;

  addNode<K extends string>(
    nodes: [key: K, action: RunnableLike<S, U>, options?: StateGraphAddNodeOptions][]
  ): StateGraph<StateDefinition, S, U, N | K, InputDefinition, OutputDefinition, ContextDefinition, NodeReturnType>;

  addEdge(
    startKey: typeof START | N | N[],
    endKey: N | typeof END
  ): this;

  addConditionalEdges(
    source: N,
    path: RunnableLike<S, string | string[] | Send | Send[]>,
    pathMap?: Record<string, N | typeof END> | (N | typeof END)[]
  ): this;

  addConditionalEdges(
    options: {
      source: N;
      path: RunnableLike<S, string | string[] | Send | Send[]>;
      pathMap?: Record<string, N | typeof END> | (N | typeof END)[];
    }
  ): this;

  addSequence<K extends string>(
    nodes: Record<K, RunnableLike<S, U>>
  ): StateGraph<StateDefinition, S, U, N | K, InputDefinition, OutputDefinition, ContextDefinition, NodeReturnType>;

  addSequence<K extends string>(
    nodes: [key: K, action: RunnableLike<S, U>, options?: StateGraphAddNodeOptions][]
  ): StateGraph<StateDefinition, S, U, N | K, InputDefinition, OutputDefinition, ContextDefinition, NodeReturnType>;

  setEntryPoint(name: N): this;

  setFinishPoint(name: N): this;

  compile(options?: {
    checkpointer?: BaseCheckpointSaver | boolean;
    store?: BaseStore;
    cache?: BaseCache;
    interruptBefore?: N[] | All;
    interruptAfter?: N[] | All;
    name?: string;
    description?: string;
  }): CompiledStateGraph<S, U, N, InputDefinition, OutputDefinition, ContextDefinition, NodeReturnType, InterruptType, WriterType>;
}

Graph

Lower-level graph class for workflow definition without automatic state management. Provides manual control over node communication and state handling.

class Graph<
  N extends string = typeof START | typeof END,
  RunInput = any,
  RunOutput = any,
  NodeSpecType extends NodeSpec<RunInput, RunOutput> = NodeSpec<RunInput, RunOutput>,
  ContextDefinition extends StateDefinition = StateDefinition
> {
  nodes: Record<N, NodeSpecType>;
  edges: Set<[N | typeof START, N | typeof END]>;
  branches: Record<string, Record<string, Branch<RunInput, N>>>;

  constructor();

  addNode<K extends string>(
    key: K,
    action: RunnableLike<RunInput, RunOutput>,
    options?: AddNodeOptions
  ): Graph<N | K, RunInput, RunOutput>;

  addNode<K extends string>(
    nodes: Record<K, RunnableLike<RunInput, RunOutput>>
  ): Graph<N | K, RunInput, RunOutput>;

  addNode<K extends string>(
    nodes: [key: K, action: RunnableLike<RunInput, RunOutput>, options?: AddNodeOptions][]
  ): Graph<N | K, RunInput, RunOutput>;

  addEdge(
    startKey: N | typeof START,
    endKey: N | typeof END
  ): this;

  addConditionalEdges(
    source: N,
    path: RunnableLike<RunInput, string | Send | (string | Send)[]>,
    pathMap?: Record<string, N | typeof END> | (N | typeof END)[]
  ): this;

  addConditionalEdges(
    options: BranchOptions<RunInput, N>
  ): this;

  setEntryPoint(key: N): this;

  setFinishPoint(key: N): this;

  compile(options?: {
    checkpointer?: BaseCheckpointSaver | false;
    interruptBefore?: N[] | All;
    interruptAfter?: N[] | All;
    name?: string;
  }): CompiledGraph<N>;

  validate(interrupt?: string[]): void;
}

CompiledStateGraph

Compiled executable graph from StateGraph. Extends Pregel with state management capabilities.

class CompiledStateGraph<
  S,
  U,
  N extends string = typeof START,
  InputDefinition = StateDefinition,
  OutputDefinition = StateDefinition,
  ContextDefinition = StateDefinition,
  NodeReturnType = unknown,
  InterruptType = unknown,
  WriterType = unknown
> extends CompiledGraph<N, S, U> {
  description?: string;

  invoke(
    input: UpdateType<InputDefinition>,
    options?: PregelOptions
  ): Promise<StateType<OutputDefinition>>;

  stream(
    input: UpdateType<InputDefinition>,
    options?: PregelOptions
  ): IterableReadableStream;

  streamEvents(
    input: UpdateType<InputDefinition>,
    options: PregelOptions
  ): IterableReadableStream;

  getState(
    config: LangGraphRunnableConfig,
    options?: GetStateOptions
  ): Promise<StateSnapshot>;

  getStateHistory(
    config: LangGraphRunnableConfig,
    options?: CheckpointListOptions
  ): AsyncIterableIterator<StateSnapshot>;

  updateState(
    config: LangGraphRunnableConfig,
    values: UpdateType<InputDefinition> | Command,
    asNode?: N
  ): Promise<RunnableConfig>;

  isInterrupted(input: unknown): input is {
    [INTERRUPT]: Interrupt<InferInterruptInputType<InterruptType>>[];
  };
}

CompiledGraph

Compiled executable graph from Graph class. Provides core execution capabilities.

class CompiledGraph<
  N extends string,
  State = any,
  Update = any,
  ContextType extends Record<string, any> = Record<string, any>,
  InputType = any,
  OutputType = any,
  NodeReturnType = unknown,
  CommandType = unknown,
  StreamCustomType = any
> extends Pregel<...> {
  builder: Graph<N, State, Update>;

  invoke(
    input: InputType,
    options?: PregelOptions
  ): Promise<OutputType>;

  stream(
    input: InputType,
    options?: PregelOptions
  ): IterableReadableStream;

  getGraph(
    config?: RunnableConfig & { xray?: boolean | number }
  ): DrawableGraph;

  getGraphAsync(
    config?: RunnableConfig & { xray?: boolean | number }
  ): Promise<DrawableGraph>;
}

Annotation System

Annotation

Factory for creating typed state annotations. The Annotation system provides type-safe state definitions with automatic type inference.

interface AnnotationFunction {
  <ValueType>(): LastValue<ValueType>;

  <ValueType, UpdateType = ValueType>(
    annotation: SingleReducer<ValueType, UpdateType>
  ): BinaryOperatorAggregate<ValueType, UpdateType>;

  Root: <S extends StateDefinition>(
    spec: S
  ) => AnnotationRoot<S>;
}

const Annotation: AnnotationFunction;

Usage examples:

// Simple field without reducer (last value wins)
const SimpleAnnotation = Annotation.Root({
  count: Annotation<number>
});

// Field with reducer for aggregation
const AnnotationWithReducer = Annotation.Root({
  messages: Annotation<BaseMessage[]>({
    reducer: (left, right) => left.concat(right),
    default: () => []
  }),
  total: Annotation<number>({
    reducer: (a, b) => a + b,
    default: () => 0
  })
});

AnnotationRoot

Root state annotation wrapper providing State/Update/Node type inference.

class AnnotationRoot<StateDefinition extends StateDefinition> {
  lc_graph_name: "AnnotationRoot";
  spec: StateDefinition;

  declare State: StateType<StateDefinition>;
  declare Update: UpdateType<StateDefinition>;
  declare Node: NodeType<StateDefinition>;

  constructor(spec: StateDefinition);
}

SingleReducer

State reducer function type for combining state updates.

type SingleReducer<ValueType, UpdateType = ValueType> =
  | {
      reducer: BinaryOperator<ValueType, UpdateType>;
      default?: () => ValueType;
    }
  | {
      value: BinaryOperator<ValueType, UpdateType>;
      default?: () => ValueType;
    }
  | null;

type BinaryOperator<ValueType, UpdateType> = (
  a: ValueType,
  b: UpdateType
) => ValueType;

Message Handling

Messages Type

Type definition for message inputs to message-based workflows.

type Messages =
  | Array<BaseMessage | BaseMessageLike>
  | BaseMessage
  | BaseMessageLike;

MessageGraph

Legacy graph class specialized for message handling. Prefer using StateGraph with MessagesAnnotation for new code.

class MessageGraph extends StateGraph<
  BaseMessage[],
  BaseMessage[],
  Messages
> {
  constructor();
}

REMOVE_ALL_MESSAGES

Special constant used with RemoveMessage to remove all messages from state.

const REMOVE_ALL_MESSAGES: "__remove_all__";

Usage

import { RemoveMessage, REMOVE_ALL_MESSAGES } from "@langchain/langgraph";

// Remove all messages from state
const removeAllMessage = new RemoveMessage({ id: REMOVE_ALL_MESSAGES });

// Use in a node
const clearMessages = (state: any) => {
  return {
    messages: [new RemoveMessage({ id: REMOVE_ALL_MESSAGES })]
  };
};

State Type Utilities

Type utilities for extracting types from state definitions.

interface StateDefinition {
  [key: string]: BaseChannel | (() => BaseChannel);
}

type StateType<SD extends StateDefinition> = {
  [key in keyof SD]: ExtractValueType<SD[key]>;
};

type UpdateType<SD extends StateDefinition> = {
  [key in keyof SD]?: ExtractUpdateType<SD[key]>;
};

type NodeType<SD extends StateDefinition> = RunnableLike<
  StateType<SD>,
  UpdateType<SD> | Partial<StateType<SD>>
>;

Node Options

Options for adding nodes to graphs.

interface StateGraphAddNodeOptions<Nodes extends string = string> {
  retryPolicy?: RetryPolicy;
  cachePolicy?: CachePolicy | boolean;
  input?: AnnotationRoot<any> | InteropZodObject;
  metadata?: Record<string, unknown>;
  subgraphs?: Pregel<any, any>[];
  ends?: Nodes[];
  defer?: boolean;
}

interface AddNodeOptions<Nodes extends string = string> {
  metadata?: Record<string, unknown>;
  subgraphs?: Pregel<any, any>[];
  ends?: Nodes[];
  defer?: boolean;
}

interface NodeSpec<RunInput, RunOutput> {
  runnable: Runnable<RunInput, RunOutput>;
  metadata?: Record<string, unknown>;
  subgraphs?: Pregel<any, any>[];
  ends?: string[];
  defer?: boolean;
}

Conditional Routing

Branch

Conditional edge implementation for dynamic routing.

class Branch<
  IO,
  N extends string,
  CallOptions extends LangGraphRunnableConfig = LangGraphRunnableConfig
> {
  path: Runnable<IO, BranchPathReturnValue, CallOptions>;
  ends?: Record<string, N | typeof END>;

  constructor(options: {
    path: RunnableLike<IO, BranchPathReturnValue, CallOptions>;
    pathMap?: Record<string, N | typeof END> | (N | typeof END)[];
  });

  run(
    writer: (dests: (string | Send)[], config: LangGraphRunnableConfig) => Runnable | void | Promise<void>,
    reader?: (config: CallOptions) => IO
  ): ChannelWrite;
}

type BranchPathReturnValue =
  | string
  | Send
  | (string | Send)[]
  | Promise<string | Send | (string | Send)[]>;

interface BranchOptions<IO, N extends string> {
  source: N;
  path: RunnableLike<IO, BranchPathReturnValue>;
  pathMap?: Record<string, N | typeof END> | (N | typeof END)[];
}

Special Node Names

Reserved node identifiers for graph flow control.

const START: "__start__";
const END: "__end__";

Usage Examples

Basic StateGraph with Annotation

import { StateGraph, Annotation, START, END } from "@langchain/langgraph";

// Define state using Annotation
const StateAnnotation = Annotation.Root({
  messages: Annotation<string[]>({
    reducer: (current, update) => [...current, ...update],
    default: () => []
  }),
  count: Annotation<number>({
    reducer: (_, update) => update,
    default: () => 0
  })
});

// Create nodes
const processNode = (state: typeof StateAnnotation.State) => {
  return {
    messages: [`Processed ${state.count} items`],
    count: state.count + 1
  };
};

// Build graph
const graph = new StateGraph(StateAnnotation)
  .addNode("process", processNode)
  .addEdge(START, "process")
  .addEdge("process", END);

// Compile and execute
const app = graph.compile();
const result = await app.invoke({
  messages: ["Hello"],
  count: 0
});
// { messages: ["Hello", "Processed 0 items"], count: 1 }

Conditional Edges

import { StateGraph, Annotation, START, END } from "@langchain/langgraph";

const StateAnnotation = Annotation.Root({
  value: Annotation<number>
});

const graph = new StateGraph(StateAnnotation)
  .addNode("check", (state) => state)
  .addNode("positive", (state) => ({ value: state.value * 2 }))
  .addNode("negative", (state) => ({ value: state.value * -1 }))
  .addEdge(START, "check")
  .addConditionalEdges(
    "check",
    (state) => (state.value > 0 ? "positive" : "negative"),
    {
      positive: "positive",
      negative: "negative"
    }
  )
  .addEdge("positive", END)
  .addEdge("negative", END);

const app = graph.compile();
await app.invoke({ value: 5 }); // { value: 10 }
await app.invoke({ value: -3 }); // { value: 3 }

Multiple State Definitions

import { StateGraph, Annotation } from "@langchain/langgraph";

// Define different state schemas for input, internal state, and output
const InternalState = Annotation.Root({
  messages: Annotation<string[]>({
    reducer: (a, b) => a.concat(b),
    default: () => []
  }),
  internalCounter: Annotation<number>
});

const InputState = Annotation.Root({
  messages: Annotation<string[]>
});

const OutputState = Annotation.Root({
  messages: Annotation<string[]>
});

// Create graph with different input/output schemas
const graph = new StateGraph(InternalState, {
  input: InputState,
  output: OutputState
})
  .addNode("process", (state) => ({
    messages: ["processed"],
    internalCounter: (state.internalCounter || 0) + 1
  }))
  .addEdge(START, "process")
  .addEdge("process", END)
  .compile();

// Input only requires messages
await graph.invoke({ messages: ["hello"] });
// Output only includes messages (internalCounter is filtered)

Sequence Helper

import { StateGraph, Annotation, START, END } from "@langchain/langgraph";

const State = Annotation.Root({
  value: Annotation<number>
});

// Add multiple nodes in sequence automatically
const graph = new StateGraph(State)
  .addSequence([
    ["step1", (s) => ({ value: s.value + 1 })],
    ["step2", (s) => ({ value: s.value * 2 })],
    ["step3", (s) => ({ value: s.value + 10 })]
  ])
  .addEdge(START, "step1")
  .addEdge("step3", END)
  .compile();

await graph.invoke({ value: 5 });
// Executes: ((5 + 1) * 2) + 10 = 22

Zod Integration

import { StateGraph } from "@langchain/langgraph";
import { z } from "zod";

// Use Zod schemas for state validation
const StateSchema = z.object({
  count: z.number().default(0),
  messages: z.array(z.string()).default([])
});

const graph = new StateGraph(StateSchema)
  .addNode("increment", (state) => ({
    count: state.count + 1,
    messages: state.messages.concat(["incremented"])
  }))
  .addEdge(START, "increment")
  .addEdge("increment", END)
  .compile();

// Input is validated against schema
await graph.invoke({ count: 5 });
// { count: 6, messages: ["incremented"] }

Install with Tessl CLI

npx tessl i tessl/npm-langchain--langgraph@1.0.1

docs

api

channels.md

control-flow-api.md

execution-api.md

functional-api.md

graph-api.md

graph-construction-full.md

imports.md

persistence-api.md

persistence-full.md

prebuilt.md

remote.md

state-management.md

types.md

zod.md

index.md

tile.json