Error in RootListenersTracer.on_chain_end callback: ValueError("Expected str, BaseMessage, list[BaseMessage], or tuple[BaseMessage]. Got {'messages': [AIMessage()

Hello guys. Im trying to create an react agent with memory, using langchain.agents create_agent
Here is my code
model = init_chat_model(

model = configs.MODEL_LLM,

api_key = configs.LLM_API_KEY,

temperature=0,

max_tokens=None,

timeout=None,

max_retries=2,

)

agent = create_agent(

model=model,

tools=\[cypher_query_tool, vector_retriever_tool, weather_tool\],

\# middleware=\[

\#     SummarizationMiddleware(

\#         model=model,

\#         max_tokens_before_summary=1000,

\#         messages_to_keep=2,

\#         summary_prompt = prompts.load_prompt("summarize_middleware_prompt.md")

\#     )

\# \],

)

prompt_chain = ChatPromptTemplate.from_messages(

\[

    ("system", "You are an assistant."),

    MessagesPlaceholder(variable_name="chat_history"),

    ("human", "{input}"),

\]

)

def get_session_history(session_id: str):

return MongoDBChatMessageHistory(

    session_id=session_id,

    connection_string="Example",

    database_name="my_db",

    collection_name="chat_histories",

    history_size=4,

)

agent_with_memory = RunnableWithMessageHistory(

prompt_chain | agent ,# | parser,

get_session_history,

input_messages="input",

history_messages_key="chat_history",

)

agent_with_memory_stream = RunnableWithMessageHistory(

prompt_chain | agent | extract_message_stream,

get_session_history,

input_messages="input",

history_messages_key="chat_history",

)

The thing is this bug only appear when i using stream
result = agent_with_memory.stream({“input”: query}, config={“configurable”: { “session_id”: session_id, “user_id”:" ok"}})

for chunk in result:

print(chunk)

when i use stream mode, it’s not write into DB.
Error in RootListenersTracer.on_chain_end callback: ValueError("Expected str, BaseMessage, list[BaseMessage], or tuple[BaseMessage]. Got {‘messages’: [AIMessage
Anyone got solution or alternative method ?

Why are you using history like this? The recommended way in LangChain v1 is as follows.

from langgraph.checkpoint.mongodb import MongoDBSaver
checkpointer = MongoDBSaver.from_conn_string(MONGODB_URI, DB_NAME)
agent = create_agent(

model=model,

tools=\[cypher_query_tool, vector_retriever_tool, weather_tool\],

checkpointer=checkpointer)

config = {"configurable": {"thread_id": "1"}} # this defines your current conversation and agent will build on top of the message history

for chunk in agent.stream({ # you can use invoke as well

        "messages": [

            {

"role": "user",

"content": query

            }

        ]

    }, config=config):
    print(chunk)

Tks. This in the docs right ? But the thing is checkpointer hash the message into binary right ? I have another service that load the k messages latest and also use k message for context window

@viphoangdep In order to make sure that you are only using last k messages in your context window, you can create a middleware for trimming messages:

from langchain.agents import create_agent
from langchain.agents.middleware import before_model

@before_model
def trim_messages(state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
    """Keep only the last few messages to fit context window."""
    messages = state["messages"]

    if len(messages) <= 3:
        return None  # No changes needed

    first_msg = messages[0]
    recent_messages = messages[-3:] if len(messages) % 2 == 0 else messages[-4:]
    new_messages = [first_msg] + recent_messages

    return {
        "messages": [
            RemoveMessage(id=REMOVE_ALL_MESSAGES),
            *new_messages
        ]
    }

agent = create_agent(
model=model,
middleware=[trim_messages],
tools=\[cypher_query_tool, vector_retriever_tool, weather_tool\],
checkpointer=checkpointer)

In the above example, it will take only the last 3 messages if the number of messages are even; otherwise will take 4, but you can change it as per your k parameter.