🔥 0
0
Lesson 3 of 10 25 min +200 XP

Creating Tasks and Custom Tools

Agents are only as useful as the tasks they perform and the tools they can use. In this lesson, you'll learn to craft effective tasks and build custom tools that connect your agents to real e-commerce systems.

Understanding Tasks

A Task is a specific piece of work assigned to an agent. Think of it as a detailed work order.

📝
Description

What needs to be done - the detailed instructions

🎯
Expected Output

What the result should look like

🤖
Agent

Who is responsible for this task

🔧
Tools

What capabilities the agent can use

Anatomy of a Great Task

from crewai import Task

# A well-defined product description task
product_description_task = Task(
    description="""
    Write a product description for the following item:

    Product: {product_name}
    Category: {category}
    Price: ${price}
    Features: {features}
    Target Audience: {target_audience}

    Requirements:
    1. Start with an attention-grabbing headline
    2. Write 3-5 benefit-focused bullet points
    3. Include a compelling main description (100-150 words)
    4. Add relevant keywords naturally for SEO
    5. End with a call-to-action

    Tone: Professional yet approachable
    Brand Voice: Modern, innovative, customer-centric
    """,

    expected_output="""
    A complete product listing with:
    - Headline (max 80 characters)
    - 5 bullet points highlighting benefits
    - Main description (100-150 words)
    - SEO keywords naturally integrated
    - Call-to-action statement
    """,

    agent=copywriter_agent,
    tools=[seo_analyzer_tool]
)

Why This Task Definition Works

Detailed Description

Includes all context (product info, requirements, tone) the agent needs. Uses template variables {product_name} for dynamic input.

Clear Expected Output

Specifies exact deliverables with formats and constraints. The agent knows exactly what "done" looks like.

Task Context and Dependencies

Tasks can depend on each other. The output of one task becomes context for the next:

# Task 1: Research the product's market
research_task = Task(
    description="Research the target market and competitor products for {product_name}",
    expected_output="Market analysis with target demographics and competitive positioning",
    agent=researcher_agent
)

# Task 2: Write description using research (context from Task 1)
writing_task = Task(
    description="Write a product description using the market research provided",
    expected_output="Complete product listing optimized for the target audience",
    agent=copywriter_agent,
    context=[research_task]  # This task receives output from research_task
)

# Task 3: Review using both previous outputs
review_task = Task(
    description="Review the product listing for accuracy and brand consistency",
    expected_output="Final approved listing or revision suggestions",
    agent=reviewer_agent,
    context=[research_task, writing_task]  # Can access both previous outputs
)

Built-in Tools from crewai-tools

CrewAI provides many ready-to-use tools:

from crewai_tools import (
    SerperDevTool,      # Google search
    WebsiteSearchTool,  # Search within a website
    ScrapeWebsiteTool,  # Extract content from URLs
    FileReadTool,       # Read local files
    DirectoryReadTool,  # List directory contents
    PDFSearchTool,      # Search PDF documents
)

# Example: Give an agent web search capability
from crewai import Agent
from crewai_tools import SerperDevTool

search_tool = SerperDevTool()

market_researcher = Agent(
    role="Market Research Analyst",
    goal="Find competitor pricing and product information",
    backstory="Expert at finding and analyzing market data",
    tools=[search_tool]  # Agent can now search the web
)

Building Custom E-commerce Tools

Real e-commerce crews need tools that connect to your specific systems. Here's how to build them:

1. Product Database Tool

from crewai.tools import tool
from typing import Optional
import json

@tool("Product Database Lookup")
def get_product_info(product_id: str) -> str:
    """
    Retrieves product information from the e-commerce database.

    Args:
        product_id: The unique identifier for the product (e.g., "SKU-12345")

    Returns:
        JSON string with product details including name, price, description,
        inventory count, and category.
    """
    # In production, this would query your actual database
    # Example using a mock database
    products_db = {
        "SKU-12345": {
            "name": "Wireless Noise-Canceling Headphones",
            "price": 149.99,
            "category": "Electronics",
            "inventory": 234,
            "features": ["40-hour battery", "Bluetooth 5.3", "ANC"],
            "rating": 4.5,
            "reviews_count": 1247
        },
        "SKU-67890": {
            "name": "Organic Cotton T-Shirt",
            "price": 34.99,
            "category": "Apparel",
            "inventory": 567,
            "features": ["100% organic", "Pre-shrunk", "Tagless"],
            "rating": 4.8,
            "reviews_count": 892
        }
    }

    product = products_db.get(product_id)
    if product:
        return json.dumps(product, indent=2)
    return f"Product {product_id} not found in database"

