Skip to main content
  1. Posts/

Automating my LinkedIn posts with CrewAI

·10 mins·
LLM Agents CrewAI Llama3 Mistral GPT
Table of Contents

If you prefer to go directly into the code, there’s a GitHub repo available!!

We all know LinkedIn, the biggest social network for professionals. And we all know that, sometimes, it’s very difficult to come up with engaging and quality content to share with the community. But … what if we try to use crewAI to help us in these situations?

Well, just to let you know, I’ve already tried it, and it works reasonably well. In this article, I’ll show you the process I followed.


Wait … crewAI? ๐Ÿ˜ฐ

Don’t know what crewAI is? Don’t worry! The official documentation gives a very nice and self-contained description of crewAI’s goal:

Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks.

It may sound difficult but, believe me, one of the BIG advantages of crewAI is its extreme simplicity. Just pay attention to these four concepts: Agent, Task, Tool and Crew. If you understand those you’ll be creating your own crewAI applications right after you finish this article ๐Ÿ˜€

Agent

The agent is like a member of a team, with its specific skills and a particular goal achieve. In addition, agents have roles and exhibit defining backstories, which further improves the collaboration dynamics.

It’s very easy to create an agent in crewAI. Let’s take as example one agent I created a few weeks ago ( see this article if you are curious):

from crewai import Agent

pycharm_agent = Agent(
        role="PyCharm Python Programmer",
        goal="Conduct thorough research on why PyCharm is a BETTER IDE than VSCode for Python development",
        tools=TOOLS,
        backstory=dedent("""
        As a Python developer deeply enamored with the PyCharm IDE, you cherish its interface, debugging 
        capabilities, and the seamless integration of features like the terminal. It frustrates you when
        fellow programmers assert that VSCode surpasses PyCharm. Your mission is to persuade the Python
        IDE judge of PyCharm's superiority over VSCode.
        """),
        verbose=True,
        allow_delegation=False
    )

As you can see, I’ve provided a role (my agent is a Python Programmer with preference for PyCharm over VSCode), a goal and a backstory (more about tools later). If you are curious about the allow_delegation param, it just enables/disables the delegation of tasks between different agents.

Task

As I said before, an agent is assigned to a task. But, what is a task?

You can think of tasks as specific assignments completed by agents. These assignments provide all the necessary details such as which agent is responsible, the required tools (again, more on tools later, I swear ๐Ÿ™), etc. Let’s see an example:

from crewai import Task
from textwrap import dedent

pycharm_research_task =  Task(
            description=dedent("""
            Conduct a comprehensive research on the advantages of PyCharm over VSCode for Python development
            """),
            expected_output=dedent("""
            A detailed report on why PyCharm is a better Python IDE than VSCode and all the 
            disadvantages of using VSCode for Python development.
            """),
            agent=pycharm_agent
        )

Remember the Pycharm Agent? What you see above is the assigned task. crewAI makes this very simple, as we only need to provide the task description, the expected_output and the assigned agent. Easy!!

Tool

Some tasks are easy to solve, like telling me the capital of France ๐Ÿฅ

But, what happens if the agent needs to find the share price of NVIDIA right now? Without any connection to the outside world, the LLM won’t be able to give me the correct answer!

So … tools to the rescue! ๐Ÿฆธโ€โ™‚๏ธ

A tool is an interface that an agent can use to interact with the world. To use tools inside crewAI, we have three options:

So, as you can see, there are plenty of options! ๐Ÿ˜

Crew

Last concept: the Crew.

A crew is nothing more than putting together all the components we have seen. I took the liberty of creating the following diagram, which captures reasonably well (at least I think so ๐Ÿ˜…) the overall behaviour of a crew.

Alt text

Do you want some code example? Let’s take one from crewAI’s official documentation:

from crewai import Crew, Agent, Task, Process
from langchain_community.tools import DuckDuckGoSearchRun

researcher = Agent(
    role='Senior Research Analyst',
    goal='Discover innovative AI technologies',
    tools=[DuckDuckGoSearchRun()]
)

writer = Agent(
    role='Content Writer',
    goal='Write engaging articles on AI discoveries',
    verbose=True
)

# Create tasks for the agents
research_task = Task(
    description='Identify breakthrough AI technologies',
    agent=researcher
)

write_article_task = Task(
    description='Draft an article on the latest AI technologies',
    agent=writer
)

# Assemble the crew with a sequential process
my_crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, write_article_task],
    process=Process.sequential,
    full_output=True,
    verbose=True,
)

my_crew.kickoff()

Let’s describe the code above.

In a few words, the crew is composed of two agents: the researcher and the writer. The former must search for breakthrough AI technologies (research_task) with the help of the DuckDuckGo Search Engine (DuckDuckGoSearchRun tool) The latter is in charge of writing an article based on all the information gathered by the researcher.

