Case Study: Multi-Agent Collaborative Content Creation System
Chapter 73: Case Study โ Multi-Agent Collaborative Content Creation System
Chapter Introduction
Truly excellent content is never just "a good article." It requires accurate information, compelling narrative, precise SEO layout, platform-adapted distribution formats, and rigorous editorial review. A single person juggling all of this inevitably makes tradeoffs; a team juggling it incurs heavy coordination overhead. This chapter designs a multi-agent collaborative content creation system where four specialized agents โ Researcher, Writer, Editor, SEO Expert โ collaborate under an Orchestrator Agent. Given a topic, the system automatically produces: a complete article + image generation prompts + SEO metadata + social media versions.
73.1 Requirements & System Goals
Traditional vs. Automated Workflow
Traditional content creation (manual):
Topic โ Research (1-2 days) โ Write (2-4 hrs) โ Edit (1-2 hrs)
โ SEO (30 min) โ Social adaptation (30 min)
Total: ~1.5-2 days
Target with multi-agent automation:
Total: ~15-30 min (including quality score โฅ 80 iterations)
Output Specification
| Deliverable | Specification | Format |
|---|---|---|
| Main article | 1500-3000 words, full structure | Markdown |
| Image prompts | 3-5 AI generation prompts | JSON |
| SEO metadata | Title / Description / Keywords | JSON |
| Twitter thread | 5-8 tweets | Text list |
| LinkedIn version | 800-word professional post | Markdown |
| Quality report | Per-dimension scores | JSON |
73.2 Multi-Agent Architecture
Agent Role Design
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Orchestrator Agent โ
โ (Task scheduling + Quality gating + Iteration control) โ
โ Responsible for: decompose โ assign โ aggregate โ score โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ coordinates
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ Researcher โ โ Writer โ โ Editor โ
โ Agent โ โ Agent โ โ Agent โ
โ โ โ โ โ โ
โ - Background โ โ - Draft article โ โ - Fact-checking โ
โ - Key facts โ โ - Narrative arc โ โ - Logic review โ
โ - Data points โ โ - Case stories โ โ - Style polish โ
โ - Keyword dig โ โ - Image prompts โ โ - Edit feedback โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ SEO Expert โ
โ Agent โ
โ โ
โ - Keyword opt โ
โ - Meta tags โ
โ - Social rewritesโ
โ - Publish strat โ
โโโโโโโโโโโโโโโโโโโ
Data Flow
[Input: Topic]
โ
[Researcher] โ Output: Research Brief (facts, data, angles, keywords)
โ
[Writer] reads brief โ Output: Draft article + image prompts
โ
[Editor] reads draft โ Output: Edit notes + revised article
โ
[SEO Expert] reads revision โ Output: SEO metadata + social versions
โ
[Orchestrator] Quality evaluation โ
Score < 80 โ request revisions
Score โฅ 80 โ output final content package
73.3 Full Implementation
Core Data Models
# content_system/models.py
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class ResearchBrief:
topic: str
background: str
key_facts: List[str]
statistics: List[dict] # [{data, source}]
target_keywords: List[str]
competitor_analysis: str
recommended_angle: str
sources: List[str]
@dataclass
class ContentPackage:
topic: str
article: str
seo_meta: dict
image_prompts: List[dict]
twitter_thread: List[str]
linkedin_post: str
quality_report: dict
generation_time_seconds: float
Orchestrator Agent
# content_system/orchestrator.py
import os, json, time
from openai import OpenAI
client = OpenAI(
base_url=os.getenv("HERMES_BASE_URL", "http://localhost:11434/v1"),
api_key=os.getenv("HERMES_API_KEY", "ollama"),
)
MODEL = os.getenv("HERMES_MODEL", "nous-hermes-2-mixtral-8x7b-dpo")
ORCHESTRATOR_PROMPT = """You are the coordinator of a multi-agent content creation system.
Your responsibilities:
1. Receive the topic and plan the creation workflow
2. Call specialized agents in sequence: Researcher โ Writer โ Editor โ SEO Expert
3. Evaluate each stage's output quality
4. If quality < 80/100, request revisions from the relevant agent
5. Compile the final content package
Quality scoring (100 points total):
- Information accuracy (25): facts supported by sources
- Narrative flow (20): engaging, logical progression
- Original value (20): unique angle and insights
- SEO readiness (15): natural keyword integration
- Reader value (20): genuinely helps the reader
Minimum publish threshold: total โฅ 80, accuracy โฅ 20"""
ORCHESTRATOR_TOOLS = [
{"type": "function", "function": {
"name": "run_researcher",
"description": "Invoke the Researcher agent to gather topic information",
"parameters": {"type": "object",
"properties": {"topic": {"type": "string"},
"research_focus": {"type": "array", "items": {"type": "string"}}},
"required": ["topic"]}
}},
{"type": "function", "function": {
"name": "run_writer",
"description": "Invoke the Writer agent to draft the article",
"parameters": {"type": "object",
"properties": {"research_brief": {"type": "object"},
"style": {"type": "string", "default": "conversational"},
"target_length": {"type": "integer", "default": 2000}},
"required": ["research_brief"]}
}},
{"type": "function", "function": {
"name": "run_editor",
"description": "Invoke the Editor agent to review and revise the draft",
"parameters": {"type": "object",
"properties": {"draft": {"type": "object"},
"research_brief": {"type": "object"},
"edit_focus": {"type": "array", "items": {"type": "string"}}},
"required": ["draft", "research_brief"]}
}},
{"type": "function", "function": {
"name": "run_seo_expert",
"description": "Invoke the SEO Expert to generate metadata and social versions",
"parameters": {"type": "object",
"properties": {"article": {"type": "object"},
"target_keywords": {"type": "array", "items": {"type": "string"}},
"platforms": {"type": "array", "items": {"type": "string"}}},
"required": ["article", "target_keywords"]}
}},
{"type": "function", "function": {
"name": "evaluate_quality",
"description": "Score the content across quality dimensions",
"parameters": {"type": "object",
"properties": {"article_content": {"type": "string"},
"research_brief": {"type": "object"}},
"required": ["article_content", "research_brief"]}
}},
{"type": "function", "function": {
"name": "compile_final_package",
"description": "Compile and return the complete content package",
"parameters": {"type": "object",
"properties": {"article": {"type": "string"},
"seo_data": {"type": "object"},
"social_versions": {"type": "object"},
"image_prompts": {"type": "array"},
"quality_report": {"type": "object"}},
"required": ["article", "seo_data", "quality_report"]}
}}
]
def run_content_system(topic: str, style: str = "conversational") -> dict:
start_time = time.time()
messages = [
{"role": "system", "content": ORCHESTRATOR_PROMPT},
{"role": "user", "content": f"""Create a complete content package for:
Topic: {topic}
Style: {style}
Required outputs:
1. Full article (1500-3000 words)
2. 3-5 AI image prompts
3. SEO metadata (title/description/keywords)
4. Twitter thread (5-8 tweets)
5. LinkedIn post (800 words)
6. Quality score report
Coordinate the specialized agents and ensure quality score โฅ 80."""}
]
final_package = None
for _ in range(20):
response = client.chat.completions.create(
model=MODEL, messages=messages, tools=ORCHESTRATOR_TOOLS,
tool_choice="auto", temperature=0.4
)
message = response.choices[0].message
messages.append(message)
if not message.tool_calls:
break
for tc in message.tool_calls:
name = tc.function.name
args = json.loads(tc.function.arguments)
result = _dispatch(name, args)
if name == "compile_final_package" and result.get("success"):
final_package = result.get("package")
messages.append({"role": "tool", "tool_call_id": tc.id,
"content": json.dumps(result)})
if final_package:
final_package["generation_time_seconds"] = time.time() - start_time
return final_package or {"status": "failed"}
Specialized Agents (Compact)
# content_system/agents/writer.py
import os, json
from openai import OpenAI
client = OpenAI(base_url=os.getenv("HERMES_BASE_URL"), api_key=os.getenv("HERMES_API_KEY"))
MODEL = os.getenv("HERMES_MODEL")
WRITER_PROMPT = """You are a skilled content writer who transforms complex information into engaging articles.
Writing principles:
- Open strong: hook the reader in the first 3 seconds
- Every section must deliver value โ no filler
- Use stories and cases to make abstractions concrete
- End with a clear call to action
Also generate AI image prompts (English, Midjourney/DALL-E format) for key sections."""
def run(research_brief: dict, style: str = "conversational", target_length: int = 2000) -> dict:
messages = [
{"role": "system", "content": WRITER_PROMPT},
{"role": "user", "content": f"""Write a {target_length}-word {style} article based on:
{json.dumps(research_brief, indent=2)}
Output as JSON:
{{
"title": "Article title",
"hook": "Opening hook (first 100 words)",
"sections": [{{"heading": "...", "content": "..."}}],
"conclusion": "Conclusion text",
"call_to_action": "CTA text",
"image_prompts": [{{"position": "header", "prompt": "English prompt", "description": "..."}}]
}}"""}
]
response = client.chat.completions.create(
model=MODEL, messages=messages, temperature=0.7,
max_tokens=4000, response_format={"type": "json_object"}
)
try:
return {"success": True, "draft": json.loads(response.choices[0].message.content)}
except Exception as e:
return {"success": False, "error": str(e)}
# content_system/agents/editor.py
EDITOR_PROMPT = """You are a rigorous senior content editor.
Tasks: fact-check, logic review, language polish, quality gating.
Review checklist:
โก All statistics sourced?
โก Logic consistent, no contradictions?
โก Language natural and fluent?
โก Title compelling?
โก Opening hook strong enough?
โก Conclusion tied to body?"""
def run_editor(draft: dict, research_brief: dict, edit_focus: list = None) -> dict:
messages = [
{"role": "system", "content": EDITOR_PROMPT},
{"role": "user", "content": f"""Review and revise this article:
Draft: {json.dumps(draft, indent=2)}
Research brief (for fact-checking): {json.dumps(research_brief, indent=2)}
Output JSON with: title, content (Markdown), editor_notes[], fact_check_results[],
quality_scores {{accuracy:0-25, narrative:0-20, originality:0-20, seo:0-15, value:0-20}},
total_score: 0-100"""}
]
response = client.chat.completions.create(
model=MODEL, messages=messages, temperature=0.2,
max_tokens=5000, response_format={"type": "json_object"}
)
try:
return {"success": True, "edited": json.loads(response.choices[0].message.content)}
except Exception as e:
return {"success": False, "error": str(e)}
73.4 Quality Scoring Engine
# content_system/quality.py
def evaluate_content_quality(article_content: str, research_brief: dict) -> dict:
scores = {}
# Accuracy (25 pts): key facts present in article
key_facts = research_brief.get("key_facts", [])
matches = sum(1 for f in key_facts if _fuzzy_match(article_content, f))
scores["accuracy"] = min(25, int(25 * matches / max(len(key_facts), 1)))
# Structure (15 pts)
has_headings = article_content.count("##") >= 2
has_conclusion = any(w in article_content.lower() for w in ["conclusion", "summary", "in summary"])
scores["structure"] = 15 if (has_headings and has_conclusion) else 8
# Length (10 pts)
wc = len(article_content.split())
scores["length"] = 10 if 400 <= wc <= 1200 else (6 if wc >= 200 else 3)
# Keyword coverage (15 pts)
keywords = research_brief.get("target_keywords", [])
kw_hits = sum(1 for kw in keywords if kw.lower() in article_content.lower())
scores["keyword_coverage"] = min(15, int(15 * kw_hits / max(len(keywords), 1)))
# Reader value proxy (20 pts): presence of examples, numbers, actionable advice
has_numbers = any(char.isdigit() for char in article_content)
has_examples = any(w in article_content.lower() for w in ["for example", "case study", "such as"])
scores["reader_value"] = 20 if (has_numbers and has_examples) else 12
total = sum(scores.values())
return {
"scores": scores, "total": total,
"grade": "A" if total >= 85 else "B" if total >= 70 else "C",
"pass": total >= 80,
"recommendations": _recommendations(scores)
}
def _fuzzy_match(text: str, fact: str) -> bool:
words = [w for w in fact.split() if len(w) > 3]
return sum(1 for w in words if w.lower() in text.lower()) >= len(words) * 0.6
def _recommendations(scores: dict) -> list:
recs = []
if scores.get("accuracy", 0) < 18:
recs.append("Add more specific data points and source citations")
if scores.get("structure", 0) < 12:
recs.append("Improve structure: add section headings and a clear conclusion")
if scores.get("keyword_coverage", 0) < 10:
recs.append("Naturally integrate more target keywords")
return recs
Chapter Summary
This chapter designed and implemented a production-grade multi-agent content creation system:
- Role specialization: Researcher/Writer/Editor/SEO Expert each handling their domain prevents quality averaging
- Orchestrator pattern: Central coordinator handles scheduling, quality gates, and iteration control
- Data flow contracts: Clear interfaces between agents enable independent testing and replacement
- Quality feedback loop: Built-in scoring ensures output reaches publishable standards
The core value of multi-agent systems is not parallel speed (collaborative agents are often sequential) but quality gains from specialization โ just as excellent content requires a researcher, writer, editor, and fact-checker working together rather than one person doing everything.
Discussion Questions
- How do you design inter-agent communication protocols that are both flexible and lossless?
- When the Editor's feedback conflicts with the Writer's stylistic choices, how should the Orchestrator arbitrate?
- How would you extend this system to support video scripts, podcast content, and other non-text formats?
- How do you design observability and debugging tooling for a multi-agent system?