I wrote this to help me understand CrewAI and how to create AI agents. I thought it was pretty cool, so I'm sharing it here.
This Python script uses CrewAI and Azure OpenAI to simulate a two-person marketing team that can instantly generate a product launch plan.
It creates the following two agents:
CEO Agent: sets the high-level go-to-market vision.
Marketing Agent: builds a 7-step launch plan with messaging, channels, KPIs, and a content calendar.
This connects CrewAI’s LLM interface to Azure OpenAI via LiteLLM’s Azure adapter so all prompts hit your secure Azure deployment instead of public OpenAI endpoints.
Add a product name, run the script, and the agents will collaborate to output an execution-ready markdown document.
You can add agents with various roles and modify the goals to match your project and goals.
I added everything to a repo for convenience: https://github.com/seanbreeden/multi-agent-marketing-ai-with-azure-openai-crewai
Here is the code:
# agent.py # AI Agent Example using Azure OpenAI + CrewAI (via LiteLLM) # Author: Sean Breedenfrom crewai import Agent, Task, Crew, Process, LLM from dotenv import load_dotenv import os import sys
load_dotenv()
API_KEY = os.environ[“AZURE_OPENAI_API_KEY”] ENDPOINT = os.environ[“AZURE_OPENAI_ENDPOINT”].rstrip(”/”) API_VERSION = os.environ[“AZURE_OPENAI_API_VERSION”] DEPLOYMENT = os.environ[“AZURE_OPENAI_DEPLOYMENT_NAME”]
llm = LLM( model=f”azure/{DEPLOYMENT}”, api_key=API_KEY, api_base=ENDPOINT, api_version=API_VERSION, temperature=0.3, )
ceo = Agent( role=“Founder/CEO”, goal=“Define a sharp go-to-market direction for a new product.”, backstory=“Pragmatic startup CEO who loves concise, high-leverage plans.”, allow_delegation=True, llm=llm, )
marketer = Agent( role=“Marketing Lead”, goal=“Create a punchy, conversion-focused launch plan.”, backstory=“Lifecycle & growth marketer obsessed with clear messaging.”, allow_delegation=False, llm=llm, )
launch_task = Task( description=( “Given the product: ‘{product}’, create a 7-point launch plan with:\n” “1) One-sentence value prop\n” “2) ICP bullets x 3\n” “3) Core message\n” “4) Channels (3-5) with why\n” “5) 2-week content calendar (table)\n” “6) Simple KPI targets\n” “7) One scrappy experiment” ), expected_output=“A tight Markdown doc that a team could execute immediately.”, agent=marketer )
crew = Crew( agents=[ceo, marketer], tasks=[launch_task], process=Process.hierarchical, manager_llm=llm, )
if name == “main”: result = crew.kickoff(inputs={“product”: “Retro T-shirt website”}) print(result)
This is the README from my repo:
__ / \ | |
| $$$$$$\ $$$$$$ _ __ ____ | $$ | $$| $$ | $$ | / / \ | | $$
| $$ $$ | $$ $$$$$$| $$$$$$| $$$$$$| $$$$$$$\$$$$$$ | $$$$$$$$ | $$ / $$| $$ | $$| $$ $$| $$ | $$ | $$ __ | $$ | $$ | $$ | $$$$$$$| $$| $$| $$$$$$$$| $$ | $$ | $$|
| $$ | $$| $$ $$ $$ $$ $$ $$ | $$ | $$ $$ $$ $$ $$ $$$$$$ $$$$$$$ $$$$$$$ $$$$$$$ $$ $$ $$$$ | _| $$ $$ $$ $$$$$$ __ |
____ __ ____ ____ | $$ ______ / \ | / | \ | / \ | $$ /
| $$$$$$\ $$/ $$ $$$$$$| $$$$$$$$$$| $$$$$$| $$| $$$$$$
| $$ $$ >$$ $$ / $$| $$ | $$ | $$| $$ | $$| $$| $$ $$ | $$$$$$$$ / $$$$| $$$$$$$| $$ | $$ | $$| $$/ $$| $$| $$$$$$$$ $$ | $$ $$\$$ $$| $$ | $$ | $$| $$ $$| $$ $$
$$$$$$$ $$ $$ $$$$$$$ $$ $$ $$| $$$$$$$ $$ $$$$$$$ | $$ | $$ $$Blog post: https://www.seanbreeden.com/blog/multi-agent-marketing-ai-with-azure-openai-crewai
Using Azure OpenAI + CrewAI (via LiteLLM)
AI-Powered Multi-Agent Marketing Planner that simulates a two-person marketing team—CEO (strategy) + Marketing Lead (execution) to generate a complete, execution-ready 7-step product launch plan from a single product name. Built with CrewAI (multi-agent orchestration) and Azure OpenAI (enterprise LLM) via LiteLLM’s Azure adapter.
Features Multi-agent workflow: A CEO agent defines the go-to-market (GTM) direction, and a Marketing Lead agent translates it into a tactical plan Deterministic output shape: The plan includes a one-sentence value proposition, ICP bullets, a core message, channels, a 2-week content calendar (in a table), key performance indicators (KPIs), and one “scrappy” experiment Azure-first: The application exclusively calls your Azure OpenAI deployment, not public OpenAI endpoints Single-file runnable: The agent.py script produces a full Markdown plan to standard output Architecture
CrewAI orchestrates agents and tasks, and calls an LLM through LiteLLM.
LiteLLM (Azure adapter) normalizes API differences and constructs the correct Azure chat completions route.
Azure OpenAI hosts your GPT models; you provide the endpoint, API version, and deployment name.
[User/Product Name] → CrewAI (Agents/Task) → LiteLLM (azure/*) → Azure OpenAI → Markdown Launch Plan
Prerequisites Python 3.12 (recommended) An Azure OpenAI resource with a chat deployment (e.g., a GPT-4o family model) The following Python packages: crewai==0.157.0 openai==1.99.6 langchain-openai==0.3.29 python-dotenv Quick Start
- Clone the repository and create a virtual environment git clone <your-repo-url> ai-agent cd ai-agent python3.12 -m venv .venv source .venv/bin/activate pip install —upgrade pip pip install crewai==0.157.0 openai==1.99.6 langchain-openai==0.3.29 python-dotenv
- Configure your environment
Create a .env file in the project root with your Azure OpenAI credentials:
Azure OpenAI
AZURE_OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxx AZURE_OPENAI_ENDPOINT=https://<your-resource>.openai.azure.com AZURE_OPENAI_API_VERSION=2024-07-01 AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4.1 # EXACT deployment name in Azure
Important Notes:
AZURE_OPENAI_ENDPOINT must not include /openai AZURE_OPENAI_DEPLOYMENT_NAME is the name you gave your deployment, not the model family 3. Run the script python agent.py
You’ll be prompted to enter a product name (or the script will use a default). A complete, ready-to-execute Markdown plan will then be printed to standard output.
Example Output
Launch Plan: AI-powered retro T-shirt designer
Value Prop (1 sentence): Design & sell retro-inspired tees in minutes using AI-assisted workflows.
ICP (3 bullets):
- Indie apparel founders needing fast concept-to-storefront
- Shopify/Magento merchants testing new SKUs weekly
- Designers seeking AI co-creation for 70s/80s aesthetics
Core Message: “Turn retro ideas into shippable SKUs—today.”
Channels (why):
- Email (owned audience, highest ROI)
- Instagram Reels (visual, style-driven discovery)
- Reddit niche subs (retro/collectibles—contextual demand) … Project Structure ├─ agent.py # Main script: agents, tasks, Crew, Azure LLM config ├─ .env # Your secrets └─ README.md # This file
Configuration
In agent.py, the LLM object is configured to use Azure:
from crewai import Agent, Task, Crew, Process, LLM
…
llm = LLM( model=f”azure/{DEPLOYMENT}”, # azure/<your-deployment-name> api_key=API_KEY, # AZURE_OPENAI_API_KEY api_base=ENDPOINT, # https://<resource>.openai.azure.com (NO /openai) api_version=API_VERSION, # e.g., 2024-07-01 temperature=0.3, )
CrewAI then uses this Azure-configured LLM for both agents and the manager.
Troubleshooting 404 Resource not found
Cause: Wrong path or deployment name.
Fix:
Ensure api_base is the resource root (e.g., https://<resource>.openai.azure.com), not …/openai Verify AZURE_OPENAI_DEPLOYMENT_NAME is the exact deployment name from your Azure portal Confirm AZURE_OPENAI_API_VERSION is supported by your deployment (e.g., 2024-06-01 is generally fine for the GPT-4o family) “The api_key client option must be set…”
Cause: The script tried to use a non-Azure OpenAI endpoint instead of Azure.
Fix:
Make sure you’re constructing the LLM object with model=f”azure/{DEPLOYMENT}” Unset any stray environment variables like OPENAI_API_KEY, OPENAI_BASE_URL, or OPENAI_PROJECT Still having problems?
Enable verbose logging to see the exact requests being made:
export LITELLM_LOG=DEBUG python agent.py
You should see requests like this:
https://<resource>.openai.azure.com/openai/deployments/<DEPLOYMENT>/chat/completions?api-version=2024-07-01
If you see /openai/openai/ or a different deployment name, you’ll know where to fix api_base or DEPLOYMENT.
FAQs
Q: Can I use LangChain’s AzureChatOpenAI instead? A: Yes, but CrewAI v0.157.0 will still call LiteLLM under the hood for some pathways. Using CrewAI’s LLM with model=“azure/<deployment>” removes ambiguity and is the recommended approach.
Q: Which models work? A: Any chat deployment you’ve provisioned in Azure OpenAI (e.g., GPT-4o variants). You must use the deployment name, not the model name.
Q: How do I change temperature or token limits? A: Pass additional keyword arguments to the LLM(…) constructor, for example: temperature=0.2, max_tokens=1500.
Development Tips Pin your package versions (as listed above) to ensure constructor signatures remain stable Never commit your .env file to version control!
This is the output from the example:
Retro T-shirt Website Launch Plan
1. Value Proposition (One Sentence)
Relive iconic eras with high-quality, limited-edition retro T-shirts—crafted for true vintage lovers.
2. Ideal Customer Profile (ICP)
- Ages 22-40, urban dwellers, passionate about pop culture, nostalgia, and unique fashion statements.
- Active on social media, especially Instagram and TikTok; frequently purchase apparel online.
- Values individuality, sustainability, and authentic retro designs over mass-market fast fashion.
3. Core Message
Step into the past with exclusive retro T-shirts—designed for those who wear their memories.
4. Launch Channels & Reasons
1. Instagram
- Visual platform ideal for showcasing retro designs and building hype with reels, stories, and influencer partnerships.
2. TikTok
- Short-form video content to tap into nostalgia trends, reach younger audiences, and drive viral engagement.
3. Email Marketing
- Direct communication to build anticipation, offer early access, and nurture leads into loyal customers.
4. Reddit (Nostalgia & Fashion Subs)
- Engage with niche communities passionate about retro culture and authentic apparel.
5. Google Ads (Search & Shopping)
- Target high-intent shoppers searching for retro T-shirts and drive immediate conversions.
5. Two-Week Content Calendar
Day Instagram TikTok Email Reddit
------------------------------------------------------------------------------------------------------------
1 Teaser post Teaser video Launch announcement Intro post in r/nostalgia
2 Behind-the-scenes BTS montage Early access offer Reply to comments
3 Product carousel Try-on video Product showcase post
4 Influencer collab Influencer reaction AMA thread
5 Customer testimonial Unboxing video
6 Poll: Favorite era Style tips
7 Giveaway launch Giveaway launch Giveaway email
8 Winner announcement Winner announcement
9 Limited drop alert Limited drop video Limited drop email
10 Meme post Nostalgia meme
11 UGC repost UGC montage
12 Style guide Outfit challenge Styling tips email
13 Thank you post Thank you video Thank you email
14 Next drop teaser Next drop teaser Next drop teaser email
6. Simple KPI Targets
- Website Launch Week Traffic: 2,000 unique visitors
- Email List Growth: 500 new subscribers
- First 2 Weeks Sales: 100 T-shirts sold
- Instagram Engagement Rate: 5% average per post
- TikTok Video Views: 10,000 total views
7. Scrappy Experiment
Pop-up “Retro Memory” Contest:
Invite users to share their favorite retro memory (photo or story) on Instagram using a branded hashtag. The best entry wins a free T-shirt and gets featured on the homepage. This drives UGC, boosts organic reach, and builds an emotional connection with the brand.
Ready to execute—let’s launch!
Adding More Agents
It is possible to add more than two agents and have them work together. The more agents you have, the higher the cost, so it’s a good idea to get familiar with Azure’s Cost Analysis tool.
Here’s how to add a “developer” agent to the mix:
# add a developer developer = Agent( role=“Full-stack Developer with senior developer knowledge of React JS”, goal=“Turn the plan into a technical spec + repo structure.”, backstory=“Software developer with extensive experience developing React websites”, allow_delegation=False, llm=llm, )developer task: develop site
spec_task = Task( description=( “From the launch plan, produce a short technical spec: ” “APIs, data schema, minimal architecture, and a repo scaffold (tree).” ), expected_output=“Markdown spec with a code-block repo tree.”, agent=developer, )
ceo task: qa
qa_task = Task( description=( “Review the plan and spec and list the top 7 risks with mitigations.” ), expected_output=“Bulleted risk register with owners and due dates.”, agent=ceo, )
define the team
crew = Crew( #—v add the extra agent here agents=[ceo, marketer, developer], #—v add the extra developer and ceo task here tasks=[launch_task, spec_task, qa_task], process=Process.hierarchical, manager_llm=llm, )