langgraph-state

LangGraph State Management

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "langgraph-state" with this command: npx skills add yonatangross/orchestkit/yonatangross-orchestkit-langgraph-state

LangGraph State Management

Design and manage state schemas for LangGraph workflows.

TypedDict Approach (Simple)

from typing import TypedDict, Annotated from operator import add

class WorkflowState(TypedDict): input: str output: str agent_responses: Annotated[list[dict], add] # Accumulates metadata: dict

MessagesState Pattern (2026 Best Practice)

from langgraph.graph import MessagesState from langgraph.graph.message import add_messages from typing import Annotated

Option 1: Use built-in MessagesState (recommended)

class AgentState(MessagesState): """Extends MessagesState with custom fields.""" user_id: str context: dict

Option 2: Define messages manually with add_messages reducer

class CustomState(TypedDict): messages: Annotated[list, add_messages] # Smart append/update by ID metadata: dict

Why add_messages matters:

  • Appends new messages (doesn't overwrite)

  • Updates existing messages by ID

  • Handles message deduplication automatically

Note: MessageGraph is deprecated in LangGraph v1.0.0. Use StateGraph with a messages key instead.

Pydantic Approach (Validation)

from pydantic import BaseModel, Field

class WorkflowState(BaseModel): input: str = Field(description="User input") output: str = "" agent_responses: list[dict] = Field(default_factory=list)

def add_response(self, agent: str, result: str):
    self.agent_responses.append({"agent": agent, "result": result})

Accumulating State Pattern

from typing import Annotated from operator import add

class AnalysisState(TypedDict): url: str raw_content: str

# Accumulate agent outputs
findings: Annotated[list[Finding], add]
embeddings: Annotated[list[Embedding], add]

# Control flow
current_agent: str
agents_completed: list[str]
quality_passed: bool

Key Pattern: Annotated[list[T], add]

  • Without add : Each node replaces the list

  • With add : Each node appends to the list

  • Critical for multi-agent workflows

Custom Reducers

from typing import Annotated

def merge_dicts(a: dict, b: dict) -> dict: """Custom reducer that merges dictionaries.""" return {**a, **b}

class State(TypedDict): config: Annotated[dict, merge_dicts] # Merges updates

def last_value(a, b): """Keep only the latest value.""" return b

class State(TypedDict): status: Annotated[str, last_value] # Overwrites

State Immutability

def node(state: WorkflowState) -> WorkflowState: """Return new state, don't mutate in place.""" # Wrong: state["output"] = "result" # Right: return { **state, "output": "result" }

Context Schema (2026 Pattern)

Pass runtime configuration without polluting state:

from dataclasses import dataclass from langgraph.graph import StateGraph

@dataclass class ContextSchema: """Runtime configuration, not persisted in state.""" llm_provider: str = "anthropic" temperature: float = 0.7 max_retries: int = 3 debug_mode: bool = False

Create graph with context schema

graph = StateGraph(WorkflowState, context_schema=ContextSchema)

Access context in nodes

def my_node(state: WorkflowState, context: ContextSchema): if context.llm_provider == "anthropic": response = call_claude(state["input"], context.temperature) else: response = call_openai(state["input"], context.temperature)

if context.debug_mode:
    logger.debug(f"Response: {response}")

return {"output": response}

Invoke with context

graph.invoke( {"input": "Hello"}, context={"llm_provider": "openai", "temperature": 0.5} )

Node Caching (2026 Pattern)

Cache expensive node results with TTL:

from langgraph.cache.memory import InMemoryCache from langgraph.types import CachePolicy

Add node with cache policy

builder.add_node( "embed_content", embed_content_node, cache_policy=CachePolicy(ttl=300) # Cache for 5 minutes )

builder.add_node( "llm_call", llm_node, cache_policy=CachePolicy(ttl=60) # Cache for 1 minute )

Compile with cache

graph = builder.compile(cache=InMemoryCache())

RemainingSteps (Proactive Recursion Handling)

Check remaining steps to wrap up gracefully:

from langgraph.types import RemainingSteps

def agent_node(state: WorkflowState, remaining: RemainingSteps): """Proactively handle recursion limit.""" if remaining.steps < 5: # Running low on steps, wrap up return { "action": "summarize_and_exit", "reason": f"Only {remaining.steps} steps remaining" }

# Continue normal processing
return {"action": "continue"}

Key Decisions

Decision Recommendation

TypedDict vs Pydantic TypedDict for internal state, Pydantic at boundaries

Messages state Use MessagesState or add_messages reducer

Accumulators Always use Annotated[list, add] for multi-agent

Nesting Keep state flat (easier debugging)

Immutability Return new state, don't mutate

Runtime config Use context_schema for non-persistent config

Expensive ops Use CachePolicy to cache node results

Recursion Use RemainingSteps for proactive handling

2026 Guidance: Use TypedDict inside the graph (lightweight, no runtime overhead). Use Pydantic at boundaries (inputs/outputs, user-facing data) for validation.

Common Mistakes

  • Forgetting add reducer (overwrites instead of accumulates)

  • Mutating state in place (breaks checkpointing)

  • Deeply nested state (hard to debug)

  • No type hints (lose IDE support)

  • Putting runtime config in state (use context_schema instead)

  • Not caching expensive operations (repeated embedding calls)

Evaluations

See references/evaluations.md for test cases.

Related Skills

  • langgraph-routing

  • Using state fields for routing decisions

  • langgraph-checkpoints

  • Persist state for fault tolerance

  • langgraph-parallel

  • Accumulating state from parallel nodes

  • langgraph-supervisor

  • State tracking for agent completion

  • langgraph-functional

  • State in Functional API patterns

  • type-safety-validation

  • Pydantic model patterns

Capability Details

state-definition

Keywords: StateGraph, TypedDict, state schema, define state Solves:

  • Define workflow state with TypedDict

  • Create Pydantic state models

  • Structure agent state properly

state-channels

Keywords: channel, Annotated, state channel, MessageChannel Solves:

  • Configure state channels for data flow

  • Implement message accumulation

  • Handle channel-based state updates

state-reducers

Keywords: reducer, add_messages, operator.add, accumulate Solves:

  • Implement state reducers with Annotated

  • Accumulate messages across nodes

  • Handle state merging strategies

subgraphs

Keywords: subgraph, nested graph, parent state, child graph Solves:

  • Compose graphs with subgraphs

  • Pass state between parent and child

  • Implement modular workflow components

state-persistence

Keywords: persist, state persistence, durable state, save state Solves:

  • Persist state across executions

  • Implement durable workflows

  • Handle state serialization

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

responsive-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

dashboard-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

rag-retrieval

No summary provided by upstream source.

Repository SourceNeeds Review
General

memory

No summary provided by upstream source.

Repository SourceNeeds Review