Seeking help with some merge message issues when LangGraph is called in parallel

hi @Huimin-station

despite some issues described below, your graph decomposition (separate model/tool/route nodes) is a strong start, and your questions show you’re debugging at the right level.

The issues I found are very common in early agent workflows - you’re on a solid track bro :flexed_biceps:

Really nice work sharing your repo openly and iterating in public, I truly appreciate! :heart:

some quick findings:

High: blank_node returns full state, which can duplicate message history

  • File: agent/nodes/tools_nodes.py (blank_node)
  • Problem: blank_node returns the entire state instead of a partial update
    With current messages reducer set to operator.add, this can append full history back into itself
  • Impact: Message list can grow incorrectly (duplicate history), increase token costs, and break logic relying on “last message”
  • Fix: Return {} from pass-through nodes (or explicit minimal updates only).
    Also switch message reducer to add_messages (see finding #2), which is designed for message lists

High: Message state uses operator.add instead of add_messages

  • File: agent/messages_state/messages_state.py
  • Problem: messages uses Annotated[list[AnyMessage], operator.add].
  • Impact: Raw list concatenation does not provide message-aware merge semantics (id-aware updates, safe merge behavior for chat state). This is fragile for tool-calling loops and especially unsafe when branches are parallelized
  • Fix: Use LangGraph’s built-in message reducer:
    • from langgraph.graph.message import add_messages
    • messages: Annotated[list[AnyMessage], add_messages]

High: Tool dispatch is manual and unvalidated; vulnerable to call/result mismatch in parallel scenarios

  • Files: agent/nodes/tools_nodes.py, agent/nodes/choose.py, agent/main.py
  • Problem: Custom tool nodes always read from state["messages"][-1].tool_calls and do not validate tool name dispatch against a tool registry
  • Impact: If multiple AI messages/tool-call batches appear in close sequence (or if you enable parallel branches), tool-call/result pairing can drift, producing invalid chat history and hard-to-debug behavior
  • Fix: Use ToolNode/agent runtime defaults (prefer create_agent for standard agent loops), or at minimum:
    • route a specific tool call payload to each tool executor
    • validate tool name before invocation
    • guarantee 1 ToolMessage per tool_call_id

High: Repository is not runnable out of the box (missing dependency manifest and missing config module)

  • Files: project root, utils/model_builder.py
  • Problem: No requirements.txt/pyproject.toml in repo; runtime immediately fails on missing langchain_core
    utils/model_builder.py imports utils.key.deepseek, but utils/key.py is not committed
  • Impact: Reproducibility is broken; reviewers cannot run or verify behavior
  • Fix: Add packaging and setup docs:
    • committed dependency manifest
    • .env.example
    • load API key from environment via os.getenv, not a local ignored module

Medium: Control-flow logic is brittle ("True"/"False" exact string matching)

  • File: agent/nodes/choose.py
  • Problem: search_or_not checks exact text equality on model output (== "False").
  • Impact: Small output variation ("false", "False.", localized text) changes graph routing unexpectedly.
  • Fix: Use structured outputs / tool-call / strict schema for decision nodes, or normalize/parse robustly.

Medium: Entry script executes immediately on import

  • File: agent/main.py
  • Problem: Graph streaming runs at module import time.
  • Impact: Importing for tests or reuse triggers real execution side effects.
  • Fix: Wrap execution in if __name__ == "__main__":.

Medium: Incorrect boolean expression in stream filtering

  • File: agent/main.py
  • Problem: ("False" or "True") always evaluates to "False".
  • Impact: Intended filtering logic is incorrect.
  • Fix: Replace with explicit set check, e.g.:
    • chunk[-1][0].content not in {"False", "True"}.

Medium: Relative output path in PNG helper is unstable

  • File: utils/png_print.py
  • Problem: Writes to ../agent/graph_show/graph.png relative to CWD, not module path.
  • Impact: Output can go to wrong location depending on execution directory.
  • Fix: Use pathlib.Path(__file__)-based absolute path resolution.

Medium: Tool API shape inconsistency

  • File: agent/tools/base_tools.py
  • Problem: search_local_position(city: str) requires a city argument even though description says it should fetch current user location.
  • Impact: Model may fail to provide required args; unnecessary invocation errors.
  • Fix: Align signature with intended behavior (search_local_position()) or rename and update prompt/docs.

Low: Dead/placeholder modules and weak tests

  • Files: agent/tools/all_tools.py, agent/tools/mcp_tools.py, test/test_01.py
  • Problem: Empty modules and a non-test script in test/.
  • Impact: Noise and no confidence from automated tests.
  • Fix: Remove placeholders or implement them; add real tests for:
    • graph routing,
    • tool-call/tool-result pairing,
    • reducer behavior under repeated/branch execution.