Introduction: The Power of AI Agent Collaboration

CrewAI is revolutionizing how we build AI systems by enabling multiple specialized agents to collaborate on complex tasks. Unlike single-agent approaches, CrewAI creates a coordinated "crew" of AI agents that work together, each handling different aspects of a workflow. This approach mirrors human team collaboration, where specialists combine their expertise to achieve outcomes greater than what any individual could accomplish alone.

My Multi-Agent Publishing System

For AI Agent Week MTY, I adapted an example from the DeepLearning.AI Multi-Agent Systems course and extended it to create a complete content production pipeline using CrewAI. Starting with the course's foundation of collaborative agents, I enhanced the system to not only generate content but also publish it directly to Dev.to. The system consists of four specialized agents:

  1. Content Planner: Analyzes the topic, identifies trends, determines target audience, and creates a structured outline
  2. Content Writer: Transforms the plan into engaging, SEO-optimized content with proper structure
  3. Editor: Reviews the draft for accuracy, clarity, and alignment with best practices
  4. Publisher: Formats the post for Dev.to, adds appropriate tags, and handles the API integration

What makes this implementation unique is that I adapted it to use Gemini instead of OpenAI, and added a custom publishing agent that can directly post content to Dev.to through their API.

Implementation: A Beginner's Guide to CrewAI

If you're new to CrewAI but familiar with Python, here's a complete walkthrough of how to build this system:

Step 1: Setting Up Your Environment

First, create a new Google Colab notebook (or use Jupyter) and install the necessary packages:

# Install CrewAI and supporting libraries
!pip install crewai==0.28.8 crewai_tools==0.1.6 langchain_community==0.0.29
!pip install requests
!pip install 'crewai[tools]'
!pip install langchain-google-genai

# Suppress warnings for cleaner output
import warnings
warnings.filterwarnings('ignore')

Step 2: Setting Up Your API Keys

CrewAI needs access to an LLM. I used Gemini instead of OpenAI, so we need to set up the Gemini API key:

import os
from crewai import Agent, Task, Crew, LLM
from langchain.tools import Tool
import requests
import json

# Set your API keys as environment variables
# Replace these with your actual API keys
os.environ["GEMINI_API_KEY"] = "your-gemini-api-key"
os.environ["DEVTO_API_KEY"] = "your-devto-api-key"

# Configure Gemini as our LLM
llm = LLM(
    model="gemini/gemini-2.0-flash-exp",  # Note the "gemini/" prefix
    temperature=0.7,
    api_key=os.environ["GEMINI_API_KEY"]
)

Step 3: Creating Your Agents

In CrewAI, each agent has a specific role, goal, and backstory that shapes how they approach tasks:

# Content Planner Agent
planner = Agent(
    role="Content Planner",
    goal="Plan engaging and factually accurate content on {topic}",
    backstory="You're working on planning a blog article "
              "about the topic: {topic}."
              "You collect information that helps the "
              "audience learn something "
              "and make informed decisions. "
              "Your work is the basis for "
              "the Content Writer to write an article on this topic.",
    allow_delegation=False,  # This agent works independently
    llm=llm,                 # Uses our configured Gemini LLM
    verbose=True             # Shows detailed output during execution
)

# Content Writer Agent
writer = Agent(
    role="Content Writer",
    goal="Write insightful and factually accurate "
         "opinion piece about the topic: {topic}",
    backstory="You're working on a writing "
              "a new opinion piece about the topic: {topic}. "
              "You base your writing on the work of "
              "the Content Planner, who provides an outline "
              "and relevant context about the topic. "
              "You follow the main objectives and "
              "direction of the outline, "
              "as provide by the Content Planner.",
    allow_delegation=False,
    llm=llm,
    verbose=True
)