To properly create crew, we need to use the Crew class, which is expecting a list of agents, tasks and the type of process (by default it’s Process.sequential but in some cases we may need other options).

And … I think we are done! At this point, you already know the building blocks of crewAI, so it’s time to get to the funny part.

Let’s automate my LinkedIn posts ๐Ÿ˜Ž

Creating LinkedIn Posts

The crew I assembled consists of these components:

  • 3 agents
  • 1 custom tool (it uses Selenium for scraping LinkedIn profiles)
  • 2 crewAI tools (for doing web research basically)
  • 3 tasks

In the following diagram, you can see how the application is going to work.

Alt text

So, first of all, we need one agent (LinkedIn Scraper Agent) in charge of scraping some of my LinkedIn profiles. Why? Because I want the generated LinkedIn post to follow my writing-style!!. The agent will interact with LinkedIn using a custom tool I’ve created, that basically wraps Selenium.

We also need another agent (Web Researcher Agent) for fetching relevant information about a given topic. In my case, I chose the recent release of Llama 3 by Meta AI, but you could choose whatever you want. This agent is able to use the SerperDevTool and the ScrapeWebsiteTool, both available as native crewAI tools.

After that, the last agent (LinkedIn Influencer Agent) will gather all the information provided by the previous agents and will generate a LinkedIn post. Ideally, it should be a LinkedIn post about Llama 3 following my writing style.

Now that you know my general approach, let’s investigate each component.

Selenium Tool: Scraping my LinkedIn profile

This is probably the trickiest part of the application, since you need to know a little bit about what is Selenium and how it works. What my custom tool does is to log into my LinkedIn account (using my email and password, stored in a .env file) and parse relevant posts from my feed. You can see the tool implementation here.

First Agent: LinkedIn Scraper Ninja ๐Ÿฅท

As I said before, the first agent will be using the Selenium tool to scrape some of my LinkedIn profiles. The implementation is pretty straightforward:

linkedin_scraper_agent = Agent(
    role="LinkedIn Post Scraper",
    goal="Your goal is to scrape a LinkedIn profile to get a list of posts from the given profile",
    tools=[scrape_linkedin_posts_tool],
    backstory=dedent(
        """
        You are an experienced programmer who excels at web scraping. 
        """
    ),
    verbose=True,
    allow_delegation=False,
    llm=openai_llm
)

You may have noticed that I’ve added a llm param that I didn’t show you before. Good catch!! ๐Ÿ˜€. This param is useful when you want to use different LLMs (by default crewAI uses gpt4). In my case, I’ve chosen gpt-3.5-turbo for this agent. You can define the LLMs just using LangChain abstractions, like this:

openai_llm = ChatOpenAI(api_key=os.environ.get("OPENAI_API_KEY"), model="gpt-3.5-turbo-0125")
mistral_llm = ChatMistralAI(api_key=os.environ.get("MISTRAL_API_KEY"), model="mistral-large-latest")

Second Agent: Web Researcher ๐Ÿง‘โ€๐Ÿ”ฌ

This is even easier to implement than the previous one, since we don’t need any custom tool. We are going to ask the agent to search for some key differences between Llama 2 and Llama 3.

web_researcher_agent = Agent(
    role="Web Researcher",
    goal="Your goal is to search for relevant content about the comparison between Llama 2 and Llama 3",
    tools=[scrape_website_tool, search_tool],
    backstory=dedent(
        """
        You are proficient at searching for specific topics in the web, selecting those that provide
        more value and information.
        """
    ),
    verbose=True,
    allow_delegation=False,
    llm=openai_llm
)

Third Agent: My own Doppelgรคnger

Alt text

This agent has to deal with the information gathered by the two previous agents and write a high quality and engaging LinkedIn post about the differences between Llama 2 and Llama 3. Additionally, the LinkedIn post must follow my writing style (I don’t want the typical ChatGPT robotic style ๐Ÿ˜‚). As you can see, I’ve chosen a Mistral model for this agent.

doppelganger_agent = Agent(
    role="LinkedIn Post Creator",
    goal="You will create a LinkedIn post comparing Llama 2 and Llama 3 following the writing style "
         "observed in the LinkedIn posts scraped by the LinkedIn Post Scraper.",
    backstory=dedent(
        """
        You are an expert in writing LinkedIn posts replicating any influencer style
        """
    ),
    verbose=True,
    allow_delegation=False,
    llm=mistral_llm
)

Defining the Tasks

I’ve defined the following tasks. Not much comment about them, since they are pretty self-explanatory …

scrape_linkedin_task = Task(
    description=dedent(
        "Scrape a LinkedIn profile to get some relevant posts"),
    expected_output=dedent("A list of LinkedIn posts obtained from a LinkedIn profile"),
    agent=linkedin_scraper_agent,
)

