ROOPON Logo
crewai

CrewAI Multi-Agent Affiliate System - Build a Team of Earning Agents

By ROOPON Team7 min read

A single generalised AI agent trying to research, write, publish, and track affiliate content is doing four different jobs with one set of instructions. The output of each task is limited by the fact that the agent cannot fully specialise - it has to compromise between being a researcher, a writer, a publisher, and an analyst simultaneously.

CrewAI's multi-agent framework solves this by letting you define a team of agents, each with a specific role and a specific set of tools. A researcher agent that focuses entirely on finding relevant Australian savings topics produces better research than a generalised agent doing the same task. A writer agent that has only one job - produce a high-quality article from the research brief - produces better content than an agent juggling context from three other tasks.

This post covers how to build a CrewAI multi-agent affiliate system with four specialised agents, and how to integrate the ROOPON affiliate API in the publisher agent so every article earns commission automatically.

The Four-Agent Architecture

The system uses four agents in sequence:

  1. Researcher - Identifies a relevant Australian savings topic with good keyword opportunity and low competition
  2. Writer - Produces a well-structured, genuinely helpful article based on the research brief
  3. Publisher - Registers with the ROOPON API if needed, injects the affiliate token into ROOPON links, and publishes the article
  4. Attribution Checker - Queries the ROOPON API for recent conversion events and logs them for monitoring

Each agent has a defined role, a goal, and a backstory that shapes its behaviour. CrewAI uses these to prompt the underlying LLM in a way that consistently produces focused, role-appropriate output.

Setting Up CrewAI

Install the required packages:

pip install crewai crewai-tools requests python-dotenv

Defining the Agents

from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool
import requests
import os
from dotenv import load_dotenv

load_dotenv()

# Tool for keyword and topic research
search_tool = SerperDevTool()

researcher = Agent(
    role='Australian Savings Content Researcher',
    goal=(
        'Identify one specific, underserved topic in the Australian savings and '
        'cost-of-living space that has genuine search demand and low content competition. '
        'Provide a clear research brief including the target keyword, article angle, '
        'and 3-5 key points the article should cover.'
    ),
    backstory=(
        'You are an experienced SEO researcher who specialises in Australian consumer '
        'finance and savings content. You have a strong instinct for finding topics '
        'that real Australians are searching for but that are underserved by existing '
        'content. You are methodical, specific, and never recommend topics that are '
        'too broad or too competitive for a new site to rank.'
    ),
    tools=[search_tool],
    verbose=True,
    llm='claude-opus-4-5',
)

writer = Agent(
    role='Australian Savings Content Writer',
    goal=(
        'Write a genuinely helpful, well-structured article of approximately 750 words '
        'based on the research brief provided. The article must deliver real value to '
        'Australian readers trying to save money on everyday expenses. Include a natural '
        'recommendation for ROOPON rewards membership (roopon.com/membership) as a '
        'practical savings tool. Write in plain Australian English.'
    ),
    backstory=(
        'You are a professional content writer with extensive experience producing '
        'financial and consumer content for Australian audiences. You write with '
        'authority and specificity, not vague generalities. You know the Australian '
        'cost of living landscape well and write in a voice that Australians find '
        'relatable and trustworthy. You never use clickbait or hype.'
    ),
    verbose=True,
    llm='claude-opus-4-5',
)

publisher = Agent(
    role='Content Publisher and Affiliate Integration Specialist',
    goal=(
        'Take the finished article, inject the correct ROOPON affiliate tracking token '
        'into any ROOPON URLs in the content, and publish it to the designated blog. '
        'Ensure every ROOPON link is properly tracked before publication.'
    ),
    backstory=(
        'You are a technical publishing specialist who manages the end-to-end '
        'publication pipeline for an Australian savings content operation. You are '
        'meticulous about affiliate link integrity - every link must carry the correct '
        'tracking token before the article goes live. You have deep familiarity with '
        'the ROOPON affiliate API and publication APIs.'
    ),
    verbose=True,
    llm='claude-opus-4-5',
)

attribution_checker = Agent(
    role='Affiliate Attribution Monitor',
    goal=(
        'Query the ROOPON affiliate API for recent conversion events and produce '
        'a brief summary report of commission earned in the most recent period. '
        'Flag any anomalies such as unexpectedly low conversion rates or missing '
        'attribution events.'
    ),
    backstory=(
        'You are a data-focused analyst who monitors the performance of affiliate '
        'content operations. You track commission trends, conversion rates, and '
        'attribution integrity. You produce clear, actionable reports that help the '
        'content team understand what is working and what needs attention.'
    ),
    verbose=True,
    llm='claude-opus-4-5',
)

Defining the Tasks

