← Back to DevBytes

Building a Content Writing Agent with AutoGen: Complete Guide

Building a Content Writing Agent with AutoGen: Complete Guide

AutoGen, Microsoft's open-source framework for multi-agent conversational systems, enables developers to build sophisticated AI workflows where multiple agents collaborate to accomplish complex tasks. In this tutorial, you'll learn how to build a complete content writing agent system—from initial research and outlining through drafting, editing, and final polishing—using AutoGen's powerful agent orchestration capabilities.

What is AutoGen?

AutoGen is a framework that simplifies the creation of multi-agent systems powered by large language models (LLMs). Rather than crafting monolithic prompts, AutoGen lets you define specialized agents—each with distinct roles, capabilities, and personas—that converse with each other to solve problems collaboratively. Key concepts include:

Why Content Writing Agents Matter

Manual content creation faces several challenges: writer's block, inconsistent quality, time-consuming research, and the difficulty of maintaining brand voice across large volumes of content. A multi-agent content writing system addresses these by:

Setting Up Your Environment

Installation and Dependencies

First, install the required packages. You'll need AutoGen itself plus a few supporting libraries for the content writing pipeline:

# Create a new project directory
mkdir content-writing-agent
cd content-writing-agent

# Create a virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install AutoGen and dependencies
pip install pyautogen
pip install openai
pip install python-dotenv
pip install requests  # For potential web research capabilities
pip install beautifulsoup4  # For content scraping in research phases

API Configuration

Create a .env file to store your API credentials securely, then configure AutoGen to use them. You can use OpenAI, Azure OpenAI, or any compatible LLM provider supported by AutoGen.

# .env file
OPENAI_API_KEY=your-openai-api-key-here
OPENAI_MODEL=gpt-4o
# Optional: Use different models for different agents
PLANNING_MODEL=gpt-4o-mini
WRITING_MODEL=gpt-4o
EDITING_MODEL=gpt-4o-mini

Now create the main configuration module that all agents will share:

# config.py
import os
from dotenv import load_dotenv
import autogen

load_dotenv()

# Define LLM configurations for different agent roles
planning_config = autogen.config_list_from_env(
    "PLANNING_MODEL",
    api_key_env="OPENAI_API_KEY",
    model_env="PLANNING_MODEL"
)

writing_config = autogen.config_list_from_env(
    "WRITING_MODEL",
    api_key_env="OPENAI_API_KEY",
    model_env="WRITING_MODEL"
)

editing_config = autogen.config_list_from_env(
    "EDITING_MODEL",
    api_key_env="OPENAI_API_KEY",
    model_env="EDITING_MODEL"
)

# Fallback: Use a single model for all agents if env vars not set
default_config = autogen.config_list_openai_aoai(
    api_key=os.getenv("OPENAI_API_KEY"),
    model=os.getenv("OPENAI_MODEL", "gpt-4o")
)

# Agent configuration dictionaries
PLANNER_CONFIG = {
    "config_list": planning_config or default_config,
    "temperature": 0.3,
    "timeout": 120,
}

WRITER_CONFIG = {
    "config_list": writing_config or default_config,
    "temperature": 0.7,
    "timeout": 180,
}

EDITOR_CONFIG = {
    "config_list": editing_config or default_config,
    "temperature": 0.2,
    "timeout": 120,
}

RESEARCHER_CONFIG = {
    "config_list": default_config,
    "temperature": 0.4,
    "timeout": 180,
}

Building the Content Writing Agent System

Core Architecture

Our content writing system uses four specialized agents orchestrated through a group chat pattern:

The workflow proceeds sequentially: Research → Plan → Write → Edit → Final Review. Each stage involves a two-agent conversation where the specialist agent produces work and a proxy agent (representing the user or system) provides feedback and approval.

Defining the Agents

Each agent needs a carefully crafted system prompt that defines its role, output format, and quality standards. Here's how to define them:

# agents.py
import autogen
from config import PLANNER_CONFIG, WRITER_CONFIG, EDITOR_CONFIG, RESEARCHER_CONFIG

