To prevent models from being overwhelmed by long histories, you can implement a message filtering strategy within your agent nodes. Use an Annotation.Root to define your state and a reducer to manage how new messages are appended. Inside your node function, slice the message array to keep only the necessary context (e.g., the most recent messages) before invoking the model.
import { Annotation, END, START, StateGraph } from "@langchain/langgraph";
import { BaseMessage, HumanMessage, AIMessage } from "@langchain/core/messages";
// Define state
const AgentState = Annotation.Root({
messages: Annotation<BaseMessage[]>({
reducer: (x, y) => x.concat(y),
}),
});
// Filter messages to keep only the most recent
const filterMessages = (messages: BaseMessage[]) => {
return messages.slice(-1); // Keep only the last message
};
// Agent node that uses filtered messages
const agent = async (state: typeof AgentState.State) => {
const { messages } = state;
const filteredMessages = filterMessages(messages);
const response = await model.invoke(filteredMessages);
return {
messages: [response],
};
};
// Build workflow
const workflow = new StateGraph(AgentState)
.addNode("agent", agent)
.addEdge(START, "agent")
.addEdge("agent", END);
const app = workflow.compile();