christian-bromann/langchain-skills/js

Claude Code and agent skill by christian-bromann/langchain-skills

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Managing state in LangGraph: schemas, reducers, channels, and message passing for coordinating agent execution

Install

npx vskill@latest install christian-bromann/langchain-skills/js

SKILL.md

langgraph-state (JavaScript/TypeScript)


name: langgraph-state description: Managing state in LangGraph - schemas, reducers, channels, and message passing for coordinating agent execution


Overview

State is the central data structure in LangGraph that persists throughout graph execution. Proper state management is crucial for building reliable agents.

Key Concepts:

  • StateSchema: Defines the structure and types of your state
  • Reducers: Control how state updates are applied (ReducedValue)
  • Channels: Low-level state management primitives
  • Message Passing: How nodes communicate via state updates

Decision Table: State Update Strategies

NeedSolutionUse Case
Overwrite valuePlain Zod schemaSimple fields like strings
Append to listReducedValue with concatLogs, accumulating data
Custom logicCustom reducer functionComplex merging, validation
MessagesMessagesValueChat applications

Code Examples

Basic State Management
typescript
import { StateGraph, StateSchema, START, END } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
input: z.string(),
processed: z.string(),
count: z.number(),
});
const process = async (state: typeof State.State) => {
return {
processed: state.input.toUpperCase(),
count: state.count + 1,
};
};
const graph = new StateGraph(State)
.addNode("process", process)
.addEdge(START, "process")
.addEdge("process", END)
.compile();
const result = await graph.invoke({ input: "hello", count: 0 });
console.log(result); // { input: 'hello', processed: 'HELLO', count: 1 }
Messages with Reducer
typescript
import { StateSchema, MessagesValue, StateGraph, START, END } from "@langchain/langgraph";
import { HumanMessage, AIMessage } from "@langchain/core/messages";
const MessagesState = new StateSchema({
messages: MessagesValue,
});
const addResponse = async (state: typeof MessagesState.State) => {
const lastMessage = state.messages.at(-1);
const userMsg = lastMessage?.content || "";
return {
messages: [new AIMessage({ content: `Response to: ${userMsg}` })],
};
};
const graph = new StateGraph(MessagesState)
.addNode("respond", addResponse)
.addEdge(START, "respond")
.addEdge("respond", END)
.compile();
const result = await graph.invoke({
messages: [new HumanMessage({ content: "Hello!" })],
});
console.log(result.messages.length); // 2 (original + response)
Custom Reducer with ReducedValue
typescript
import { StateSchema, ReducedValue, START, END, StateGraph } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
metadata: new ReducedValue(
z.record(z.string(), z.any()).default(() => ({})),
{
inputSchema: z.record(z.string(), z.any()),
reducer: (current, update) => ({ ...current, ...update }),
}
),
data: z.string(),
});
const updateMetadata = async (state: typeof State.State) => {
return { metadata: { timestamp: "2024-01-01" } };
};
const graph = new StateGraph(State)
.addNode("update", updateMetadata)
.addEdge(START, "update")
.addEdge("update", END)
.compile();
const result = await graph.invoke({
metadata: { user: "alice" },
data: "test",
});
// metadata is merged: { user: "alice", timestamp: "2024-01-01" }
List Accumulation with ReducedValue
typescript
import { StateSchema, ReducedValue } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
items: new ReducedValue(
z.array(z.string()).default(() => []),
{
inputSchema: z.array(z.string()),
reducer: (current, update) => current.concat(update),
}
),
});
const addItems = async (state: typeof State.State) => {
return { items: ["new_item"] };
};
const graph = new StateGraph(State)
.addNode("add", addItems)
.addEdge(START, "add")
.addEdge("add", END)
.compile();
const result = await graph.invoke({ items: ["old1", "old2"] });
console.log(result.items); // ['old1', 'old2', 'new_item']
Using Channels API
typescript
import { StateGraph, LastValue, BinaryOperatorAggregate } from "@langchain/langgraph";
interface State {
counter: number;
logs: string[];
}
const graph = new StateGraph<State>({
channels: {
counter: new BinaryOperatorAggregate<number>(
(x, y) => x + y,
() => 0
),
logs: new BinaryOperatorAggregate<string[]>(
(x, y) => x.concat(y),
() => []
),
},
});
Partial State Updates
typescript
import { StateSchema, StateGraph, START, END } from "@langchain/langgraph";
import { z } from "zod";
const State = new StateSchema({
field1: z.string(),
field2: z.string(),
field3: z.string(),
});
const updateField1 = async (state: typeof State.State) => {
// Only update field1, others unchanged
return { field1: "updated" };
};
const updateField2 = async (state: typeof State.State) => {
// Only update field2
return { field2: "also updated" };
};
const graph = new StateGraph(State)
.addNode("node1", updateField1)
.addNode("node2", updateField2)
.addEdge(START, "node1")
.addEdge("node1", "node2")
.addEdge("node2", END)
.compile();
const result = await graph.invoke({
field1: "original1",
field2: "original2",
field3: "original3",
});
// field1: "updated", field2: "also updated", field3: "original3"

Boundaries

What You CAN Configure

✅ Define custom state schemas with Zod ✅ Add reducers via ReducedValue ✅ Create custom reducer functions ✅ Use built-in channels ✅ Use MessagesValue for chat ✅ Partial state updates ✅ Nested state structures

What You CANNOT Configure

❌ Change state schema after compilation ❌ Access state outside node functions ❌ Modify state directly (must return updates) ❌ Share state between separate graphs

Gotchas

1. Forgot Reducer for Arrays
typescript
// ❌ WRONG - Array will be overwritten
const State = new StateSchema({
items: z.array(z.string()), // No reducer!
});
// Node 1 returns: { items: ["A"] }
// Node 2 returns: { items: ["B"] }
// Final state: { items: ["B"] } // A is lost!
// ✅ CORRECT
import { ReducedValue } from "@langchain/langgraph";
const State = new StateSchema({
items: new ReducedValue(
z.array(z.string()).default(() => []),
{ reducer: (current, update) => current.concat(update) }
),
});
// Final state: { items: ["A", "B"] }
2. State Updates Must Return Partial
typescript
// ❌ WRONG - Returning entire state object
const myNode = async (state: typeof State.State) => {
state.field = "updated";
return state; // Don't do this!
};
// ✅ CORRECT - Return partial updates
const myNode = async (state: typeof State.State) => {
return { field: "updated" };
};
3. Default Values
typescript
// ❌ RISKY - No default handling
const State = new StateSchema({
count: z.number(), // What if undefined?
});
const increment = async (state: typeof State.State) => {
return { count: state.count + 1 }; // May error if count undefined
};
// ✅ BETTER - Use defaults in schema
const State = new StateSchema({
count: z.number().default(0),
});
4. Always Await Nodes
typescript
// ❌ WRONG - Forgetting await
const result = graph.invoke({ input: "test" });
console.log(result.output); // undefined (Promise!)
// ✅ CORRECT
const result = await graph.invoke({ input: "test" });
console.log(result.output); // Works!

Links

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
3
Repository forks
1
7-day trend score
7

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 19 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/christian-bromann/langchain-skills/js/badge)](https://verified-skill.com/skills/christian-bromann/langchain-skills/js)

Something wrong with this skill or its page? Tell us.