# ============================================================
# RESEARCH AGENT - Gathers facts and background information
# ============================================================
research_system_message = """You are a Senior Research Analyst specializing in content research.

Your responsibilities:
1. Analyze the given topic thoroughly and identify 5-7 key subtopics or angles
2. For each subtopic, provide factual information, statistics, or expert perspectives
3. Identify the target audience's likely questions and pain points
4. Suggest credible sources or references where applicable
5. Output your research as a structured JSON object with these keys:
   - "topic_summary": A concise 2-3 sentence summary
   - "key_points": Array of objects with "point", "details", and "audience_question"
   - "sources": Array of suggested reference types
   - "audience_insights": Object describing target reader demographics and needs

Be thorough but concise. Focus on actionable insights that will guide the writer.
"""

research_agent = autogen.AssistantAgent(
    name="Research_Agent",
    system_message=research_system_message,
    llm_config=RESEARCHER_CONFIG,
)

# ============================================================
# PLANNING AGENT - Creates structured content outlines
# ============================================================
planning_system_message = """You are a Content Strategist and Outline Specialist.

Your responsibilities:
1. Review the research provided and create a detailed content outline
2. Structure the outline with: Title, Introduction, Main Sections (with sub-points), Conclusion
3. For each section, specify the key message and estimated word count
4. Consider SEO elements: suggest primary keywords, meta description, and header structure
5. Define the content's tone, voice, and style guidelines for the writer
6. Output your outline as a structured JSON object with these keys:
   - "title": The proposed article title
   - "meta_description": SEO meta description (150-160 chars)
   - "primary_keyword": Main target keyword
   - "secondary_keywords": Array of supporting keywords
   - "tone": Description of desired tone (e.g., "conversational yet authoritative")
   - "sections": Array of section objects with "heading", "key_message", "word_count", and "sub_points"

The outline should be comprehensive enough that a writer can produce excellent content from it alone.
"""

planning_agent = autogen.AssistantAgent(
    name="Planning_Agent",
    system_message=planning_system_message,
    llm_config=PLANNER_CONFIG,
)

# ============================================================
# WRITING AGENT - Drafts the actual content
# ============================================================
writing_system_message = """You are a Professional Content Writer and Copywriter.

Your responsibilities:
1. Write engaging, well-structured content following the provided outline
2. Maintain the specified tone and voice consistently throughout
3. Use clear transitions between sections and paragraphs
4. Incorporate the provided research naturally without forced keyword stuffing
5. Write for humans first, but keep SEO best practices in mind
6. Format output as clean HTML-ready text with proper heading hierarchy
7. Include a compelling introduction that hooks readers and a conclusion that reinforces key takeaways

Output format:
- Use markdown formatting (## for H2 headings, ### for H3, etc.)
- Write complete, polished paragraphs (no placeholders or TODO items)
- Include the full article from title to conclusion
- Total word count should match the outline specifications

Do NOT include meta-commentary about your writing process in the final output.
"""

writing_agent = autogen.AssistantAgent(
    name="Writing_Agent",
    system_message=writing_system_message,
    llm_config=WRITER_CONFIG,
)

# ============================================================
# EDITOR AGENT - Reviews and polishes content
# ============================================================
editing_system_message = """You are a Senior Content Editor and Quality Assurance Specialist.

Your responsibilities:
1. Review the draft for grammar, spelling, and punctuation errors
2. Check for consistency in tone, voice, and terminology
3. Verify that all points from the outline are adequately covered
4. Assess readability: sentence variety, paragraph length, and flow
5. Evaluate SEO elements: keyword usage, header structure, meta elements
6. Provide specific, actionable feedback organized by category
7. If the draft meets all quality standards, approve it with a "FINAL_APPROVAL: true" tag

Output your review as a structured JSON object:
{
  "grammar_issues": [...],
  "structure_feedback": "...",
  "tone_assessment": "...",
  "seo_check": {...},
  "overall_score": 1-10,
  "requires_revision": true/false,
  "specific_changes": [...],
  "final_approval": true/false
}

Be thorough but constructive. Your goal is to elevate the content, not discourage the writer.
"""