2. Competitor Price Checker Tool

@tool("Competitor Price Checker")
def check_competitor_prices(product_name: str, category: str) -> str:
    """
    Checks competitor prices for similar products.

    Args:
        product_name: Name of the product to search for
        category: Product category for more accurate results

    Returns:
        JSON string with competitor pricing data including store name,
        price, and product URL.
    """
    # In production, this would scrape or use APIs
    # Mock data for demonstration
    competitor_data = {
        "competitors": [
            {"store": "Amazon", "price": 159.99, "shipping": "Free"},
            {"store": "Best Buy", "price": 149.99, "shipping": "$5.99"},
            {"store": "Walmart", "price": 139.99, "shipping": "Free"},
        ],
        "average_price": 149.99,
        "lowest_price": 139.99,
        "price_range": "$139.99 - $159.99"
    }

    return json.dumps(competitor_data, indent=2)

3. Customer Reviews Fetcher Tool

@tool("Customer Reviews Fetcher")
def get_customer_reviews(
    product_id: str,
    limit: int = 10,
    rating_filter: Optional[int] = None
) -> str:
    """
    Fetches customer reviews for a product.

    Args:
        product_id: The product's unique identifier
        limit: Maximum number of reviews to return (default 10)
        rating_filter: Only return reviews with this star rating (1-5)

    Returns:
        JSON string with review data including rating, title, text,
        date, and verified purchase status.
    """
    # Mock review data
    reviews = [
        {
            "rating": 5,
            "title": "Best headphones I've ever owned!",
            "text": "The noise cancellation is incredible. I use them daily for work calls.",
            "date": "2025-03-15",
            "verified": True
        },
        {
            "rating": 4,
            "title": "Great sound, battery could be better",
            "text": "Sound quality is excellent but battery only lasts 30 hours for me.",
            "date": "2025-03-10",
            "verified": True
        },
        {
            "rating": 2,
            "title": "Uncomfortable after 2 hours",
            "text": "Sound is good but ear cups press too hard. Had to return them.",
            "date": "2025-03-05",
            "verified": True
        }
    ]

    if rating_filter:
        reviews = [r for r in reviews if r["rating"] == rating_filter]

    return json.dumps(reviews[:limit], indent=2)

4. Inventory Status Tool

@tool("Inventory Status Checker")
def check_inventory_status(product_id: str) -> str:
    """
    Checks current inventory levels and restock status.

    Args:
        product_id: The product's unique identifier

    Returns:
        JSON string with inventory data including current stock,
        reorder point, days until stockout, and restock date.
    """
    inventory_data = {
        "product_id": product_id,
        "current_stock": 234,
        "reorder_point": 100,
        "daily_sales_avg": 12,
        "days_until_stockout": 19,
        "restock_date": "2025-04-01",
        "restock_quantity": 500,
        "status": "HEALTHY"  # HEALTHY, WARNING, CRITICAL, OUT_OF_STOCK
    }

    return json.dumps(inventory_data, indent=2)

5. SEO Keyword Analyzer Tool

@tool("SEO Keyword Analyzer")
def analyze_seo_keywords(product_category: str, target_market: str) -> str:
    """
    Analyzes SEO keywords for a product category.

    Args:
        product_category: The product category (e.g., "wireless headphones")
        target_market: Target customer segment (e.g., "remote workers")

    Returns:
        JSON string with keyword data including primary keywords,
        long-tail keywords, search volume, and competition level.
    """
    seo_data = {
        "primary_keywords": [
            {"keyword": "wireless headphones", "volume": 450000, "competition": "high"},
            {"keyword": "noise canceling headphones", "volume": 320000, "competition": "high"},
            {"keyword": "bluetooth headphones", "volume": 280000, "competition": "medium"}
        ],
        "long_tail_keywords": [
            {"keyword": "best wireless headphones for work from home", "volume": 12000, "competition": "low"},
            {"keyword": "noise canceling headphones for office", "volume": 8500, "competition": "low"},
            {"keyword": "comfortable headphones for all day wear", "volume": 6200, "competition": "low"}
        ],
        "recommended_keywords": [
            "work from home headphones",
            "office noise canceling",
            "all-day comfort headphones",
            "video call headphones"
        ]
    }

    return json.dumps(seo_data, indent=2)