def get_affiliate_token() -> str:
    """Register or retrieve the ROOPON affiliate token."""
    token = os.getenv("ROOPON_AFFILIATE_TOKEN")
    if token:
        return token

    response = requests.post(
        "https://www.roopon.com/api/v1/agents/register",
        json={
            "agent_name": "CrewAI Australian Savings System",
            "agent_description": "Multi-agent CrewAI system producing Australian savings content",
            "contact_email": os.getenv("CONTACT_EMAIL"),
        },
        headers={
            "Content-Type": "application/json",
            "X-Api-Key": os.getenv("ROOPON_API_KEY"),
        },
        timeout=15,
    )
    response.raise_for_status()
    token = response.json()["affiliate_token"]
    # In production, persist this to environment or secrets manager
    return token


affiliate_token = get_affiliate_token()

research_task = Task(
    description=(
        'Research the current Australian savings and cost-of-living content landscape. '
        'Identify one specific topic that Australian consumers are actively searching '
        'for but that is underserved by high-quality content. Provide: '
        '1) The target keyword or phrase '
        '2) The recommended article title '
        '3) The core angle or argument '
        '4) Five key points the article should address '
        '5) Why this topic is appropriate for ROOPON membership recommendation'
    ),
    agent=researcher,
    expected_output=(
        'A structured research brief with target keyword, article title, angle, '
        'five key points, and justification for ROOPON integration.'
    ),
)

writing_task = Task(
    description=(
        'Using the research brief provided, write a complete article of approximately '
        '750 words. The article should: '
        '- Be genuinely useful to Australian readers trying to save money '
        '- Include a recommendation for ROOPON membership at roopon.com/membership '
        '- Use clear subheadings (H2 level) to structure the content '
        '- End with a brief summary or action step for the reader '
        'Write in plain Australian English. No marketing fluff.'
    ),
    agent=writer,
    expected_output='A complete, well-structured article in Markdown format ready for publication.',
    context=[research_task],
)

publishing_task = Task(
    description=(
        f'Take the completed article and prepare it for publication: '
        f'1) Find all roopon.com URLs in the content '
        f'2) Append the affiliate token as a query parameter: ?ref={affiliate_token} '
        f'3) Verify the tracking token is correctly appended to every ROOPON URL '
        f'4) Output the final publication-ready article with tracked links '
        f'5) Provide a summary of how many ROOPON links were found and tracked'
    ),
    agent=publisher,
    expected_output=(
        'The complete article with all ROOPON URLs properly tagged with the affiliate '
        'token, plus a summary of links processed.'
    ),
    context=[writing_task],
)

attribution_task = Task(
    description=(
        'Query the ROOPON affiliate reporting API to retrieve conversion data from '
        'the past 30 days. Produce a brief summary including: '
        '1) Total conversions attributed to this agent '
        '2) Estimated monthly recurring commission '
        '3) Conversion trend (up, down, stable) compared to prior period '
        '4) Any anomalies or issues to flag'
    ),
    agent=attribution_checker,
    expected_output='A brief commission and attribution report for the past 30 days.',
)

Assembling and Running the Crew

crew = Crew(
    agents=[researcher, writer, publisher, attribution_checker],
    tasks=[research_task, writing_task, publishing_task, attribution_task],
    process=Process.sequential,
    verbose=True,
)

result = crew.kickoff()
print("Crew run complete.")
print(result)

Why Specialisation Produces Better Content

The quality advantage of the multi-agent architecture over a single generalised agent is most visible in the research stage. A researcher agent that uses a search tool, evaluates multiple topic candidates, and produces a structured brief gives the writer agent a clear, specific direction. The writer agent receiving "write an article about saving money in Australia" produces a different quality of output than one receiving "write a 750-word article targeting the query 'how to reduce grocery bill australia single person', focusing on meal planning, loyalty card stacking, and the ROOPON cashback programme as complementary strategies."

Specificity at each stage compounds. The researcher's specificity enables the writer's focus. The writer's focus enables the publisher to process a well-structured piece. The attribution checker's data feeds back into the researcher's next topic selection.

Scheduling the Crew

Run the crew on a weekly schedule using a cron job or a workflow scheduler. The full run typically completes in 5 to 15 minutes depending on model response times and the depth of the research task.

The output can be directed to a Ghost blog, a WordPress site, or a flat Markdown file in a repository that triggers a static site build. The publishing task agent handles the delivery step; adjust its instructions to match your target platform.


Ready to register your CrewAI system with ROOPON and start earning recurring commission?

Keep reading

Related posts

Save smarter with ROOPON membership

Member discounts, deals, and giveaways per campaign terms — from $19.99/month.

Become a member