Calling a model inside a node

LangGraph · Essentials · 10 min

Almost every LangGraph app has at least one model-calling node; getting its shape right matters.

A model-calling node is a normal function: read messages from state, call the model, return the reply as a state update.

You can use any client library. With LangChain's chat model interface (from the LangChain lessons) the code is short and provider-independent:

model = init_chat_model("claude-sonnet-4-6")

def chatbot(state: MessagesState):
    return {"messages": [model.invoke(state["messages"])]}

init_chat_model picks the provider from the model name (or a prefix like "openai:...") and needs that provider's package and API key. Model names change often; check the provider's current list.

Patterns worth knowing:

  • System prompt: prepend it at call time, model.invoke([SystemMessage(...)] + state["messages"]), rather than storing it in state. That keeps state clean and lets you change the prompt without migrating saved threads.
  • Create the model once, outside the node, so it isn't rebuilt every step.
  • Async: in an async app write async def chatbot(...) and use await model.ainvoke(...).
  • Structured decisions: for routing, use model.with_structured_output(Schema) (it returns a parsed object matching your schema instead of free text) and store the parsed field in state; then a conditional edge reads it.

Token-by-token output works automatically: LangGraph's messages stream mode picks up tokens from LangChain models called inside nodes, as the streaming lesson shows.

Example

from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage
from langgraph.graph import StateGraph, START, END, MessagesState

# pip install langgraph langchain langchain-anthropic; set ANTHROPIC_API_KEY
model = init_chat_model("claude-sonnet-4-6", temperature=0)   # names change; check docs
SYSTEM = SystemMessage("You are a concise assistant for a bike shop.")


def chatbot(state: MessagesState) -> dict:
    reply = model.invoke([SYSTEM] + state["messages"])
    return {"messages": [reply]}


b = StateGraph(MessagesState)
b.add_node(chatbot)
b.add_edge(START, "chatbot")
b.add_edge("chatbot", END)
graph = b.compile()

out = graph.invoke({"messages": [{"role": "user", "content": "Do you fix e-bikes?"}]})
print(out["messages"][-1].content)

Remember

  • A model node: read state['messages'], call the model, return {'messages': [reply]}
  • Create the model once; add the system prompt at call time
  • Use with_structured_output for decisions that drive routing
  • LangChain models stream tokens through LangGraph automatically

Check yourself

  1. Why prepend the system prompt at call time instead of storing it in state?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.langchain.com/oss/python/langgraph/quickstart