editor_agent = autogen.AssistantAgent(
    name="Editor_Agent",
    system_message=editing_system_message,
    llm_config=EDITOR_CONFIG,
)

Creating User Proxy Agents

User proxy agents act as the human-in-the-loop interface and can also simulate user behavior in automated workflows. We'll create specialized proxy agents for each stage:

# proxies.py
import autogen

# ============================================================
# RESEARCH PROXY - Initiates research and validates output
# ============================================================
research_proxy = autogen.UserProxyAgent(
    name="Research_Proxy",
    human_input_mode="NEVER",  # Fully automated for research
    code_execution_config=False,
    max_consecutive_auto_reply=1,
    system_message="""You are a proxy for the content team manager.
    When you receive research output from the Research_Agent:
    1. Verify it contains all required JSON fields
    2. If incomplete, ask the Research_Agent to fill in missing parts
    3. If complete, respond with 'RESEARCH_COMPLETE: true' and pass the data forward
    """,
)

# ============================================================
# PLANNING PROXY - Reviews outlines before passing to writer
# ============================================================
planning_proxy = autogen.UserProxyAgent(
    name="Planning_Proxy",
    human_input_mode="NEVER",
    code_execution_config=False,
    max_consecutive_auto_reply=1,
    system_message="""You are a proxy for the content strategist.
    When you receive an outline from the Planning_Agent:
    1. Check that all required sections are present
    2. Verify word count allocations are reasonable
    3. Confirm SEO elements are included
    4. If satisfied, respond with 'OUTLINE_APPROVED: true' and include the outline
    5. If issues found, ask specific questions for improvement
    """,
)

# ============================================================
# WRITING PROXY - Receives the draft and forwards to editing
# ============================================================
writing_proxy = autogen.UserProxyAgent(
    name="Writing_Proxy",
    human_input_mode="NEVER",
    code_execution_config=False,
    max_consecutive_auto_reply=1,
    system_message="""You are a proxy for the content manager.
    When you receive a draft from the Writing_Agent:
    1. Verify the draft is complete (has intro, body sections, conclusion)
    2. Check approximate word count
    3. If the draft seems complete, respond with 'DRAFT_RECEIVED: true' and forward it
    4. If incomplete, ask the Writing_Agent to complete the missing sections
    """,
)

# ============================================================
# EDITOR PROXY - Reviews editorial feedback and approves final
# ============================================================
editor_proxy = autogen.UserProxyAgent(
    name="Editor_Proxy",
    human_input_mode="NEVER",
    code_execution_config=False,
    max_consecutive_auto_reply=3,  # Allow revision cycles
    system_message="""You are a proxy for the editorial director.
    When you receive an editorial review from the Editor_Agent:
    1. If final_approval is true, respond with 'PUBLISH_READY: true' and include the final content
    2. If requires_revision is true, relay the specific changes to the Writing_Agent
    3. Manage up to 2 revision cycles before forcing final approval
    4. Track revision count and escalate if quality isn't improving
    """,
)

Creating the Orchestrated Workflow

The workflow chains multiple two-agent conversations into a complete pipeline. Each stage receives the output of the previous stage as context:

# workflow.py
import autogen
import json
import re
from typing import Dict, Optional
from agents import research_agent, planning_agent, writing_agent, editor_agent
from proxies import research_proxy, planning_proxy, writing_proxy, editor_proxy


