A chatbot graph needs a place to keep its human and assistant messages. MessagesState is a built-in LangGraph state class with a messages field. When a node returns new messages, they are added to the existing list rather than replacing it. section 10.2.3 section 10.4.2
Return only the new reply
In a StateGraph(MessagesState), an assistant node can pass state["messages"] to an LLM, then return {"messages": [ai_response_message]}. A custom state without that append behavior instead returns {"messages": messages + [ai_response_message]} to keep the earlier messages. The node returns the field it updates, not the entire state. section 10.2.3
To carry more than messages, subclass MessagesState and add a field: class AgentState(MessagesState): sys_msg_text: str. A context node can return {"sys_msg_text": BASE_SYS_MSG} without changing messages. This new field uses the default replacement behavior; the messages field retains its append behavior, enabled internally by add_messages. section 10.4.2
Listing 10.2 The SupportAgentGraph class in graph.py
from langgraph.graph import START, END, StateGraph, MessagesState
from langchain_core.messages import HumanMessage
class SupportAgentGraph:
def __init__(self, llm):
self.llm = llm
self.graph = self.build_graph()
def get_assistant_node(self):
def assistant_node(state):
ai_response_message = self.llm.invoke(state["messages"])
return {"messages": [ai_response_message]}
return assistant_node
def build_graph(self):
builder = StateGraph(MessagesState)
builder.add_node("assistant", self.get_assistant_node())
builder.add_edge(START, "assistant")
builder.add_edge("assistant", END)
return builder.compile()
def invoke(self, human_message_text):
human_msg = HumanMessage(content=human_message_text)
state = {"messages": [human_msg]}
return self.graph.invoke(state)
See how the support-agent graph uses StateGraph(MessagesState) and returns only the assistant's new message. section 10.2.3
