Subtitle: A three-party cyclical flow where a Writer drafts, an Editor critiques, and the draft goes back for revision.
Hello everyone! I'm your AI technical mentor. Today, we're moving away from solo acts and diving into group collaboration! In the real world, no complex task is handled by a single person, and the same goes for AI agents. While our previously built AI content agency had a Planner, Researcher, Writer, and Editor each performing their duties, the flow between them was mostly unidirectional. Today, we're breaking that linear thinking and introducing a more realistic, intelligent collaboration model: the Network of Agents, specifically focusing on cyclical flows with feedback and iteration.
Imagine your Writer toils away on a draft and hands it to the Editor with full confidence. The Editor takes one look, frowns, and says, "This won't do. The logic is flawed, and the tone is off. Revise it!" Smack! The draft is back in the Writer's hands. The Writer, armed with the Editor's notes (and perhaps a little grievance), gets back to work. Doesn't this back-and-forth sound exactly like our daily work lives? This is the three-party cyclical flow we are going to simulate today using LangGraph: the Writer, the Editor, and the Content State that ties them together.
This cyclical flow is an indispensable capability for building any complex AI system that requires iteration, optimization, and negotiation mechanisms. Master this, and your AI Agents will no longer be rigid assembly-line workers, but intelligent team members capable of true "thinking," "feedback," and "iteration." Ready? Let's dive into the core of LangGraph and unlock this advanced skill!
🎯 Learning Objectives for This Episode
After completing this episode, you will be able to:
- Understand and build conditional-based LangGraph cyclical flows: Master the use of
add_conditional_edgesto implement dynamic feedback and iteration mechanisms between multiple agents. - Granularly manage complex Graph State: Learn how to design and update shared states in multi-agent collaboration to carry the inputs, outputs, and decision-making data of each agent.
- Simulate real-world collaboration in an AI content agency: Deeply integrate the Writer and Editor roles to achieve an automated iterative optimization process from first draft to final copy.
- Master strategies to avoid infinite loops and optimize iterative workflows: Understand potential pitfalls when building cyclical flows and learn how to design robust exit conditions and optimization mechanisms.
📖 Theory Breakdown
In LangGraph, the core of building a multi-agent "Network of Agents" lies in the Graph State and Conditional Edges. Imagine the Graph State as a shared whiteboard where all agents write, draw, and update information. Conditional Edges are like the meeting facilitator, deciding who gets to speak next—or if the meeting can be adjourned—based on the latest discussion results (the state) on the whiteboard.
Today's "three-party game"—the Writer drafting, the Editor critiquing, and the Writer revising—is essentially an iterative optimization loop.
- Writer: Receives a topic or content to be revised, and outputs a first draft or a revised draft.
- Editor: Receives the Writer's draft and evaluates it. It outputs two things:
- Feedback: Tells the Writer what needs improvement.
- Decision: Determines whether the draft meets the requirements (
approved) or still needs work (needs_revision).
- Content State: This is our "whiteboard," which records:
- The current draft (
current_article). - The Editor's latest feedback (
editor_feedback). - The current status of the draft (
status:drafting,revising,approved). - It can even record the number of revisions (
revision_count) to prevent infinite loops.
- The current draft (
The essence of this flow lies in the Editor's decision. If the Editor decides needs_revision, the flow routes back to the Writer node via a conditional edge, forming a loop. If the Editor decides approved, the flow terminates (or moves to the next stage, like publishing).
Core Architecture via Mermaid Diagram
Let's use a Mermaid diagram to visualize this cyclical flow:
graph TD
A[Start] --> B(Writer: Draft/Revise Article);
B --> C{Editor: Review Article};
C -- Needs Revision (needs_revision) --> B;
C -- Approved (approved) --> D[End: Final Article];
style A fill:#f9f,stroke:#333,stroke-width:2px;
style B fill:#bbf,stroke:#333,stroke-width:2px;
style C fill:#bfb,stroke:#333,stroke-width:2px;
style D fill:#f9f,stroke:#333,stroke-width:2px;Diagram Explanation:
- Start: The starting point of the entire process.
- Writer (Draft/Revise Article): A node representing the Writer Agent's operation. It generates or updates the article based on the current state (whether it's an initial draft or a revision based on feedback).
- Editor (Review Article): Another node representing the Editor Agent's operation. It receives the Writer's output, reviews it, and makes a decision.
- Conditional Edges:
- Needs Revision (needs_revision): If the Editor determines the draft needs work, this conditional edge routes the flow back to the Writer node, creating a loop.
- Approved (approved): If the Editor determines the draft meets the standards, this conditional edge routes the flow to the end, finalizing the article.
- End: The endpoint of the process, marking the final completion of the article.
This diagram clearly shows how we connect two independent agents (Writer and Editor) into a collaborative network capable of feedback and iteration using LangGraph's conditional edge mechanism. This is the core charm of the "Network of Agents"!
💻 Practical Code Exercise (Application in the Agency Project)
Alright, theory is great, but code is better. Now, let's seamlessly integrate this "three-party game" mechanism into our AI content creation agency. We will create an ArticleRevisionGraph containing two core Agents, Writer and Editor, and implement iterative article revision using LangGraph's StateGraph and add_conditional_edges features.
We will use a simplified AgentState to simulate the article content, editorial feedback, and revision status.
import operator
from typing import TypedDict, Annotated, List, Union
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
import os
# Ensure your OpenAI API Key is set in the environment variables
# os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"
# Define the state of the graph
class AgentState(TypedDict):
"""
Represent the state of our content agency's article revision process.
"""
topic: str # The topic of the article
current_article: str # The current content of the article
editor_feedback: str # Editor's feedback
revision_count: Annotated[int, operator.add] # Revision count, accumulates using operator.add
status: str # The current status of the article (e.g., "drafting", "revising", "approved")
# Simulated Writer Agent
class WriterAgent:
def __init__(self, llm_model: str = "gpt-4o-mini"):
self.llm = ChatOpenAI(model=llm_model, temperature=0.7)
def write_or_revise(self, state: AgentState) -> AgentState:
"""
Writer Agent's node function: Writes the initial draft or revises the article based on the current state.
"""
topic = state["topic"]
current_article = state["current_article"]
editor_feedback = state["editor_feedback"]
revision_count = state["revision_count"]
# Construct the prompt for the LLM
if revision_count == 0:
prompt = HumanMessage(f"你是一位专业的文章写手。请根据以下主题撰写一篇高质量的文章:\n主题: {topic}\n\n请确保文章结构清晰,内容丰富,语言流畅。")
print(f"\n--- Writer: 撰写初稿 (Revision {revision_count}) ---")
else:
prompt = HumanMessage(f"你是一位专业的文章写手。以下是之前的文章内容和编辑的反馈意见,请根据反馈进行修改和润色:\n\n旧文章内容:\n{current_article}\n\n编辑反馈:\n{editor_feedback}\n\n请提供修改后的完整文章。")
print(f"\n--- Writer: 正在修订文章 (Revision {revision_count}) ---")
print(f"接收到编辑反馈: {editor_feedback}")
# Call LLM to generate content
response = self.llm.invoke([prompt])
new_article = response.content
# Update the state
print(f"Writer 生成了新文章或修订稿:\n{new_article[:200]}...") # Print the first 200 characters
return {"current_article": new_article, "status": "revising", "revision_count": state["revision_count"] + 1}
# Simulated Editor Agent
class EditorAgent:
def __init__(self, llm_model: str = "gpt-4o-mini", max_revisions: int = 3):
self.llm = ChatOpenAI(model=llm_model, temperature=0.7)
self.max_revisions = max_revisions # Set maximum revision count
def review_article(self, state: AgentState) -> AgentState:
"""
Editor Agent's node function: Reviews the article, provides feedback, and decides whether to approve or require revision.
"""
current_article = state["current_article"]
revision_count = state["revision_count"]
# Construct the prompt for the LLM
prompt = HumanMessage(f"你是一位资深的内容编辑。请审查以下文章,并给出详细的修改意见。如果文章已经达到发布标准,请在反馈中明确说明 '文章已通过'。否则,请详细指出需要改进的地方。\n\n文章内容:\n{current_article}")
print(f"\n--- Editor: 正在审查文章 (Revision {revision_count-1}的成果) ---")
# Call LLM to generate feedback
response = self.llm.invoke([prompt])
feedback = response.content
# Determine if the article is approved
status = "needs_revision"
if "文章已通过" in feedback or "已达到发布标准" in feedback:
status = "approved"
print("Editor 判定: 文章已通过!")
elif revision_count >= self.max_revisions:
status = "approved" # Reached max revisions, force approval (in real projects, this might require human intervention)
feedback += "\n[系统提示]:已达到最大修订次数,文章强制通过,可能需要人工复审。"
print(f"Editor 判定: 达到最大修订次数 {self.max_revisions},强制通过。")
else:
print("Editor 判定: 文章需要修改。")
# Update the state
print(f"Editor 提供了反馈:\n{feedback[:200]}...") # Print the first 200 characters
return {"editor_feedback": feedback, "status": status}
# Define a routing function to decide the next flow
def route_article(state: AgentState) -> str:
"""
Routes the article based on its 'status'.
"""
if state["status"] == "approved":
print("\n--- 路由: 文章已通过,流程结束 ---")
return "end"
elif state["status"] == "revising":
print("\n--- 路由: 文章需要修改,返回给 Writer ---")
return "writer"
else:
# Default case, e.g., initial state, or unknown state, usually goes back to Writer
print("\n--- 路由: 初始状态或未知状态,返回给 Writer ---")
return "writer"
# Build the LangGraph
def build_article_revision_graph(llm_model: str = "gpt-4o-mini", max_revisions: int = 3):
writer_agent = WriterAgent(llm_model=llm_model)
editor_agent = EditorAgent(llm_model=llm_model, max_revisions=max_revisions)
# Initialize StateGraph
workflow = StateGraph(AgentState)
# Add nodes
workflow.add_node("writer", writer_agent.write_or_revise)
workflow.add_node("editor", editor_agent.review_article)
# Set the entry point
workflow.set_entry_point("writer")
# Add edges
# After the Writer node completes, it always goes to the Editor for review
workflow.add_edge("writer", "editor")
# After the Editor node completes, a routing function decides whether to return to Writer or end
workflow.add_conditional_edges(
"editor", # From node
route_article, # Routing function
{ # Mapping table
"writer": "writer", # If routing function returns "writer", flow to "writer" node
"end": END # If routing function returns "end", the process ends
}
)
# Compile the graph
app = workflow.compile()
return app
# Run the simulation
if __name__ == "__main__":
# Ensure OpenAI API Key is set
if not os.getenv("OPENAI_API_KEY"):
print("请设置环境变量 OPENAI_API_KEY。")
exit()
# Build and run the graph
app = build_article_revision_graph(llm_model="gpt-4o-mini", max_revisions=3) # You can try gpt-3.5-turbo or gpt-4o-mini
initial_state = {
"topic": "探索人工智能在教育领域的应用与挑战",
"current_article": "",
"editor_feedback": "",
"revision_count": 0,
"status": "drafting"
}
print("--- 开始文章创作与修订流程 ---")
final_state = None
for s in app.stream(initial_state):
print(s) # Print state changes at each step
final_state = s
print("\n--- 流程结束 ---")
print("\n最终文章状态:")
print(f"主题: {final_state['editor']['topic']}")
print(f"最终修订次数: {final_state['editor']['revision_count'] - 1}") # Subtract 1 because the first is 0, then +1 each time
print(f"最终状态: {final_state['editor']['status']}")
print("\n--- 最终文章内容 ---")
print(final_state['editor']['current_article'])
print("\n--- 最终编辑反馈 ---")
print(final_state['editor']['editor_feedback'])
Code Explanation:
AgentStateDefinition:- We use
TypedDictto defineAgentState, which includestopic,current_article,editor_feedback,revision_count, andstatus. revision_count: Annotated[int, operator.add]is an advanced feature specific to LangGraph. It tells LangGraph that when merging states, therevision_countfield should be accumulated usingoperator.addrather than simply overwritten. This means every time a node returns a newrevision_count, it adds to the existing value. This is perfect for counters.
- We use
WriterAgent:- The
write_or_revisemethod is the core logic of the Writer node. - It checks
revision_countto determine whether it's writing the initial draft or making revisions. - If revising, it passes
current_articleandeditor_feedbackas context to the LLM, allowing the LLM to make targeted edits. - It returns a new
current_articleand updates thestatusandrevision_count.
- The
EditorAgent:- The
review_articlemethod is the core logic of the Editor node. - It receives the
current_articleand asks the LLM for feedback. - Crucially, it checks if the LLM's feedback contains keywords like "文章已通过" (Article approved) or "已达到发布标准" (Meets publishing standards) to determine if the article can be finalized.
- To prevent infinite loops, we introduced the
max_revisionsparameter. If the maximum number of revisions is reached, it forces an approval even if the Editor hasn't explicitly approved it. This is a vital mechanism in real projects to prevent deadlocks (though it usually triggers a human intervention alert). - It returns
editor_feedbackand the updatedstatus.
- The
route_articleRouting Function:- This is the core of
add_conditional_edges. It receives the currentAgentStateand returns a string. This string acts as a key to match against the mapping table inadd_conditional_edges, determining the flow's direction. - If
statusisapproved, it returns"end", terminating the process. - If
statusisrevising, it returns"writer", routing the flow back to the Writer node.
- This is the core of
- Graph Construction (
build_article_revision_graph):workflow = StateGraph(AgentState): Creates a state graph based onAgentState.workflow.add_node("writer", writer_agent.write_or_revise)andworkflow.add_node("editor", editor_agent.review_article): Registers the Writer and Editor methods as nodes in the graph.workflow.set_entry_point("writer"): Specifies that the flow starts at the Writer.workflow.add_edge("writer", "editor"): After the Writer finishes, it unconditionally passes the result to the Editor.workflow.add_conditional_edges("editor", route_article, {"writer": "writer", "end": END}): This is the highlight of this episode! After the Editor finishes, based on the judgment of theroute_articlefunction, it decides whether to return to thewriternode or proceed toEND.
- Running the Simulation (
if __name__ == "__main__":):- Sets the
initial_state, including the article topic, empty content, empty feedback, and an initial revision count. app.stream(initial_state)iteratively executes the graph. Each iteration prints the current state changes, allowing you to clearly see how the process advances step by step.
- Sets the
Through this code, you have manually built a content creation workflow capable of self-iteration and self-optimization. This isn't just a simple connection of two Agents; it's a true Network of Agents that simulates human team collaboration and feedback loops.
Pitfalls & Best Practices
While this complex workflow with loops and feedback is powerful, it's also easy to fall into traps. As your senior mentor, I must give you some preventative advice.
- Infinite Loop Trap:
- Pitfall: The Editor is never satisfied, and the Writer never quite hits the mark, causing the flow to loop endlessly between Writer and Editor. Your API costs will drain like water.
- Best Practice:
- Set a maximum revision count (
max_revisions): This is the most direct and effective method. Add a counter in the Editor Agent. When the preset maximum revision count is reached, force the loop to end (e.g., mark it as "requires human review" or simply "approved"). We have already implemented this in our code. - Clear approval criteria: In the prompt to the LLM (Editor), explicitly state the criteria for "approval," such as "The article meets all the following conditions: complete structure, clear arguments, fluent language, and no grammatical errors." Give the LLM a clear basis for judgment.
- Progressively converging feedback: Design the Editor's feedback so that it attempts to bring the Writer closer to the goal each time, rather than raising new, unrelated issues in every iteration.
- Set a maximum revision count (
- Chaotic State Management:
- Pitfall: The
AgentStateis poorly designed, and critical information isn't correctly passed or updated between nodes, resulting in an Agent missing required data or receiving stale data. - Best Practice:
- Clear structure with
TypedDict: Always useTypedDictto defineAgentState. It provides type checking and effectively prevents typos and inconsistent data structures. - Use
Annotatedfor merge strategies: For fields that need accumulation or special merging (likerevision_count), useAnnotatedcombined with theoperatormodule to ensure the state updates correctly. - Single responsibility for nodes: Each node should only be responsible for updating its relevant state fields. Don't try to modify all states within a single node to avoid side effects.
- Print logs: Printing key state information before and after each node executes can help you track data flow and state changes.
- Clear structure with
- Pitfall: The
- LLM Output Volatility:
- Pitfall: LLMs sometimes "hallucinate." The Editor LLM might not output the explicit "approved" or "needs revision" signals in the format you expect, causing the routing function to misjudge.
- Best Practice:
- Robust routing logic: The
route_articlefunction should have enough fault tolerance for LLM outputs. For example, don't just check for one exact string; check for multiple synonyms or phrases ("文章已通过" in feedback or "已达到发布标准" in feedback). - System-level prompt engineering: In the Agent's LLM prompt, explicitly require the LLM to output key information in a specific format, such as "Please write 'STATUS: APPROVED' or 'STATUS: REVISE' clearly on the last line of your feedback." This makes it much easier for the routing function to parse.
- Adjust temperature parameters: At critical decision points, you can appropriately lower the LLM's
temperatureparameter to make its output more stable and deterministic.
- Robust routing logic: The
- Debugging Complex Graphs:
- Pitfall: As the number of nodes and edges in a graph increases, tracking down issues becomes extremely difficult.
- Best Practice:
- Use
app.stream(): As shown in the code, thestream()method allows you to observe state changes step-by-step after each node executes. This is a powerful tool for debugging complex graphs. - Detailed
printlogs: Add detailedprintstatements inside each Agent to output the current received inputs, generated outputs, and decisions made. - Visualization tools: LangGraph provides methods like
get_graph().draw_mermaid_png()to generate visualizations of the graph, which is incredibly helpful for understanding the graph's structure and potential issues.
- Use
Remember, building complex AI systems is like playing with Lego blocks. Every piece must be placed correctly, and you must anticipate the chain reactions it might cause. Think more, practice more, and you will become a LangGraph master!
📝 Episode Summary
Congratulations! In this episode of the LangGraph Masterclass, we conquered an advanced and crucial pattern: the Network of Agents. We are no longer satisfied with linear task flows; instead, we dove deep into the core of LangGraph, utilizing StateGraph, add_conditional_edges, and clever AgentState management to build an article creation and revision loop capable of self-iteration and self-feedback.
We simulated a real "three-party game" between a Writer and an Editor in an AI content agency: The Writer submits a first draft, the Editor strictly reviews it and provides feedback, and if the draft falls short, it's sent back to the Writer for revision until the Editor is satisfied. This cyclical flow not only improves the quality of the content output but also equips your AI Agents with true "learning" and "optimization" capabilities.
You learned how to:
- Cleverly design
AgentState, especially utilizingAnnotatedfor cumulative state merging. - Build Writer and Editor agents capable of drafting, reviewing, and making decisions based on context.
- Apply
add_conditional_edgesand routing functions (route_article) to dynamically adjust the workflow based on agent decisions. - And most importantly, master advanced techniques for preventing infinite loops and effectively debugging complex graphs.
This agent network with feedback loops is the cornerstone of building any complex, adaptable AI system. Whether it's content creation, code review, product design, or medical diagnosis, wherever there is a need for iteration and optimization, this pattern will shine brightly.
Next time, we will build upon this foundation to explore even more advanced collaboration patterns and optimization techniques. Keep up the enthusiasm, and see you in the next episode!