class ContentWritingPipeline:
    """Orchestrates the complete content writing workflow using AutoGen agents."""
    
    def __init__(self):
        self.research_data: Optional[Dict] = None
        self.outline_data: Optional[Dict] = None
        self.draft_content: Optional[str] = None
        self.final_content: Optional[str] = None
        self.revision_count: int = 0
        self.max_revisions: int = 2
    
    def extract_json_from_message(self, message: str) -> Optional[Dict]:
        """Extract JSON object from an agent's message."""
        # Find JSON block in the message
        json_match = re.search(r'\{[\s\S]*\}', message)
        if json_match:
            try:
                return json.loads(json_match.group())
            except json.JSONDecodeError:
                # Try to find a markdown-embedded JSON block
                json_match = re.search(r'json\s*([\s\S]*?)\s*', message)
                if json_match:
                    try:
                        return json.loads(json_match.group(1))
                    except json.JSONDecodeError:
                        pass
        return None
    
    def run_research_phase(self, topic: str, audience: str = "general") -> Dict:
        """Phase 1: Research the topic."""
        print("=" * 60)
        print("PHASE 1: RESEARCH")
        print("=" * 60)
        
        initial_message = f"""
        Please research the following topic thoroughly:
        
        TOPIC: {topic}
        TARGET AUDIENCE: {audience}
        
        Provide your research as a structured JSON object with topic_summary, key_points, 
        sources, and audience_insights as specified in your instructions.
        """
        
        research_proxy.initiate_chat(
            research_agent,
            message=initial_message,
            max_turns=4
        )
        
        # Extract the research data from the conversation
        last_message = research_agent.last_message()
        if isinstance(last_message, dict):
            content = last_message.get("content", "")
        else:
            content = str(last_message) if last_message else ""
        
        self.research_data = self.extract_json_from_message(content)
        
        if not self.research_data:
            print("[WARNING] Could not parse research JSON. Using raw content.")
            self.research_data = {"raw_research": content, "topic": topic}
        
        print("[RESEARCH PHASE COMPLETE]")
        return self.research_data
    
    def run_planning_phase(self) -> Dict:
        """Phase 2: Create content outline based on research."""
        print("=" * 60)
        print("PHASE 2: PLANNING")
        print("=" * 60)
        
        research_summary = json.dumps(self.research_data, indent=2)
        
        planning_message = f"""
        Based on the following research, create a detailed content outline.
        
        RESEARCH DATA:
        {research_summary}
        
        Please provide your outline as a structured JSON object with all required fields:
        title, meta_description, primary_keyword, secondary_keywords, tone, and sections.
        Each section should have heading, key_message, word_count, and sub_points.
        """
        
        planning_proxy.initiate_chat(
            planning_agent,
            message=planning_message,
            max_turns=4
        )
        
        last_message = planning_agent.last_message()
        if isinstance(last_message, dict):
            content = last_message.get("content", "")
        else:
            content = str(last_message) if last_message else ""
        
        self.outline_data = self.extract_json_from_message(content)
        
        if not self.outline_data:
            print("[WARNING] Could not parse outline JSON. Using raw content.")
            self.outline_data = {"raw_outline": content}
        
        print("[PLANNING PHASE COMPLETE]")
        return self.outline_data
    
    def run_writing_phase(self) -> str:
        """Phase 3: Draft the content."""
        print("=" * 60)
        print("PHASE 3: WRITING")
        print("=" * 60)
        
        outline_str = json.dumps(self.outline_data, indent=2)
        research_str = json.dumps(self.research_data, indent=2) if self.research_data else ""
        
        writing_message = f"""
        Please write a complete article based on the following outline and research.
        
        OUTLINE:
        {outline_str}
        
        RESEARCH:
        {research_str}
        
        Write the complete article using markdown formatting. Include all sections from the outline.
        The article should be polished, engaging, and ready for editorial review.
        Do not include meta-commentary or placeholder text.
        """
        
        writing_proxy.initiate_chat(
            writing_agent,
            message=writing_message,
            max_turns=4
        )
        
        last_message = writing_agent.last_message()
        if isinstance(last_message, dict):
            content = last_message.get("content", "")
        else:
            content = str(last_message) if last_message else ""
        
        self.draft_content = content
        print("[WRITING PHASE COMPLETE]")
        return self.draft_content
    
    def run_editing_phase(self) -> Dict:
        """Phase 4: Edit and review the draft."""
        print("=" * 60)
        print("PHASE 4: EDITING")
        print("=" * 60)
        
        outline_str = json.dumps(self.outline_data, indent=2)
        
        editing_message = f"""
        Please review the following content draft against the original outline.
        
        ORIGINAL OUTLINE:
        {outline_str}
        
        DRAFT CONTENT:
        {self.draft_content}
        
        Provide your editorial review as a structured JSON object with grammar_issues, 
        structure_feedback, tone_assessment, seo_check, overall_score, requires_revision, 
        specific_changes, and final_approval.
        """
        
        editor_proxy.initiate_chat(
            editor_agent,
            message=editing_message,
            max_turns=6  # Allow for revision cycles
        )
        
        # Check the conversation history for final approval
        editor_response = editor_agent.last_message()
        if isinstance(editor_response, dict):
            content = editor_response.get("content", "")
        else:
            content = str(editor_response) if editor_response else ""
        
        editorial_feedback = self.extract_json_from_message(content)
        
        if editorial_feedback and editorial_feedback.get("final_approval", False):
            self.final_content = self.draft_content
            print("[CONTENT APPROVED - READY TO PUBLISH]")
        elif editorial_feedback and editorial_feedback.get("requires_revision", False):
            print(f"[REVISIONS REQUIRED] - {editorial_feedback.get('specific_changes', [])}")
            self._handle_revisions(editorial_feedback)
        
        print("[EDITING PHASE COMPLETE]")
        return editorial_feedback or {}
    
    def _handle_revisions(self, feedback: Dict):
        """Handle revision cycles between editor and writer."""
        while self.revision_count < self.max_revisions:
            self.revision_count += 1
            print(f"--- Revision Cycle {self.revision_count} ---")
            
            revision_message = f"""
            Please revise your draft based on the following editorial feedback:
            
            FEEDBACK:
            {json.dumps(feedback.get('specific_changes', []), indent=2)}
            
            OVERALL SCORE: {feedback.get('overall_score', 'N/A')}
            STRUCTURE FEEDBACK: {feedback.get('structure_feedback', 'N/A')}
            TONE ASSESSMENT: {feedback.get('tone_assessment', 'N/A')}
            
            Please provide the fully revised draft. Keep all good elements and fix the issues.
            """
            
            writing_proxy.initiate_chat(
                writing_agent,
                message=revision_message,
                max_turns=2
            )
            
            revised = writing_agent.last_message()
            if isinstance(revised, dict):
                self.draft_content = revised.get("content", "")
            else:
                self.draft_content = str(revised) if revised else self.draft_content
            
            # Re-evaluate
            editor_proxy.initiate_chat(
                editor_agent,
                message=f"""Please re-review this revised draft:
                
                REVISED DRAFT:
                {self.draft_content}
                
                Provide updated editorial review with final_approval field.
                """,
                max_turns=2
            )
            
            new_feedback_msg = editor_agent.last_message()
            if isinstance(new_feedback_msg, dict):
                fb_content = new_feedback_msg.get("content", "")
            else:
                fb_content = str(new_feedback_msg) if new_feedback_msg else ""
            
            new_feedback = self.extract_json_from_message(fb_content)
            
            if new_feedback and new_feedback.get("final_approval", False):
                self.final_content = self.draft_content
                print("[REVISIONS APPROVED]")
                break
            elif new_feedback:
                feedback = new_feedback
        
        # If max revisions reached, accept the last draft
        if self.final_content is None:
            self.final_content = self.draft_content
            print("[MAX REVISIONS REACHED - Accepting current draft]")
    
    def run_full_pipeline(self, topic: str, audience: str = "general") -> str:
        """Execute the complete content writing pipeline."""
        print("\n" + "=" * 60)
        print("STARTING CONTENT WRITING PIPELINE")
        print(f"Topic: {topic}")
        print(f"Audience: {audience}")
        print("=" * 60 + "\n")
        
        self.run_research_phase(topic, audience)
        self.run_planning_phase()
        self.run_writing_phase()
        self.run_editing_phase()
        
        print("\n" + "=" * 60)
        print("PIPELINE COMPLETE")
        print("=" * 60)
        
        return self.final_content

