Day 56 of 80

Multi-Agent Systems

Phase 6: Frameworks & Agents

What You'll Build Today

Welcome to Day 56! Today, we are graduating from building single AI assistants to building an entire AI Workforce.

Imagine you are running a digital marketing agency. You need to research a topic, write a blog post about it, and then edit that post to ensure it fits your brand voice. You could try to do this all yourself, or you could hire a team where everyone is an expert in their specific role.

Today, you will build a Content Creation Crew using the CrewAI framework. Your system will simulate a digital newsroom with three distinct AI employees:

  • The Researcher: Scours for information and identifies key trends.
  • The Writer: Takes raw research and crafts a compelling narrative.
  • The Editor: Reviews the draft for tone, clarity, and formatting.
  • Here is what you will learn:

    * Role-Based Agent Design: Why giving an AI a specific "job title" and "backstory" makes it smarter than a generic chatbot.

    * Task Atomicity: How to break a large project into small, chainable steps.

    * Sequential Processes: How to pass the output of one agent automatically into the input of the next.

    * Delegation: How agents can work together to solve problems without your constant intervention.

    Let's start building your team.

    ---

    The Problem

    Up until now, we have mostly treated Large Language Models (LLMs) like a very smart individual. We give them a prompt, and they give us an answer.

    But what happens when the task is complex? Let's say we want a high-quality, fact-checked article about "The Future of AI in Agriculture."

    If you try to do this with a single prompt, you run into the "Jack of all trades, master of none" problem.

    The Painful Code (The "God Prompt")

    Look at this attempt to do everything at once. This is what we want to avoid:

    import os
    

    from langchain_openai import ChatOpenAI

    # Assume API key is set in environment variables

    llm = ChatOpenAI(model="gpt-4")

    # One massive prompt trying to do three different jobs

    god_prompt = """

    I need you to act as a Researcher, a Writer, and an Editor.

  • First, think about the current state of AI in Agriculture. content.
  • Identify 3 key trends.
  • Then, write a 500-word blog post about these trends.
  • Finally, critique your own work. Check for grammatical errors,
  • ensure the tone is professional yet exciting, and rewrite the

    intro if it is boring.

    Output the final polished blog post only.

    """

    response = llm.invoke(god_prompt)

    print(response.content)

    Why This Fails

  • Loss of Focus: The model tries to research and write simultaneously. It often hallucinates facts to fit the narrative flow because it isn't separating the "fact-finding" phase from the "creative writing" phase.
  • Self-Correction is Hard: Asking a model to critique its own work in the same generation pass rarely works well. It is biased towards what it just generated.
  • No Transparency: If the output is bad, you don't know if the research was wrong or if the writing style was just poor. You can't debug the process.
  • It feels like asking one employee to be the CEO, the janitor, and the accountant all in the same hour. They might get it done, but it will be messy.

    There has to be a way to separate these concerns.

    ---

    Let's Build It

    The solution is a Multi-Agent System. We will use CrewAI, a framework designed specifically to orchestrate role-playing AI agents.

    Step 1: Installation and Setup

    First, we need to install the library.

    ``bash

    pip install crewai langchain_openai

    `

    Now, let's set up our imports and the LLM we want to use. We will use OpenAI's GPT-4 (or GPT-3.5-turbo) for this, as it follows complex instructions well.

    import os
    

    from crewai import Agent, Task, Crew, Process

    # You must have your OPENAI_API_KEY set in your environment # os.environ["OPENAI_API_KEY"] = "sk-..." # Define the specific model we want our agents to use # (CrewAI automatically picks up the OPENAI_API_KEY from env)

    model_name = "gpt-4"

    Step 2: Define the Agents

    An Agent in CrewAI is like an employee. It needs three things:

  • Role: What is their job title?
  • Goal: What are they trying to achieve?
  • Backstory: This is the secret sauce. Giving the AI a persona helps it stay in character and produce higher-quality, specific outputs.
  • Let's create our Researcher and Writer.

    # 1. The Senior Researcher
    

    researcher = Agent(

    role='Senior Technology Researcher',

    goal='Uncover groundbreaking technologies in a specific topic',

    backstory="""You are a veteran tech analyst with an eye for

    emerging trends. You don't just find facts; you find the

    narrative behind the data. You are skeptical and thorough.""",

    verbose=True, # This lets us see what the agent is thinking

    allow_delegation=False

    )

    # 2. The Content Writer

    writer = Agent(

    role='Tech Content Strategist',

    goal='Craft compelling content on tech advancements',

    backstory="""You are a renowned tech journalist known for

    simplifying complex topics. You write in an engaging,

    optimistic, but professional tone. You rely on the Researcher

    for facts and focus on the story.""",

    verbose=True,

    allow_delegation=False

    )

    Why this matters: Notice the
    backstory. The Researcher is told to be "skeptical," while the Writer is told to be "optimistic." If we used one model, we couldn't easily balance these two opposing viewpoints.

    Step 3: Define the Tasks

    A Task is a specific assignment given to an agent. It needs a description and an expected output format.

    topic = "AI in Healthcare"
    
    # Task for the Researcher
    

    task1 = Task(

    description=f"""Conduct a comprehensive analysis of the latest advancements

    in {topic}. Identify key trends, potential benefits, and risks.

    Focus on the year 2024.""",

    expected_output="A full analysis report in bullet points regarding the latest trends.",

    agent=researcher

    )

    # Task for the Writer

    task2 = Task(

    description=f"""Using the insights provided, develop an engaging blog

    post about {topic}. The post should be informative yet accessible

    to a general audience. Avoid jargon where possible.""",

    expected_output="A 4 paragraph blog post formatted in markdown.",

    agent=writer

    )

    Why this matters: We don't need to manually pass the output of
    task1 into task2. CrewAI handles this context sharing automatically because they are part of the same "Crew."

    Step 4: The Editor Agent

    Let's add our quality control layer. The Editor ensures the Writer didn't get lazy.

    # 3. The Editor
    

    editor = Agent(

    role='Chief Editor',

    goal='Ensure content quality and adherence to brand voice',

    backstory="""You are a strict editor who prioritizes clarity

    and grammatical perfection. You hate passive voice and

    overly complex sentences.""",

    verbose=True,

    allow_delegation=True # The editor can assign work to others if needed

    )

    # Task for the Editor

    task3 = Task(

    description="""Proofread the blog post. Check for grammatical errors

    and ensure the tone is professional. If the post is too dry,

    make it more engaging.""",

    expected_output="The final, polished blog post ready for publication.",

    agent=editor

    )

    Step 5: Assembling the Crew

    Now we bring the agents and tasks together into a Crew. We define the process as sequential, meaning Task 1 happens, then Task 2, then Task 3.

    crew = Crew(
    

    agents=[researcher, writer, editor],

    tasks=[task1, task2, task3],

    verbose=2, # High verbosity to see the log

    process=Process.sequential

    )

    Step 6: Run the Crew

    This is the moment of truth. We "kickoff" the process.

    print(f"Starting the crew for topic: {topic}...\n")
    
    

    result = crew.kickoff()

    print("\n\n########################")

    print("## HERE IS THE RESULT ##")

    print("########################\n")

    print(result)

    What you will see:

    When you run this, watch the console. You will see the Researcher "thinking," then producing a report. Then the Writer picks up that report (without you doing anything) and drafts the post. Finally, the Editor polishes it.

    This is an autonomous pipeline.

    ---

    Now You Try

    You have a working content team. Now, let's expand their capabilities.

  • The Social Media Manager:
  • Create a new Agent called social_manager and a new Task. Their job is to take the final output from the Editor and generate a LinkedIn post and a Twitter thread summarizing the article. Add them to the end of the crew.

  • Change the Persona:
  • Modify the Writer's backstory. Instead of a "Tech Journalist," make them a "Pirate" or a "Shakespearean Poet." Run the crew again. Notice how the facts (from the Researcher) stay the same, but the style changes completely. This proves the separation of concerns works.

  • File Output:
  • Right now, the result just prints to the console. Modify the code to save the final result to a file named article.md. Hint: You can do this with standard Python file handling after crew.kickoff() returns.

    ---

    Challenge Project: The "Reject and Revise" Loop

    In our current setup, the Editor edits the text directly. But in a real office, a Chief Editor might reject a draft and send it back to the Writer with notes.

    Your challenge is to implement a workflow where the Editor provides feedback, and the Writer must rewrite based on that feedback.

    Requirements:
  • Create a Reviewer agent (instead of just an Editor) whose goal is to list critiques of the draft, not fix them.
  • Create a task for the Reviewer: "Analyze the draft and provide a list of 3 specific improvements needed."
  • Create a final task for the Writer: "Take the critique from the Reviewer and rewrite the blog post to address the feedback."
  • The sequence should be: Researcher -> Writer -> Reviewer -> Writer.
  • Example Input/Output:

    * Input: Topic "AI in Education"

    * Reviewer Output (Internal): "1. The intro is too long. 2. You missed mentioning personalized learning. 3. Tone is too informal."

    * Final Writer Output: A new blog post that is shorter, includes personalized learning, and is more formal.

    Hint: You don't need complex loops. You simply need to structure your
    tasks` list in the correct order. CrewAI passes the context of all previous tasks down the chain. If Task 3 is "Critique" and Task 4 is "Rewrite," the agent performing Task 4 will see the critique automatically.

    ---

    What You Learned

    Today you moved from being a solitary coder to a manager of AI agents.

    * Agents vs. Chains: You learned that Agents are autonomous entities with personalities, while Chains (which we learned earlier) are just rigid steps.

    * Specialization: You saw that a "Researcher" agent finds better facts than a generic "Do everything" agent.

    * Context Passing: You learned that frameworks like CrewAI handle the messy work of passing the output of one step to the input of the next.

    Why This Matters:

    In the real world, complex software isn't built by one function, and complex problems aren't solved by one person. As you build more advanced GenAI applications, you will find that breaking a problem down into specialized agents—one for database access, one for logic, one for user interface—is the key to reliability.

    Tomorrow:

    Our agents are smart, but they are trapped in a box. They only know what they were trained on. Tomorrow, we give them access to the outside world. We will learn about Web Search and External Tools.