Having examined the principles of workflow orchestration, it's time to translate theory into practice. In this hands-on section, we will design and outline the implementation of a multi-stage workflow. This exercise will demonstrate how several LLM agents, each with a specialized role, can collaborate systematically to accomplish a complex task. We'll focus on a common application: generating a comprehensive report based on a user-defined topic.
Our goal is to build a system that takes a topic from a user and produces a well-structured, informative report. This process naturally breaks down into several stages, each suitable for a dedicated agent. This division of labor allows each agent to focus on its specific expertise, leading to a more effective overall outcome.
The workflow will involve the following agents:
Optionally, a final human review step can be incorporated before the report is considered complete, aligning with the human-in-the-loop principles discussed earlier in this chapter.
The collaboration between these agents needs a clearly defined flow. We can visualize this as a directed graph where nodes represent agents (or tasks) and edges represent the flow of information or control.
The diagram illustrates the report generation workflow. Each agent performs a distinct step, passing its output to the next agent in the sequence. Note the feedback loop from the Review Agent to the Drafting Agent, allowing for iterative refinement.
For agents to collaborate effectively, they need well-defined interfaces. Each agent should expect a certain input format and produce a predictable output format. JSON is a common choice for structuring these messages.
For example, the Research Agent might:
{"topic": "Advancements in Renewable Energy Storage"}
{"topic": "Advancements in Renewable Energy Storage", "raw_data": [{"source": "url1", "content": "..."}, {"source": "doc2", "content": "..."}], "summary": "Initial overview of findings."}
The Analysis Agent would then take this output as its input and produce something like:
{"topic": "Advancements in Renewable Energy Storage", "structured_insights": [{"point": "Lithium-ion battery improvements...", "details": "..."}, {"point": "Solid-state battery research...", "details": "..."}], "proposed_outline": ["Introduction", "Lithium-ion", "Solid-state", "Conclusion"]}
This structured data exchange is fundamental for smooth transitions between workflow stages.
An orchestrator component is responsible for managing the overall workflow. In a simple sequential workflow like this, the orchestrator calls each agent in turn, passing the output of one agent as the input to the next. For more complex scenarios, you might implement a state machine or use a graph-based execution engine as discussed in "State-Driven and Graph-Based Orchestration Models."
Here's a high-level Python-like structure for a simple orchestrator:
# Assume agent classes (ResearchAgent, AnalysisAgent, etc.) are defined elsewhere.
# Each agent class would have a 'run' method taking a dictionary and returning a dictionary.
class ReportOrchestrator:
def __init__(self):
self.research_agent = ResearchAgent()
self.analysis_agent = AnalysisAgent()
self.drafting_agent = DraftingAgent()
self.review_agent = ReviewAgent()
self.max_revisions = 2 # Prevent infinite loops
def generate_report(self, topic: str) -> dict:
print(f"Starting report generation for topic: {topic}")
# Stage 1: Research
research_input = {"topic": topic}
research_output = self.research_agent.run(research_input)
print("Research complete.")
if not research_output.get("raw_data"):
print("Research Agent failed to find data. Aborting.")
return {"status": "error", "message": "No data found."}
# Stage 2: Analysis
analysis_output = self.analysis_agent.run(research_output)
print("Analysis complete.")
# Stage 3 & 4: Drafting and Review Loop
current_draft_input = analysis_output
final_report = None
for attempt in range(self.max_revisions + 1):
print(f"Drafting attempt {attempt + 1}...")
draft_output = self.drafting_agent.run(current_draft_input)
print("Drafting complete.")
print("Reviewing draft...")
review_input = draft_output # Pass the entire draft context
review_output = self.review_agent.run(review_input)
print("Review complete.")
if review_output.get("status") == "approved":
final_report = review_output.get("final_report", draft_output.get("draft_text"))
print("Report approved!")
break
elif attempt < self.max_revisions:
print("Revisions requested. Preparing for redraft.")
# The review_output should contain feedback for the drafting agent
# This feedback needs to be incorporated into the input for the next drafting iteration
current_draft_input = {
**analysis_output, # Original insights
"previous_draft": draft_output.get("draft_text"),
"feedback": review_output.get("feedback")
}
else:
print("Maximum revisions reached. Report not approved.")
final_report = review_output.get("final_report_as_is", draft_output.get("draft_text")) # Or handle as error
break
# Stage 5: Optional Human Review (outside this main flow, but noted)
if final_report:
print("Report generation process finished.")
return {"status": "success", "report": final_report}
else:
print("Report generation failed after revisions.")
return {"status": "error", "message": "Failed to produce an approved report."}
# Example usage:
# orchestrator = ReportOrchestrator()
# report_topic = "The Impact of Quantum Computing on Cryptography"
# result = orchestrator.generate_report(report_topic)
# if result["status"] == "success":
# print("\nFinal Report:\n", result["report"])
# else:
# print("\nReport Generation Failed:\n", result["message"])
In this pseudo-code:
generate_report
method executes the sequence.ReviewAgent
would need to be designed to output a status (approved
or needs_revision
) and detailed feedback. The DraftingAgent
would then need to be able to accept this feedback to improve its next draft.While we are not detailing the full LLM prompt engineering for each agent here (as that is covered in prerequisite material and earlier chapters on agent design), consider the following for each agent's run
method:
To truly build this, you would integrate with your chosen LLM framework. During execution, you would monitor:
Logging (as discussed in Chapter 6) is very important here. Comprehensive logs allow you to trace the flow of data and decisions, which is indispensable for debugging and understanding agent behavior.
Once this basic pipeline is functional, consider these enhancements as further exercises, drawing from other concepts in this chapter:
This exercise in building a multi-stage workflow should solidify your understanding of:
By working through the design and (even high-level) implementation of such a system, you are well on your way to mastering the construction of sophisticated multi-agent LLM applications. The patterns and challenges encountered here are representative of those found in more advanced and larger-scale agent teams.
Was this section helpful?
© 2025 ApX Machine Learning