Putting It All Together: Complete Executable Script

Here's the main entry point that ties everything together. Save this as main.py:

# main.py
"""
Content Writing Agent System using AutoGen
===========================================
A multi-agent system that researches, plans, writes, and edits content.
Usage: python main.py --topic "Your Topic Here" --audience "general"
"""

import argparse
import os
from dotenv import load_dotenv
from workflow import ContentWritingPipeline

load_dotenv()


def save_output(content: str, topic: str):
    """Save the final content to a markdown file."""
    # Create output directory
    os.makedirs("output", exist_ok=True)
    
    # Generate filename from topic
    filename = topic.lower().replace(" ", "-")[:50] + ".md"
    filepath = os.path.join("output", filename)
    
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(content)
    
    print(f"\n[OUTPUT SAVED] → {filepath}")


def main():
    parser = argparse.ArgumentParser(
        description="Generate content using the AutoGen Content Writing Agent System"
    )
    parser.add_argument(
        "--topic",
        type=str,
        required=True,
        help="The topic to generate content about"
    )
    parser.add_argument(
        "--audience",
        type=str,
        default="general",
        help="Target audience description (default: 'general')"
    )
    parser.add_argument(
        "--max-revisions",
        type=int,
        default=2,
        help="Maximum number of revision cycles (default: 2)"
    )
    parser.add_argument(
        "--verbose",
        action="store_true",
        help="Print detailed agent conversation logs"
    )
    
    args = parser.parse_args()
    
    # Create and configure pipeline
    pipeline = ContentWritingPipeline()
    pipeline.max_revisions = args.max_revisions
    
    if not args.verbose:
        # Suppress detailed AutoGen logs for cleaner output
        import autogen
        autogen.ChatAgent.logger.setLevel("WARNING")
    
    # Run the full pipeline
    final_content = pipeline.run_full_pipeline(
        topic=args.topic,
        audience=args.audience
    )
    
    if final_content:
        print("\n" + "=" * 40)
        print("FINAL CONTENT PREVIEW (first 500 chars):")
        print("=" * 40)
        print(final_content[:500] + "...")
        
        save_output(final_content, args.topic)
    else:
        print("[ERROR] Pipeline did not produce final content.")
        print("Check agent configurations and API connectivity.")