# Editor Agent
editor = Agent(
    role="Editor",
    goal="Edit a given blog post to align with "
         "the writing style of the organization. ",
    backstory="You are an editor who receives a blog post "
              "from the Content Writer. "
              "Your goal is to review the blog post "
              "to ensure that it follows journalistic best practices,"
              "provides balanced viewpoints "
              "when providing opinions or assertions.",
    allow_delegation=False,
    llm=llm,
    verbose=True
)

Step 4: Creating a Custom Publishing Tool

The key innovation in my implementation is adding a custom tool that allows the Publisher agent to interact with the Dev.to API:

from crewai.tools import BaseTool, tool
from pydantic import BaseModel, Field
from typing import Type, List, Optional

# Define the input schema for our tool
class DevtoPublishInput(BaseModel):
    """Input schema for publishing to Dev.to."""
    title: str = Field(..., description="Article title")
    content: str = Field(..., description="Content in Markdown format")
    tags: Optional[List[str]] = Field(None, description="List of tags (max 4)")
    series: Optional[str] = Field(None, description="Series name if part of one")
    published: bool = Field(False, description="True to publish, False for draft")

# Create the custom publishing tool
class DevtoPublishTool(BaseTool):
    name: str = "publish_to_devto"
    description: str = "Publishes an article to Dev.to using its API"
    args_schema: Type[BaseModel] = DevtoPublishInput

    def _run(
        self,
        title: str,
        content: str,
        tags: Optional[List[str]] = None,
        series: Optional[str] = None,
        published: bool = False
    ) -> str:
        """Publishes an article to Dev.to."""
        api_key = os.environ.get("DEVTO_API_KEY")
        if not api_key:
            return "Error: Dev.to API key not configured. Set DEVTO_API_KEY."

        # Prepare the article data
        article_data = {
            "article": {
                "title": title,
                "body_markdown": content,
                "published": published
            }
        }

        # Add tags if provided (max 4 allowed)
        if tags:
            if len(tags) > 4:
                tags = tags[:4]  # Dev.to allows max 4 tags
            article_data["article"]["tags"] = tags

        # Add series if provided
        if series:
            article_data["article"]["series"] = series

        # Send request to Dev.to API
        headers = {
            "api-key": api_key,
            "Content-Type": "application/json"
        }

        try:
            response = requests.post(
                "https://dev.to/api/articles",
                json=article_data,
                headers=headers
            )

            if response.status_code not in [200, 201]:
                return f"Error: {response.status_code} - {response.text}"

            result = response.json()
            article_url = result.get('url', 'Not available')
            return f"Article {'published' if published else 'saved as draft'}. URL: {article_url}"
        except Exception as e:
            return f"Error connecting to Dev.to API: {str(e)}"

# Initialize our tool
devto_tool = DevtoPublishTool()

Step 5: Creating the Publisher Agent with Our Custom Tool

Now we can create a Publisher agent that uses our custom tool:

# Publisher Agent with Dev.to Publishing Tool
publisher = Agent(
    role="Dev.to Publisher",
    goal="Format and publish technical articles on Dev.to",
    backstory="You're a technical content strategist specializing in "
              "developer-focused content. You know how to format and "
              "optimize articles for the Dev.to platform to maximize "
              "engagement and visibility in the developer community.",
    llm=llm,
    verbose=True,
    tools=[devto_tool]  # Attach our custom tool to this agent
)

Step 6: Creating Tasks for Each Agent

Each agent needs a specific task that defines what they should do:

# Task for the Content Planner
plan = Task(
    description=(
        "1. Prioritize the latest trends, key players, "
            "and noteworthy news on {topic}.\n"
        "2. Identify the target audience, considering "
            "their interests and pain points.\n"
        "3. Develop a detailed content outline including "
            "an introduction, key points, and a call to action.\n"
        "4. Include SEO keywords and relevant data or sources."
    ),
    expected_output="A comprehensive content plan document "
        "with an outline, audience analysis, "
        "SEO keywords, and resources.",
    agent=planner,
)