web_research_task = Task(
    description=dedent(
        "Get valuable and high quality web information about the comparison between Llama 2 and Llama 3"),
    expected_output=dedent("Your task is to gather high quality information about the comparison"
                           " between Llama 2 and Llama 3"),
    agent=web_researcher_agent,
)

create_linkedin_post_task = Task(
    description=dedent(
        "Create a LinkedIn post comparing Llama 2 and Llama 3 following the writing-style "
        "expressed in the scraped LinkedIn posts."
    ),
    expected_output=dedent("A high-quality and engaging LinkedIn post comparing Llama 2 and Llama 3."
                           " The LinkedIn post must follow"
                           " the same writing-style as the one expressed in the scraped LinkedIn posts"),
    agent=doppelganger_agent,
)

But there’s something missing here … The thing is that, by default, the execution of tasks is sequential (remember Process.sequential?), but I need the last task to access the context from the two previous tasks. How can we do this? Easy.

create_linkedin_post_task.context = [scrape_linkedin_task, web_research_task]

Build the Crew

Ok, we’re almost done! Let’s define the crew now.

crew = Crew(
    agents=[
        linkedin_scraper_agent,
        web_researcher_agent,
        doppelganger_agent
    ],
    tasks=[
        scrape_linkedin_task,
        web_research_task,
        create_linkedin_post_task
    ]
)

And … let’s kick it off!!!

crew.kickoff()

Conclusion

This is the final result I obtained after running the crew. It’s not the best LinkedIn post out there but, hey, it’s pretty good, and it has its own personality (which is just a copy of mine ๐Ÿ™ƒ)

๐Ÿฆ™ ๐Ÿคฏ ๐‹๐‹๐€๐Œ๐€ 2 vs ๐‹๐‹๐€๐Œ๐€ 3: ๐–๐‡๐Ž ๐‘๐„๐ˆ๐†๐๐’ ๐’๐”๐๐‘๐„๐Œ๐„? ๐Ÿคฏ ๐Ÿฆ™

This week, I've been diving deep into the world of AI models, specifically Llama 2 and Llama 3. At first glance, you might think they're just two versions of the same model, but let's dig deeper ๐Ÿ‘‡

1๏ธโƒฃ ๐๐ž๐ซ๐Ÿ๐จ๐ซ๐ฆ๐š๐ง๐œ๐ž ๐Œ๐ž๐ญ๐ซ๐ข๐œ๐ฌ: Llama 3 outperforms Llama 2 in various metrics such as MMLU, ARC, and DROP. It's like comparing a cheetah to a leopard in a race - both are fast, but one is just a bit faster!

2๏ธโƒฃ ๐“๐จ๐ค๐ž๐ง๐ข๐ณ๐ž๐ซ: Llama 3 introduces a tokenizer with a vocabulary of 128K tokens, which encodes language more effectively than Llama 2. Think of it as having a larger toolbox to build better sentences.

3๏ธโƒฃ ๐’๐ฉ๐ž๐œ๐ข๐š๐ฅ ๐“๐จ๐ค๐ž๐ง๐ฌ: Llama 3 is noted for its flexibility in managing special tokens, essential for parsing distinct textual elements. It's like having a Swiss Army knife instead of a regular one - more tools for different tasks!

4๏ธโƒฃ ๐๐จ๐ญ๐ž๐ง๐ญ๐ข๐š๐ฅ ๐ˆ๐ฆ๐ฉ๐š๐œ๐ญ: Llama 3 has been highlighted as a top-performing AI model with the potential to shake up the AI landscape. It's not just an upgrade - it's a game changer!

So, ๐ฐ๐ก๐š๐ญ ๐๐จ๐ž๐ฌ ๐ข๐ญ ๐ซ๐ž๐š๐ฅ๐ฅ๐ฒ ๐ฆ๐ž๐š๐ง ๐Ÿ๐จ๐ซ ๐ญ๐ก๐ž ๐Ÿ๐ฎ๐ญ๐ฎ๐ซ๐ž ๐จ๐Ÿ ๐€๐ˆ? Does Llama 3's superior performance signal a new era in AI capabilities? Let me know what you think in the comments ๐Ÿค” ๐Ÿ‘‡

Hope you enjoyed this article. See you around! ๐Ÿ‘‹

Related

Arduino programming with CrewAI
·7 mins
LLM Agents CrewAI Arduino Ollama Llama3 GPT
In this article, I’ll show you how to program an Arduino using crewAI, Ollama and Llama 3
CrewAI decides: VSCode or PyCharm?
·7 mins
LLM Agents CrewAI GPT
A funny weekend project where I created a crew of agents to give me a final verdict about the best Python IDE
Melody Agents: CrewAI meets Suno AI
·8 mins
LLM Agents CrewAI Groq
Let me introduce you to Melody Agents, an application that combines crewAI and Suno AI