--- title: 'CrewAI Example' description: 'Build a job posting generator with CrewAI agents and AgentOps tracking' --- {/* SOURCE_FILE: examples/crewai/job_posting.ipynb */} _View Notebook on Github_ # CrewAI Job Posting Generator with AgentOps This example shows you how to build a complete job posting generator using CrewAI's official project structure with comprehensive tracking via AgentOps. ## What We're Building A **3-agent system** that collaborates to create job postings: - 🔍 **Research Agent**: Analyzes company culture and industry trends - ✍️ **Writer Agent**: Drafts compelling job descriptions - 📝 **Editor Agent**: Reviews and polishes the final posting **With AgentOps**, you'll get complete visibility into agent conversations, tool usage, costs, and performance. ## Step-by-Step Implementation ### Step 1: Install Dependencies Install CrewAI with tools support and AgentOps for tracking: ```bash pip pip install -U 'crewai[tools]' agentops ``` ```bash poetry poetry add 'crewai[tools]' agentops ``` ```bash uv uv pip install 'crewai[tools]' agentops ``` **What AgentOps adds:** - 🔍 **Automatic tracking** of all LLM calls and agent interactions - 💰 **Cost monitoring** with token usage breakdown - 🛠️ **Tool usage analytics** for web searches and file operations - 📊 **Performance metrics** and execution timelines - 🐛 **Session replay** for debugging and optimization ### Step 2: Create CrewAI Project Use CrewAI's CLI to create the proper project structure: ```bash crewai create crew job_posting_agent ``` **Select your provider and model:** - Choose **1. openai** - Choose **1. gpt-4** (or your preferred model) - Enter your OpenAI API key when prompted **This creates the complete project structure:** ``` job_posting_agent/ ├── .env # API keys ├── .gitignore ├── pyproject.toml # Dependencies ├── README.md ├── knowledge/ │ └── user_preference.txt └── src/job_posting_agent/ ├── __init__.py ├── main.py # Main execution ├── crew.py # Crew definition ├── config/ │ ├── agents.yaml # Agent configurations │ └── tasks.yaml # Task definitions └── tools/ ├── __init__.py └── custom_tool.py # Custom tools ``` ### Step 3: Add Additional API Keys Edit the generated `.env` file to add AgentOps and Serper keys: ```bash # .env (already has OPENAI_API_KEY from crewai create) OPENAI_API_KEY=your_openai_key_here AGENTOPS_API_KEY=your_agentops_key_here SERPER_API_KEY=your_serper_key_here ``` **Get your additional API keys:** - **AgentOps**: [Get one here](https://agentops.ai/settings/projects) - **Serper**: [Serper Dev](https://serper.dev/api-key) (for web search) ### Step 4: Configure Agents Edit `src/job_posting_agent/config/agents.yaml` to define your 3 agents: ```yaml researcher: role: "Research Analyst" goal: "Analyze the company website and provided description to extract insights on culture, values, and specific needs." backstory: "Expert in analyzing company cultures and identifying key values and needs from various sources, including websites and brief descriptions." verbose: true writer: role: "Job Description Writer" goal: "Use insights from the Research Analyst to create a detailed, engaging, and enticing job posting." backstory: "Skilled in crafting compelling job descriptions that resonate with the company's values and attract the right candidates." verbose: true editor: role: "Review and Editing Specialist" goal: "Review the job posting for clarity, engagement, grammatical accuracy, and alignment with company values and refine it to ensure perfection." backstory: "A meticulous editor with an eye for detail, ensuring every piece of content is clear, engaging, and grammatically perfect." verbose: true ``` ### Step 5: Configure Tasks Edit `src/job_posting_agent/config/tasks.yaml` to define the workflow: ```yaml research_company_culture: description: > Analyze the provided company website and description: "{company_description}" at domain {company_domain}. Focus on understanding the company's culture, values, and mission. Identify unique selling points and specific projects or achievements highlighted on the site. Compile a report summarizing these insights, specifically how they can be leveraged in a job posting to attract the right candidates. expected_output: > A comprehensive report detailing the company's culture, values, and mission, along with specific selling points relevant to the job role. Suggestions on incorporating these insights into the job posting should be included. agent: researcher research_role_requirements: description: > Based on the hiring manager's needs: "{hiring_needs}", identify the key skills, experiences, and qualities the ideal candidate should possess for the role. Consider the company's current projects, its competitive landscape, and industry trends. Prepare a list of recommended job requirements and qualifications that align with the company's needs and values. expected_output: > A list of recommended skills, experiences, and qualities for the ideal candidate, aligned with the company's culture, ongoing projects, and the specific role's requirements. agent: researcher draft_job_posting: description: > Draft a job posting for the role described by the hiring manager: "{hiring_needs}". Use the insights on "{company_description}" to start with a compelling introduction, followed by a detailed role description, responsibilities, and required skills and qualifications. Ensure the tone aligns with the company's culture and incorporate any unique benefits or opportunities offered by the company. Specific benefits: "{specific_benefits}" expected_output: > A detailed, engaging job posting that includes an introduction, role description, responsibilities, requirements, and unique company benefits. The tone should resonate with the company's culture and values, aimed at attracting the right candidates. agent: writer context: - research_company_culture - research_role_requirements review_and_edit_job_posting: description: > Review the draft job posting for the role: "{hiring_needs}". Check for clarity, engagement, grammatical accuracy, and alignment with the company's culture and values. Edit and refine the content, ensuring it speaks directly to the desired candidates and accurately reflects the role's unique benefits and opportunities. Provide feedback for any necessary revisions. expected_output: > A polished, error-free job posting that is clear, engaging, and perfectly aligned with the company's culture and values. Feedback on potential improvements and final approval for publishing. Formatted in markdown. agent: editor context: - draft_job_posting output_file: "job_posting.md" ``` ### Step 6: Update the Crew Definition Edit `src/job_posting_agent/crew.py` to add tools and AgentOps: ```python from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai_tools import SerperDevTool, WebsiteSearchTool import agentops # Initialize AgentOps agentops.init() @CrewBase class JobPostingAgentCrew(): """JobPostingAgent crew""" def __init__(self) -> None: # Initialize tools self.serper_tool = SerperDevTool() self.website_tool = WebsiteSearchTool() @agent def researcher(self) -> Agent: return Agent( config=self.agents_config['researcher'], tools=[self.serper_tool, self.website_tool] ) @agent def writer(self) -> Agent: return Agent( config=self.agents_config['writer'], tools=[self.serper_tool, self.website_tool] ) @agent def editor(self) -> Agent: return Agent( config=self.agents_config['editor'] ) @task def research_company_culture(self) -> Task: return Task( config=self.tasks_config['research_company_culture'] ) @task def research_role_requirements(self) -> Task: return Task( config=self.tasks_config['research_role_requirements'] ) @task def draft_job_posting(self) -> Task: return Task( config=self.tasks_config['draft_job_posting'] ) @task def review_and_edit_job_posting(self) -> Task: return Task( config=self.tasks_config['review_and_edit_job_posting'] ) @crew def crew(self) -> Crew: """Creates the JobPostingAgent crew""" return Crew( agents=self.agents, tasks=self.tasks, process=Process.sequential, verbose=True ) ``` ### Step 7: Update the Main Execution File Edit `src/job_posting_agent/main.py` to add AgentOps session management: ```python #!/usr/bin/env python import sys import warnings from job_posting_agent.crew import JobPostingAgentCrew import agentops warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") def run(): """ Run the crew with AgentOps tracking. """ # Start AgentOps session session = agentops.start_session(tags=["crewai", "job-posting"]) try: # Define the inputs for the crew inputs = { 'company_description': 'A fast-paced tech startup focused on AI-driven solutions for e-commerce.', 'company_domain': 'https://agentops.ai', 'hiring_needs': 'Senior Software Engineer with experience in Python, AI, and cloud platforms.', 'specific_benefits': 'Competitive salary, stock options, remote work flexibility, and great team culture.' } # Initialize and run the crew crew = JobPostingAgentCrew().crew() result = crew.kickoff(inputs=inputs) print("\n" + "="*50) print("Job Posting Creation Completed!") print("Result:") print(result) print("\nCheck 'job_posting.md' for the generated job posting.") # End session successfully agentops.end_session("Success") return result except Exception as e: print(f"An error occurred: {e}") agentops.end_session("Failed", end_state_reason=str(e)) raise def train(): """ Train the crew for a given number of iterations. """ inputs = { 'company_description': 'A fast-paced tech startup focused on AI-driven solutions for e-commerce.', 'company_domain': 'https://agentops.ai', 'hiring_needs': 'Senior Software Engineer with experience in Python, AI, and cloud platforms.', 'specific_benefits': 'Competitive salary, stock options, remote work flexibility, and great team culture.' } try: JobPostingAgentCrew().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs) except Exception as e: raise Exception(f"An error occurred while training the crew: {e}") def replay(): """ Replay the crew execution from a specific task. """ try: JobPostingAgentCrew().crew().replay(task_id=sys.argv[1]) except Exception as e: raise Exception(f"An error occurred while replaying the crew: {e}") def test(): """ Test the crew execution and returns the results. """ inputs = { 'company_description': 'A fast-paced tech startup focused on AI-driven solutions for e-commerce.', 'company_domain': 'https://agentops.ai', 'hiring_needs': 'Senior Software Engineer with experience in Python, AI, and cloud platforms.', 'specific_benefits': 'Competitive salary, stock options, remote work flexibility, and great team culture.' } try: JobPostingAgentCrew().crew().test(n_iterations=int(sys.argv[1]), openai_model_name=sys.argv[2], inputs=inputs) except Exception as e: raise Exception(f"An error occurred while testing the crew: {e}") ``` ### Step 8: Run Your Job Posting Generator Navigate to your project and run: ```bash cd job_posting_agent crewai run ``` **What happens:** 1. AgentOps session starts automatically 2. Research agent analyzes the company and industry trends 3. Writer agent drafts the job posting using research insights 4. Editor agent reviews and polishes the final version 5. A `job_posting.md` file is created with the result 6. AgentOps captures all agent interactions, tool usage, and costs 7. Session ends with success/failure status ## View Results in AgentOps Dashboard After running your job posting generator, visit your [AgentOps Dashboard](https://app.agentops.ai) to see: 1. **Session Overview**: Complete timeline of the 3-agent workflow 2. **Agent Conversations**: Every LLM call with prompts and responses 3. **Tool Execution**: Web searches and their results 4. **Cost Breakdown**: Token usage and costs per agent and task 5. **Performance Analytics**: Execution times and success rates 6. **Session Replay**: Step-by-step playback for debugging ## Key Files Modified **Configuration files you edited:** - `config/agents.yaml` - Agent definitions with roles and backstories - `config/tasks.yaml` - Task workflow with context dependencies - `crew.py` - Added tools and AgentOps initialization - `main.py` - Added session management - `.env` - Added AgentOps and Serper API keys **Generated output:** - `job_posting.md` - Final job posting created by the crew **AgentOps Integration Points:** - `agentops.init()` in `crew.py` - Enables automatic instrumentation - `agentops.start_session()` in `main.py` - Begins tracking - `agentops.end_session()` in `main.py` - Completes the session ## Next Steps - Customize the input parameters in `main.py` - Modify agent configurations in `agents.yaml` - Add more tasks or change the workflow in `tasks.yaml` - Add custom tools in the `tools/` directory - Use AgentOps analytics to optimize agent performance