Silent Quality Degradation In Multi-Agent Flat Round-Table: 34.3/100 Without Synthesis Node Vs 86.3/100 With It
Standard LangGraph multi-agent flat round-table topology silently degrades output quality on judgment and commitment tasks because terminal agents adhere to their role prompts instead of synthesizing a final answer. Adding a terminal synthesis node with an explicit role-override instruction resolves the issue.
Agent nodes with role-based system prompts (Analyst, Reviewer, etc.) follow their role function at the terminal step. A Reviewer reviews, an Analyst analyses. Without an explicit instruction to override this and produce a final committed output, the last agent responds to the prior agent rather than synthesising a deliverable. LangGraph does not enforce a synthesis step, so examples without it lead users to suboptimal patterns.
Use the provided reproduction code with a flat round-table graph (analyst -> reviewer -> END). Run the task to allocate $500K across three initiatives. Observe that the final output is a critique rather than a specific dollar allocation. Add a synthesis node as shown in fix_code and re-run to get a committed answer.
Fixing Code Block
from typing import Annotated, TypedDict
from langchain_core.messages import HumanMessage
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
class State(TypedDict):
messages: Annotated[list, add_messages]
llm = ChatOpenAI(model='gpt-4o-mini', temperature=0)
TASK = (
'A startup has $500K to allocate across three initiatives. '
'One must receive >50% of the budget.\n'
'Option A: Reduce infrastructure costs 30% (ROI: 4 months, no customer impact)\n'
'Option B: Hire 2 enterprise sales reps (ROI: 9 months, impacts Q3 revenue)\n'
'Option C: Ship the feature top churning customers want (ROI: 2 months, reduces churn)\n'
'Produce a specific allocation in dollars.'
)
def analyst(state: State) -> State:
resp = llm.invoke([
{'role': 'system', 'content': 'You are a financial analyst.'},
*state['messages']
])
return {'messages': [resp]}
def reviewer(state: State) -> State:
resp = llm.invoke([
{'role': 'system', 'content': 'You are a business reviewer. Respond to the analysis above.'},
*state['messages']
])
return {'messages': [resp]}
SYNTHESIS = (
'OVERRIDE YOUR ROLE FUNCTION FOR THIS TURN. '
'You are the terminal synthesis agent. '
'Identify what prior analysis got right, what it missed, '
'produce a COMPLETE, DEFINITIVE final answer. '
'Close every open question. Be decisive.'
)
def synthesiser(state: State) -> State:
resp = llm.invoke([
{'role': 'system', 'content': 'You are a synthesis agent.'},
*state['messages'],
{'role': 'user', 'content': SYNTHESIS}
])
return {'messages': [resp]}
graph2 = StateGraph(State)
graph2.add_node('analyst', analyst)
graph2.add_node('reviewer', reviewer)
graph2.add_node('synthesiser', synthesiser)
graph2.set_entry_point('analyst')
graph2.add_edge('analyst', 'reviewer')
graph2.add_edge('reviewer', 'synthesiser')
graph2.add_edge('synthesiser', END)
result2 = graph2.compile().invoke({'messages': [HumanMessage(content=TASK)]})
print(result2['messages'][-1].content)
The fix adds a terminal synthesis node with a user message that explicitly instructs the model to override its current role function and produce a definitive final answer. The 'OVERRIDE YOUR ROLE FUNCTION' phrase prevents the model from continuing to act as a reviewer or analyst and forces it to synthesize all prior context into a committed output. The synthesis node is placed after all analysis nodes, ensuring it has access to the full conversation history.
Edge Case Audit
This fix adds one extra LLM call, increasing latency and cost. The aggressive 'OVERRIDE' instruction may cause the model to ignore important uncertainties or nuances in favour of decisiveness, potentially reducing answer quality in ambiguous scenarios. Different models may react differently to such strong instructions; some may overfit or hallucinate commitments. If conversation history grows too large, the synthesis node may hit context window limits. To roll back, simply remove the synthesiser node and edge, but expect the original quality degradation to return. Alternative: modify the final node's system prompt to include synthesis instructions without adding a new node, but this may be less effective.