I like writing. It’s possible you’ll notice that when you follow me or my blog. For that reason, I’m consistently producing recent content and talking about Data Science and Artificial Intelligence.
I discovered this passion a few years ago once I was just starting my path in Data Science, learning and evolving my skills. At the moment, I heard some more experienced professionals in the realm saying that a very good study technique was practicing recent skills and writing about it somewhere, teaching whatever you learned.
As well as, I had just moved to the US, and no one knew me here. So I had to begin somewhere, creating my skilled image on this competitive market. I remember I talked to my cousin, who’s also within the Tech industry, and he told me: And so I did.
And I never stopped.
Fast forward to 2025, now I actually have almost 200 published articles, a lot of them with Towards Data Science, a printed Book, and a very good audience.
Writing helped me a lot within the Data Science area.
Most recently, one in every of my interests has been the amazing Natural Language Processing and Large Language Models subjects. Learning about how these modern models work is fascinating.
That interest led me to experiment with Agentic Ai as well. So, I learned about CrewAI, a straightforward and open-source package that helps us construct AI agents in a fun and simple way, with little code. I made a decision to check it by making a crew of agents to put in writing a blog post, after which see how that goes.
On this post, we are going to learn how one can create those agents and make them work together to provide a straightforward blog post.
Let’s do this.
What’s a Crew?
A crew of AI agents is a mixture of two or more agents, each of them performing a task towards a final goal.
On this case study, we are going to create a crew that may work together to provide a small blog post a few given topic that we’ll provide.
The flow works like this:
- We decide a given topic for the agents to put in writing about.
- Once the crew is began, it is going to go to the knowledge base, read a few of my previously written articles, and take a look at to mimic my writing style. Then, it generates a set of guidelines and passes it to the following agent.
- Next, the Planner agent takes over and searches the Web searching for good content in regards to the topic. It creates a plan of content and sends it to the following agent.
- The Author agent receives the writing plan and executes it in accordance with the context and knowledge received.
- Finally, the content is passed to the last agent, the Editor, who reviews the content and returns the ultimate document because the output.
In the next section, we are going to see how this may be created.
Code
CrewAI is a fantastic Python package since it simplifies the code for us. So, let’s begin by installing the 2 needed packages.
pip install crewai crewai-tools
Next, when you want, you possibly can follow the instructions on their page and have a full project structure created for you with just a few commands on a terminal. Mainly, it is going to install some dependencies, generate the folder structure suggested for CrewAI projects, in addition to generate some .yaml and .py files.
I personally prefer to create those myself, however it is as much as you. The page is listed within the References section.
Folder Structure
So, here we go.
We’ll create these folders:
And these files:
- Within the config folder: create the files
agents.yaml
andtasks.yaml
- Within the knowledge folder, that’s where I’ll add the files with my writing style.
- Within the project root: create
crew.py
andmost important.py
.
Be certain to create the folders with the names mentioned, as CrewAI looks for agents and tasks contained in the config folder and for the knowledge base inside a knowledge folder.
Next, allow us to set our agents.
Agents
The agents are composed of:
- Name of the agent:
writer_style
- Role: LLMs are good role players, so here you possibly can tell them which role to play.
- Goal: tell the model what the goal of that agent is.
- Backstory: Describe the story behind this agent, who it’s, what it does.
writer_style:
role: >
Writing Style Analyst
goal: >
Thoroughly read the knowledge base and learn the characteristics of the crew,
equivalent to tone, style, vocabulary, mood, and grammar.
backstory: >
You might be an experienced ghost author who can mimic any writing style.
You recognize how one can discover the tone and type of the unique author and mimic
their writing style.
Your work is the idea for the Content Author to put in writing an article on this topic.
I won’t bore you with all of the agents created for this crew. I consider you bought the concept. It’s a set of prompts explaining to every agent what they will do. All of the agents instructions are stored within the agents.yaml file.
Consider it as when you were a manager hiring people to create a team. Take into consideration what kinds of execs you would wish, and what skills are needed.
We’d like 4 professionals who will work towards the ultimate goal of manufacturing written content: (1) a , (2) a , (3) a and (4) an .
If you ought to see the setup for them, just check the complete code within the GitHub repository.
Tasks
Now, back to the analogy of the manager hiring people, once we “hired” our entire crew, it’s time to separate the tasks. We all know that we would like to provide a blog post, we have now 4 agents, but what each of them will do.
Well, that shall be configured within the file tasks.yaml
.
For instance, let me show you the code for the Author agent. Once more, these are the parts needed for the prompt:
- Name of the duty:
write
- Description: The outline is like telling the skilled how you would like that task to be performed, similar to we’d tell a brand new hire how one can perform their recent job. Give precise instructions to get one of the best result possible.
- Expected output: That is how we would like to see the output. Notice that I give instructions like the scale of the blog post, the amount of paragraphs, and other information that helps my agent to present me the expected output.
- Agent to perform it: Here, we’re indicating the agent who will perform this task, using the identical name set within the
agents.yaml
file. - Output file: Now at all times applicable, but in that case, that is the argument to make use of. We asked for a markdown file as output.
write:
description: >
1. Use the content plan to craft a compelling blog post on {topic}.
2. Incorporate search engine optimization keywords naturally.
3. Sections/Subtitles are properly named in an enticing manner. Be certain
so as to add Introduction, Problem Statement, Code, Before You Go, References.
4. Add a summarizing conclusion - That is the "Before You Go" section.
5. Proofread for grammatical errors and alignment with the author's style.
6. Use analogies to make the article more engaging and sophisticated concepts easier
to grasp.
expected_output: >
A well-written blog post in markdown format, ready for publication.
The article have to be inside a 7 to 12 minutes read.
Each section should have not less than 3 paragraphs.
When writing code, you'll write a snippet of code and explain what it does.
Watch out to not add an enormous snippet at a time. Break it in reasonable chunks.
Within the examples, create a sample dataset for the code.
Within the Before You Go section, you'll write a conclusion that's engaging
and factually accurate.
agent: content_writer
output_file: blog_post.md
After the agents and tasks are defined, it’s time to create our crew flow.
Coding the Crew
Now we are going to create the file crew.py
, where we are going to translate the previously presented flow to Python code.
We start by importing the needed modules.
#Imports
import os
from crewai import Agent, Task, Process, Crew, LLM
from crewai.project import CrewBase, agent, crew, task
from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource
from crewai_tools import SerperDevTool
We’ll use the essential Agent
, Task
, Crew
, Process
and LLM
to create our flow. PDFKnowledgeSource
will help the primary agent learning my writing style, and SerperDevTool is the tool to look the web. For that one, be sure to get your API key at https://serper.dev/signup.
A best practice in software development is to maintain your API keys and configuration settings separate out of your code. We’ll use a .env
file for this, providing a secure place to store these values. Here’s the command to load them into our surroundings.
from dotenv import load_dotenv
load_dotenv()
Then, we are going to use the PDFKnowledgeSource
to indicate the Crew where to look for the author’s style. By default, that tool looks on the knowledge folder of your project, thus the importance of the name being the identical.
# Knowledge sources
pdfs = PDFKnowledgeSource(
file_paths=['article1.pdf',
'article2.pdf',
'article3.pdf'
]
)
Now we will arrange the LLM we would like to make use of for the Crew. It could be any of them. I tested a bunch of them, and people I liked probably the most were qwen-qwq-32b
and gpt-4o
. Should you select OpenAI’s, you will want an API Key as well. For Qwen-QWQ, just uncomment the code and comment out the OpenAI’s lines.. You would like an API key from Groq.
# LLMs
llm = LLM(
# model="groq/qwen-qwq-32b",
# api_key= os.environ.get("GROQ_API_KEY"),
model= "gpt-4o",
api_key= os.environ.get("OPENAI_API_KEY"),
temperature=0.4
)
Now we have now to create a Crew Base, showing where CrewAI can find the agents and tasks configuration files.
# Creating the crew: base shows where the agents and tasks are defined
@CrewBase
class BlogWriter():
"""Crew to put in writing a blog post"""
agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"
Agents Functions
And we’re able to create the code for every agent. They’re composed of a decorator @agent
to indicate that the next function is an agent. We then use the category Agent and indicate the name of the agent within the config file, the extent of verbosity, being 1 low, 2 high. You may as well use a Boolean value, equivalent to true or false.
Lastly, we specify if the agent uses any tool, and what model it is going to use.
# Configuring the agents
@agent
def writer_style(self) -> Agent:
return Agent(
config=self.agents_config['writer_style'],
verbose=1,
knowledge_sources=[pdfs]
)
@agent
def planner(self) -> Agent:
return Agent(
config=self.agents_config['planner'],
verbose=True,
tools=[SerperDevTool()],
llm=llm
)
@agent
def content_writer(self) -> Agent:
return Agent(
config=self.agents_config['content_writer'],
verbose=1
)
@agent
def editor(self) -> Agent:
return Agent(
config=self.agents_config['editor'],
verbose=1
)
Tasks Functions
The subsequent step is creating the tasks. Similarly to the agents, we are going to create a function and decorate it with @task
. We use the category Task to inherit CrewAI’s functionalities after which point to the duty for use from our tasks.yaml
file for use for every task created. If any output file is anticipated, use the output_file
argument.
# Configuring the tasks
@task
def style(self) -> Task:
return Task(
config=self.tasks_config['mystyle'],
)
@task
def plan(self) -> Task:
return Task(
config=self.tasks_config['plan'],
)
@task
def write(self) -> Task:
return Task(
config=self.tasks_config['write'],
output_file='output/blog_post.md' # That is the file that shall be contain the ultimate blog post.
)
@task
def edit(self) -> Task:
return Task(
config=self.tasks_config['edit']
)
Crew
To connect all the things together, we now create a function and decorate it with the @crew
decorator. That function will line up the agents and the tasks within the order to be performed, because the process chosen here is the best: sequential. In other words, all the things runs in sequence, from start to complete.
@crew
def crew(self) -> Crew:
"""Creates the Blog Post crew"""
return Crew(
agents= [self.writer_style(), self.planner(), self.content_writer(), self.editor(), self.illustrator()],
tasks= [self.style(), self.plan(), self.write(), self.edit(), self.illustrate()],
process=Process.sequential,
verbose=True
)
Running the Crew
Running the crew may be very easy. We create the most important.py
file and import the Crew Base BlogWriter
created. Then we just use the functions crew().kickoff(inputs)
to run it, passing a dictionary with the inputs for use to generate the blog post.
# Script to run the blog author project
# Warning control
import warnings
warnings.filterwarnings('ignore')
from crew import BlogWriter
def write_blog_post(topic: str):
# Instantiate the crew
my_writer = BlogWriter()
# Run
result = (my_writer
.crew()
.kickoff(inputs = {
'topic': topic
})
)
return result
if __name__ == "__main__":
write_blog_post("Price Optimization with Python")
There it’s. The result’s a pleasant blog post created by the LLM. See below.
That’s so nice!
Before You Go
Before you go, know that this blog post was 100% created by me. This crew I created was an experiment I desired to do to learn more about how one can create AI agents and make them work together. And, like I said, I like writing, so that is something I might have the ability to read and assess the standard.
My opinion is that this crew still didn’t do a excellent job. They were capable of complete the tasks successfully, but they gave me a really shallow post and code. I might not publish this, but not less than it could possibly be a start, perhaps.
From here, I encourage you to learn more about CrewAI. I took their free course where João de Moura, the creator of the package, shows us how one can create different sorts of crews. It is absolutely interesting.
GitHub Repository
https://github.com/gurezende/Crew_Writer
About Me
If you ought to learn more about my work, or follow my blog (it is absolutely me!), listed here are my contacts and portfolio.
References
[Quickstart CrewAI](https://docs.crewai.com/quickstart)
[CrewAI Documentation](https://docs.crewai.com/introduction)
[GROQ](https://groq.com/)
[OpenAI](https://openai.com)
[CrewAI Free Course](https://learn.crewai.com/)