# Task for the Content Writer
write = Task(
    description=(
        "1. Use the content plan to craft a compelling "
            "blog post on {topic}.\n"
        "2. Incorporate SEO keywords naturally.\n"
        "3. Sections/Subtitles are properly named "
            "in an engaging manner.\n"
        "4. Ensure the post is structured with an "
            "engaging introduction, insightful body, "
            "and a summarizing conclusion.\n"
        "5. Proofread for grammatical errors and "
            "alignment with the brand's voice.\n"
    ),
    expected_output="A well-written blog post "
        "in markdown format, ready for publication, "
        "each section should have 2 or 3 paragraphs.",
    agent=writer,
)

# Task for the Editor
edit = Task(
    description=("Proofread the given blog post for "
                 "grammatical errors and "
                 "alignment with the brand's voice."),
    expected_output="A well-written blog post in markdown format, "
                    "ready for publication, "
                    "each section should have 2 or 3 paragraphs.",
    agent=editor
)

# Task for the Publisher
publish = Task(
    description="""
    Prepare and publish the edited article on Dev.to. You must:
    1. Optimize the title for the developer audience
    2. Format the content properly in Markdown
    3. Select up to 4 relevant tags
    4. Decide if the article should be part of a series
    5. Save as a draft (published=False) initially

    Use the publish_to_devto tool to submit the article to Dev.to.
    """,
    expected_output="""
    A confirmation message that the article has been successfully published to Dev.to as a draft,
    including the title, tags selected, and URL of the article if available.
    """,
    agent=publisher,
    context=[edit]  # This provides the edited content as context
)

Step 7: Assembling and Running Your Crew

Finally, we create a crew with all our agents and tasks, then start the process:

# Create our crew with all agents and tasks
crew = Crew(
    agents=[planner, writer, editor, publisher],
    tasks=[plan, write, edit, publish],
    verbose=True  # Show detailed logs during execution
)

# Start the process with our chosen topic
result = crew.kickoff(inputs={"topic": "AI agents"})

# Display the results
from IPython.display import display, Markdown
display(Markdown(result))

That's it! This complete workflow will:

  1. Generate a content plan for your topic
  2. Write a blog post based on that plan
  3. Edit the post for clarity and style
  4. Publish it to Dev.to as a draft

Challenges & Solutions

The main challenge I faced was adapting the system from OpenAI to Gemini. This required:

  1. Configuring the LLM differently: llm = LLM(model="gemini/gemini-2.0-flash-exp", temperature=0.7)
  2. Handling different response formats between AI providers
  3. Building a custom Dev.to publishing tool that could process the output format from Gemini

Results & Demo

This project successfully generated and published a comprehensive article on AI agents to Dev.to (view the published article) which is my previous blog post. The system demonstrates how CrewAI can automate complex workflows while maintaining high-quality output through specialized agent collaboration.

This approach has wide-ranging applications:

  • Content teams can accelerate production while maintaining editorial standards
  • Developers can build workflow automation systems that handle complex, multi-stage processes
  • Organizations can create scalable content strategies with consistent quality and messaging

When I showcased this project at AI Agent Week MTY, the audience was incredibly engaged. Developers were excited to see the system in action, asking thoughtful questions about agent collaboration and API integration. These discussions enriched the learning experience for everyone involved, as we explored different approaches and shared insights together. The collective enthusiasm demonstrated how multi-agent systems are capturing the imagination of the developer community and opening new possibilities for AI applications.

Acknowledgments

This code is based on the Multi-Agent Systems course from DeepLearning.AI platform, with additional custom functionality for publishing to Dev.to. If you're interested in learning more about CrewAI and multi-agent systems, check out their excellent course: Multi-AI Agent Systems with CrewAI.

You can find the complete implementation of this project in my GitHub repository: AI Agent Week MTY. Feel free to fork it, experiment with it, or contribute improvements!