LangGraph/Core Model
Intermediate18 min

Nodes

Nodes are the units of computation in LangGraph. This article covers every node type — function, ToolNode, Command, deferred — plus node-level caching, pre/post model hooks, failure modes, and how to test nodes in isolation.

Quick Reference

  • Function node: any (state) -> dict function added via graph.add_node()
  • ToolNode: pre-built node that executes AIMessage tool_calls — from langgraph.prebuilt
  • Command node: return Command(goto='name', update={...}) to route from inside a node
  • Deferred node: waits for all upstream parallel branches before running — @defer decorator
  • Node caching: add_node('name', fn, cache_policy=CachePolicy(ttl=120)) — from langgraph.types
  • Pre/post hooks: pre_model_hook and post_model_hook on create_react_agent for context control
  • Nodes return partial state — only changed keys, merged into full state by reducers

What Is a Node

STARTAgentLLM decides?conditionalneeds tooldoneENDToolsExecute & returnloop

START → Agent → Tools → Agent (loop) → END

A node is any callable — sync or async — that receives the current graph state and returns a partial state update. LangGraph calls it, takes the returned dict, and merges it into the full state via reducers. That is the entire contract. Everything else — routing, caching, tool execution — is built on top of this.

Full stateGraphStateCache hit?CachePolicy checkhit → skip nodemissNode fnpre/post hooks hereException → graph failsPartial dictchanged keys onlyReducermerge → state

Node lifecycle: full state in → cache check → node fn (with pre/post hooks) → partial dict → reducer merge

Before a node runs, LangGraph checks whether a cache hit exists (if you configured CachePolicy). If the node runs, any pre_model_hook fires first, then the node function, then any post_model_hook. The node returns a partial dict. Reducers merge it into the full state. If the node throws an unhandled exception, the graph fails — there is no automatic retry at the node level.