Putting Tools and Tasks Together

Here's a complete example combining custom tools with tasks:

from crewai import Agent, Task, Crew, Process
from crewai.tools import tool
import json

# Define custom tools
@tool("Product Database")
def get_product(product_id: str) -> str:
    """Get product details from database."""
    return json.dumps({
        "name": "Premium Yoga Mat",
        "price": 79.99,
        "features": ["Non-slip surface", "6mm thick", "Eco-friendly"],
        "category": "Fitness"
    })

@tool("SEO Analyzer")
def analyze_keywords(category: str) -> str:
    """Get SEO keywords for product category."""
    return json.dumps({
        "keywords": ["yoga mat", "exercise mat", "non-slip yoga mat"],
        "search_volume": "High"
    })

# Create specialized agents with tools
researcher = Agent(
    role="Product Research Analyst",
    goal="Gather comprehensive product and market data",
    backstory="Expert at analyzing products and finding opportunities",
    tools=[get_product],
    verbose=True
)

copywriter = Agent(
    role="SEO Copywriter",
    goal="Write compelling, SEO-optimized product descriptions",
    backstory="Expert at converting features into benefits",
    tools=[analyze_keywords],
    verbose=True
)

# Define tasks with clear dependencies
research_task = Task(
    description="""
    Research product SKU-YOGA-001:
    1. Get all product details from the database
    2. Identify key selling points
    3. Note any inventory or pricing concerns
    """,
    expected_output="Comprehensive product brief with all details",
    agent=researcher
)

copywriting_task = Task(
    description="""
    Using the product research, write a compelling product listing:
    1. Analyze relevant SEO keywords for the category
    2. Write an attention-grabbing title
    3. Create 5 benefit-focused bullet points
    4. Write a 150-word description
    """,
    expected_output="Complete product listing with title, bullets, and description",
    agent=copywriter,
    context=[research_task]  # Uses output from research_task
)

# Create and run the crew
product_listing_crew = Crew(
    agents=[researcher, copywriter],
    tasks=[research_task, copywriting_task],
    process=Process.sequential,
    verbose=True
)

result = product_listing_crew.kickoff()
print(result)

Tool Best Practices

Practice Why It Matters
Descriptive docstrings Agents use docstrings to understand when and how to use tools
Type hints on parameters CrewAI generates schemas from types - agents know what to pass
Return strings (usually JSON) LLMs work with text - structured JSON is easy to parse
Handle errors gracefully Return helpful error messages instead of crashing
Keep tools focused One tool, one purpose - easier for agents to select correctly

YAML Task Configuration

For cleaner organization, define tasks in YAML:

# config/tasks.yaml

product_research:
  description: |
    Research product {product_id}:
    1. Fetch all product details from the database
    2. Analyze current inventory status
    3. Check competitor pricing
    4. Summarize key selling points
  expected_output: |
    A comprehensive product brief containing:
    - Product specifications and features
    - Inventory status and recommendations
    - Competitive pricing analysis
    - Top 5 selling points for marketing

copywriting_task:
  description: |
    Using the product research, create a compelling product listing:
    1. Analyze SEO keywords for the category
    2. Write headline (max 80 chars)
    3. Create 5 benefit-focused bullet points
    4. Write main description (150 words)
  expected_output: |
    Complete product listing ready for publication:
    - SEO-optimized headline
    - 5 bullet points
    - Main description
    - Recommended tags

Key Takeaways

  • Tasks need clear descriptions and expected outputs - Tell agents exactly what you want
  • Use context for task dependencies - Chain tasks so outputs flow to inputs
  • Custom tools connect to your systems - Databases, APIs, and internal services
  • @tool decorator makes functions discoverable - Type hints and docstrings are essential
  • Return structured JSON from tools - Easy for agents to parse and use

Next up: Product Description Generation Crew - Build a complete crew that auto-generates product listings.

🧠 Quick Quiz

Test your understanding of this lesson.

1

What are the two required fields when defining a Task in CrewAI?

2

Why would you create a custom tool instead of using built-in tools?

3

What does the @tool decorator do in CrewAI?

Defining Agent Roles and Goals