Building a Smarter Advertising System: A Multi-Agent Architecture Guide

By

Overview

Modern advertising platforms face immense complexity: they must deliver relevant ads in real time, respect user privacy, optimize for multiple performance metrics, and adapt to dynamic market conditions. Traditional monolithic systems struggle to manage this. Inspired by Spotify Engineering’s approach, this guide walks through designing a multi-agent architecture that breaks down advertising tasks into specialized, cooperative agents. Each agent focuses on a core responsibility—such as target selection, creative generation, bid optimization, or budget pacing—while communicating through a shared context layer. The result is a modular, scalable, and smarter advertising system that can evolve with new requirements.

Building a Smarter Advertising System: A Multi-Agent Architecture Guide
Source: engineering.atspotify.com

Prerequisites

Technical Background

Tools & Environment

Step-by-Step Instructions

1. Define the Agent Roles and Responsibilities

Identify the key decision points in an advertising pipeline. Common agents include:

Define clear input/output contracts using structured data (e.g., JSON schemas).

2. Set Up Inter‑Agent Communication

Agents should not block each other. Use an event bus or message queue. Example with Redis:

import redis
r = redis.Redis(host='localhost', port=6379, db=0)
# Agent A publishes
r.publish('ad_requests', json.dumps({'user_id':'123', 'context':'...'}))
# Agent B subscribes
pubsub = r.pubsub()
pubsub.subscribe('ad_requests')
for msg in pubsub.listen():
    process(msg['data'])

For more robust patterns, adopt Apache Kafka with topic partitioning per agent type.

3. Implement a Simple Targeting Agent (Example)

This agent uses a rule‑based approach to start, later upgradeable to an RL model.

class TargetingAgent:
    def __init__(self, rules):
        self.rules = rules  # e.g., {'age': [18-35], 'interest': 'tech'}
    def select_segment(self, user_profile):
        for segment, criteria in self.rules.items():
            if all(user_profile.get(k) in v for k,v in criteria.items()):
                return segment
        return 'default'

Publish the segment decision to the creative and bid agents.

4. Build a Bid Agent with Reinforcement Learning

Use a simple Q‑learning approach. The state: remaining budget, time left, user segment, ad slot quality. The action: bid price (discrete buckets). Reward: success (impression + conversion) minus cost.

import numpy as np
class BidAgent:
    def __init__(self, actions, lr=0.1, discount=0.9):
        self.q_table = np.zeros((n_states, len(actions)))
        self.lr = lr
        self.discount = discount
    def act(self, state):
        if np.random.uniform(0,1) < epsilon:
            return np.random.choice(self.actions)
        else:
            return np.argmax(self.q_table[state])
    def learn(self, state, action, reward, next_state):
        target = reward + self.discount * np.max(self.q_table[next_state])
        self.q_table[state, action] += self.lr * (target - self.q_table[state, action])

Train the bid agent offline using logged impressions before deploying.

5. Orchestrate the Agents with a Coordinator

Create a lightweight orchestrator that manages the workflow per ad request:

  1. Receive incoming request (user context, available inventory).
  2. Invoke Targeting Agent → get segment.
  3. Invoke Creative Agent with segment → get creative.
  4. Invoke Bid Agent with segment + remaining budget → get bid price.
  5. Submit bid. On win, display creative.
  6. Log outcome and feed rewards to learning agents.

Orchestration can be a central service or use choreography via events. For example, after the targeting event, the creative agent automatically picks it up.

Building a Smarter Advertising System: A Multi-Agent Architecture Guide
Source: engineering.atspotify.com

6. Integrate a Budget Pacing Agent

A budget agent uses a proportional‑integral (PI) controller to adjust spending rate:

class BudgetAgent:
    def __init__(self, total_budget, campaign_duration):
        self.remaining_budget = total_budget
        self.time_left = campaign_duration
        self.Kp = 0.1  # proportional gain
        self.Ki = 0.05
        self.integral = 0
    def pacing_multiplier(self, spent_so_far):
        error = (self.remaining_budget / self.time_left) - spent_so_far
        self.integral += error
        return max(0, min(1, self.Kp * error + self.Ki * self.integral))

Multiply the bid agent’s output by this factor to slow down when spending too fast.

7. Set Up Monitoring and Feedback Loops

Centralize metrics using prometheus_client and visualize with Grafana. Track per‑agent performance, request latency, and overall campaign ROI. Use the performance monitor agent to compute rewards and push them back to the RL agents via shared memory or a pub/sub channel.

8. Deploy and Scale

Containerize each agent with Docker. Use Kubernetes for orchestration and auto‑scaling. For high throughput, consider deploying multiple instances of the same agent behind a load balancer.

Common Mistakes

Summary

This guide presented a multi‑agent architecture for advertising, decomposing the problem into independent yet cooperative agents: targeting, creative generation, bidding, and budget pacing. By following the step‑by‑step implementation—from defining roles, setting up communication, to training RL agents and deploying—you can build a smarter ad system that scales and adapts. The approach mirrors Spotify Engineering’s philosophy: fix structural complexity with modularity. Start small, iterate, and let each agent sharpen its skill over time.

Tags:

Related Articles

Recommended

Discover More

AI Data Center Boom Strains Denmark’s Green Grid, Triggers Connection Freeze10 Crucial Updates About docs.rs Build Target Changes Starting May 2026Shivon Zilis, Mother of Four of Elon Musk’s Children, Testifies in Court – Reveals ‘One-Off’ Romantic EncounterThe Growing Health Threat of Wildfire Smoke: What the Data RevealACEMAGIC F5A AI 470: A Refined Mini PC with Ryzen AI HX 470 and Versatile Connectivity