if __name__ == "__main__":
    main()

Run the system with:

python main.py --topic "Building Scalable Microservices with Python" --audience "senior developers"

Advanced Features and Customization

Adding Research Capabilities with Web Search

To make the research agent more powerful, integrate real web search using a tool function. AutoGen supports registering custom functions that agents can invoke:

# research_tools.py
import autogen
import requests
from bs4 import BeautifulSoup
from typing import List, Dict


def search_web(query: str, num_results: int = 5) -> List[Dict]:
    """
    Search the web for relevant content.
    In production, replace this with a real search API (SerpAPI, Google Custom Search, etc.)
    """
    # This is a placeholder implementation
    # For production, use: SerpAPI, Google Custom Search API, or Tavily
    search_results = []
    
    # Example using DuckDuckGo's API (no API key required for basic usage)
    try:
        response = requests.get(
            "https://api.duckduckgo.com/",
            params={
                "q": query,
                "format": "json",
                "no_html": 1,
                "skip_disambig": 1
            },
            timeout=10
        )
        data = response.json()
        
        # Extract relevant fields
        if data.get("Abstract"):
            search_results.append({
                "title": data.get("Heading", query),
                "snippet": data.get("Abstract", ""),
                "source": data.get("AbstractURL", "")
            })
        
        for topic in data.get("RelatedTopics", [])[:num_results - 1]:
            if isinstance(topic, dict) and topic.get("Text"):
                search_results.append({
                    "title": topic.get("FirstURL", "").split("/")[-1],
                    "snippet": topic.get("Text", ""),
                    "source": topic.get("FirstURL", "")
                })
    except Exception as e:
        search_results.append({"error": f"Search failed: {str(e)}"})
    
    return search_results[:num_results]


