Introduction
In the fast-paced world of B2B SaaS and digital services, competitive intelligence is no longer a quarterly report—it’s a real-time necessity. Waiting for a monthly newsletter to learn that a competitor has dropped prices or launched a new feature is too late.
This article details the architecture of a Real-Time Competitor Intel Agent. Unlike simple web scrapers, this system uses LangGraph to orchestrate a multi-agent workflow that:
Monitors diverse data sources (websites, social media, press releases).
Retrieves historical context via RAG to distinguish "noise" from "signal."
Analyzes impact using LLM-based reasoning.
Suggests actionable counter-strategies.
Remembers past interactions to build a longitudinal view of competitor behavior.
Real-Time Use Case: The "Pricing War" in Cloud Security
Scenario
Company: "SecureCloud Inc." (Your Company) Competitor: "ShieldNet" (Main Rival) Event: ShieldNet updates their pricing page and posts a LinkedIn announcement about a "New Enterprise Tier" with a 20% discount for annual contracts.
The Problem
Data Silos: Pricing changes are on the website; announcements are on LinkedIn; technical specs are in press releases.
Context Gap: Is this a permanent price drop or a limited-time offer? How does it compare to our last quarter’s pricing?
Action Lag: By the time sales teams hear about it, prospects may have already signed with ShieldNet.
The Autonomous Solution
The Competitor Intel Agent detects the change, retrieves historical pricing data from its vector store, analyzes the strategic intent, and immediately suggests a counter-campaign: "Launch a 'Value-Over-Price' webinar series highlighting our superior support SLAs."
System Architecture

Prerequisites
pip install langgraph langchain langchain-openai chromadb psycopg2-binary redis pydantic beautifulsoup4 requests
Step-by-Step Implementation
Step 1: Define State Schema and Data Models
We need a state that tracks the competitor, the detected change, historical context, and the suggested response.
from typing import TypedDict, List, Optional, Dict, Any
from pydantic import BaseModel, Field
from datetime import datetime
import uuid
class CompetitorChange(BaseModel):
source_type: str # "website", "social", "press_release"
url: str
content_summary: str
detected_at: datetime
change_type: str # "pricing", "feature", "messaging", "personnel"
class HistoricalContext(BaseModel):
previous_pricing: Optional[str] = None
previous_messaging: Optional[str] = None
last_similar_change: Optional[str] = None
class StrategicAnalysis(BaseModel):
impact_level: str # "high", "medium", "low"
strategic_intent: str
threat_to_us: str
class CounterStrategy(BaseModel):
recommended_action: str
campaign_theme: str
key_messaging_points: List[str]
target_channel: str
class IntelState(TypedDict):
competitor_name: str
detected_change: Optional[CompetitorChange]
historical_context: Optional[HistoricalContext]
analysis: Optional[StrategicAnalysis]
counter_strategy: Optional[CounterStrategy]
conversation_history: List[Dict[str, str]]
error_message: Optional[str]
Step 2: Data Ingestion Agent (Monitoring)
This agent simulates monitoring. In production, this would connect to APIs (LinkedIn, Twitter) or use headless browsers (Playwright) for websites.
import requests
from bs4 import BeautifulSoup
class DataIngestionAgent:
def monitor_competitor(self, competitor_name: str, source_url: str) -> CompetitorChange:
"""Simulate fetching data from a competitor source."""
# In production: Use Playwright for JS-heavy sites or APIs for social
try:
response = requests.get(source_url, timeout=10)
soup = BeautifulSoup(response.text, 'html.parser')
# Simple extraction logic (demo only)
content = soup.get_text()[:500]
change_type = "pricing" if "price" in content.lower() else "feature"
return CompetitorChange(
source_type="website",
url=source_url,
content_summary=content,
detected_at=datetime.now(),
change_type=change_type
)
except Exception as e:
raise ValueError(f"Failed to ingest data: {str(e)}")
def run(self, state: IntelState) -> IntelState:
"""Execute monitoring."""
# Demo URL
url = f"https://{state['competitor_name'].lower()}.com/pricing"
state['detected_change'] = self.monitor_competitor(state['competitor_name'], url)
return state
Step 3: Context Retriever Agent (RAG)
This agent retrieves historical data to provide context. Is this price drop normal?
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
class ContextRetrieverAgent:
def __init__(self, vector_db_path: str = "./competitor_history_db"):
self.embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
self.vector_db = Chroma(
persist_directory=vector_db_path,
embedding_function=self.embeddings,
collection_name="competitor_history"
)
self._seed_history()
def _seed_history(self):
"""Seed with historical data."""
if self.vector_db._collection.count() == 0:
docs = [
Document(
page_content="ShieldNet lowered prices by 10% in Q3 2025 during holiday season.",
metadata={"competitor": "ShieldNet", "type": "pricing", "date": "2025-12-01"}
),
Document(
page_content="ShieldNet launched 'Enterprise Lite' tier in Jan 2026.",
metadata={"competitor": "ShieldNet", "type": "feature", "date": "2026-01-15"}
)
]
self.vector_db.add_documents(docs)
def retrieve_context(self, competitor_name: str, change_type: str) -> HistoricalContext:
"""Retrieve relevant historical context."""
query = f"{competitor_name} {change_type} history"
docs = self.vector_db.similarity_search(query, k=2)
prev_pricing = None
last_change = None
if docs:
last_change = docs[0].page_content
if change_type == "pricing":
prev_pricing = "Previous drop was 10% seasonal."
return HistoricalContext(
previous_pricing=prev_pricing,
last_similar_change=last_change
)
def run(self, state: IntelState) -> IntelState:
"""Execute retrieval."""
if state['detected_change']:
state['historical_context'] = self.retrieve_context(
state['competitor_name'],
state['detected_change'].change_type
)
return state

Join the conversation! Your thoughts help the community grow.