Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

AI Agents · Const

Annotation

Annotation declares channels for StateGraph state. Use it directly for replacement semantics or configure a reducer to combine node updates.

How it works

Annotation creates channels for fields in an Annotation.Root state schema. A field can either keep the latest node update or use a reducer to combine the existing value with each update; an optional default supplies its initial value.

Syntax

Annotation<T>(config?)
Annotation.Root(spec)

Parameters

NameTypeDescription
value/configurationT or Annotation<T> configurationThe channel's value type, optionally followed by reducer and default configuration.
specAnnotationRootSpecAn object mapping state field names to annotations, passed to Annotation.Root.

Returns

An annotation channel for a state field, or an annotation root when used through Annotation.Root.

Key points

  • Annotation is the helper for declaring the channels that make up a StateGraph state schema.
  • Place Annotation fields inside Annotation.Root to define the graph's state shape.
  • The direct form uses last-write behavior: the newest node update replaces the previous channel value.
  • The reducer form lets a field aggregate updates rather than simply replacing its prior value.
  • Use the root annotation's generated State type to type a node's state parameter.

Common mistakes

  • Without a reducer, a field is overwritten by the latest value returned for that channel.
  • A reducer changes the update behavior, so its implementation must combine the current value and incoming update correctly.

Example: Define state with Annotation

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

const State = Annotation.Root({
  input: Annotation<string>,
  output: Annotation<string>({
    reducer: (current, update) => `${current}\n${update}`,
    default: () => "",
  }),
});

const graph = new StateGraph(State)
  .addNode("respond", (state) => ({ output: `Answer: ${state.input}` }))
  .addEdge("__start__", "respond")
  .addEdge("respond", "__end__")
  .compile();

const result = await graph.invoke({ input: "Hello" });
console.log(result.output);

Defines graph state with a direct channel and a reducer-backed channel, then runs a node that writes an output value.

When to use it

Declare graph state

A graph needs a typed state schema shared by its nodes.

Aggregate updates with a reducer

Several nodes contribute to one field, such as accumulated messages or text.

Type node state

A node should return a precisely typed partial state update.

Interview questions

QWhat does Annotation do in LangGraph.js?

Annotation defines channels used by a StateGraph state schema. With a direct annotation, a node's returned value becomes the channel's current value.

Follow-up: How would you preserve multiple node updates? Define the field with a reducer, then combine the existing value and each incoming update in that reducer.

QHow is Annotation used with StateGraph?

Use Annotation.Root to wrap an object whose fields are annotated channels. The resulting root annotation can be passed to StateGraph, and its State type can be used to type node input.

Follow-up: How can a node update only part of the state? Return an object containing only the fields that node changes; the graph applies each field's channel behavior.

QWhen should a field use a reducer or default value?

A reducer-backed annotation applies the reducer to a node's returned update. A default function can provide the channel's initial value, which is useful when combining updates into an initially empty collection or string.

Follow-up: What should a reducer's inputs represent? Treat them as the current channel value and the node-provided update, and return the next channel value.

  • Annotation.Root
  • StateGraph
  • MessagesAnnotation
  • messagesStateReducer

Source: Namespace Annotation. Checked 2026-10-15.