# Register the search function with AutoGen
def register_research_tools(agent):
    """Register web search capability with an agent."""
    autogen.register_function(
        func=search_web,
        caller=agent,
        executor=agent,
        name="search_web",
        description="Search the web for information on a given query. Returns relevant snippets and sources."
    )

Update your research agent to use this tool:

# Enhanced research agent setup in agents.py
from research_tools import register_research_tools

# After creating research_agent:
register_research_tools(research_agent)

# Update the system message to instruct the agent to use the search tool
research_agent.system_message += """
\nYou have access to a 'search_web' function. Use it to gather current, factual information.
When you call search_web, analyze the results and incorporate them into your research JSON.
Always cite sources when using web search results.
"""

Implementing Feedback Loops with Human-in-the-Loop

For production content workflows, you may want human approval at key stages. Switch the proxy agents to human_input_mode="ALWAYS" at critical checkpoints:

# human_review_config.py
import autogen

# Create a human-review proxy that pauses for approval at key stages
human_review_proxy = autogen.UserProxyAgent(
    name="Human_Reviewer",
    human_input_mode="ALWAYS",  # Pauses for human input at each turn
    code_execution_config=False,
    max_consecutive_auto_reply=0,
    system_message="""You are the human content director.
    Review the agent's output and provide feedback or approval.
    - Type 'APPROVED' to move to the next phase
    - Type specific feedback to request changes
    - Type 'EXIT' to end the workflow
    """,
)

# Use this proxy for outline approval and final content sign-off
def create_interactive_pipeline():
    """Create a pipeline variant with human review gates."""
    from agents import planning_agent, writing_agent, editor_agent
    
    # Phase 1: Automated research
    # Phase 2: Human reviews outline
    # Phase 3: Automated writing
    # Phase 4: Human reviews final content
    
    # Insert human_review_proxy at outline and final stages
    # ... (implementation details depend on workflow structure)
    pass

Customizing Agent Personas for Brand Voice

Different brands require different voices. Create persona templates that you can swap in:

# personas.py

PERSONAS = {
    "tech_startup": {
        "tone": "Innovative, forward-thinking, accessible",
        "writing_style": "Use short paragraphs, bold claims, and concrete examples. Avoid jargon.",
        "example": "Write like Stripe's blog or Notion's documentation.",
        "system_additions": """
        Write with energy and optimism. Use active voice. 
        Start sentences with verbs. Keep paragraphs under 4 sentences.
        Include specific numbers and metrics where possible.
        """,
    },
    "enterprise": {
        "tone": "Professional, authoritative, solution-oriented",
        "writing_style": "Structured, thorough, with clear business value propositions.",
        "example": "Write like McKinsey insights or AWS documentation.",
        "system_additions": """
        Maintain a formal yet approachable tone. 
        Structure content with clear executive summaries.
        Include ROI-focused language and implementation considerations.
        """,
    },
    "educational": {
        "tone": "Clear, patient, encouraging",
        "writing_style": "Progressive disclosure, analogies, and step-by-step explanations.",
        "example": "Write like Khan Academy or freeCodeCamp tutorials.",
        "system_additions": """
        Break complex concepts into digestible chunks.
        Use analogies and real-world examples.
        Include 'check your understanding' moments.
        Assume the reader is intelligent but new to the topic.
        """,
    },
    "conversational": {
        "tone": "Friendly, witty, relatable",
        "writing_style": "Direct address, humor where appropriate, storytelling elements.",
        "example": "Write like a smart friend explaining something over coffee.",
        "system_additions": """
        Use 'you' and 'we' liberally. Include personal anecdotes.
        Use contractions. Keep it light but substantive.
        Crack a joke if it fits naturally.
        """,
    },
}


def apply_persona(agent, persona_name: str):
    """Apply a brand persona to an agent's system message."""
    if persona_name in

— Ad —

Google AdSense will appear here after approval

← Back to all articles