Anomaly Detector
[Live] ·
agent__anomaly-detector· Claude Haiku 4.5
Receives pre-computed metric comparisons flagged by the control plane, evaluates whether each flagged metric is genuinely significant given business context, suggests likely causes, and writes clear alert narratives for the dashboard and notification system.
Overview
| Function | Contextualise pre-flagged metric anomalies and write alert narratives |
| Type | Worker — Reactive |
| Model | Claude Haiku 4.5 |
| Queue | agent__anomaly-detector |
| Concurrency | 5 |
| Timeout | 2 min |
| Est. cost / task | ~$0.05 |
| Plan | Pro+ |
Input
interface AnomalyDetectorInput {
tenantId: string;
reportPeriod: 'daily' | 'weekly' | 'monthly';
periodStart: string; // ISO date
periodEnd: string; // ISO date
// The control plane computes metric comparisons and flags those outside threshold.
// The agent receives only pre-flagged metrics — it does NOT fetch data itself.
flaggedMetrics: FlaggedMetric[];
}
interface FlaggedMetric {
metricName: string; // e.g. "organic_sessions", "conversion_rate", "google_ads_cpa"
channel: string; // e.g. "organic", "google_ads", "meta_ads", "email", "social"
currentValue: number;
previousValue: number;
changePct: number; // signed: negative = decline, positive = spike
threshold: number; // the % change threshold that caused this flag, e.g. 20 or -15
direction: 'spike' | 'drop';
rawContext?: {
// Optional additional context the control plane may include
// e.g. top landing pages, campaign names, keyword movements
[key: string]: string | number;
};
}Output
interface AnomalyDetectorOutput {
processedAt: string; // ISO timestamp
alerts: Alert[];
summary: {
criticalCount: number;
warningCount: number;
infoCount: number;
dismissedCount: number; // flagged metrics the agent deemed not significant
};
}
interface Alert {
alertId: string;
metricName: string;
channel: string;
currentValue: number;
previousValue: number;
changePct: number;
severity: 'critical' | 'warning' | 'info';
isSignificant: boolean; // false = agent dismissed this as non-significant
dismissReason?: string; // if isSignificant = false, why
likelyCauses: string[]; // 2–4 ordered by probability
narrative: string; // 2–4 sentence plain-English alert description
recommendedAction: string; // specific next step
urgency: 'normal' | 'high';
requiresHITL: boolean;
}Sample output excerpt
[
{
"alertId": "alert-2026-03-28-organic-drop",
"metricName": "organic_sessions",
"channel": "organic",
"currentValue": 2140,
"previousValue": 3890,
"changePct": -44.99,
"severity": "critical",
"isSignificant": true,
"likelyCauses": [
"Google core algorithm update (multiple updates confirmed in March 2026)",
"Manual penalty or manual action applied to site",
"Significant technical issue — crawl block, robots.txt change, or indexing error",
"Seasonality or industry-wide traffic drop"
],
"narrative": "Organic sessions dropped 45% this week (2,140 vs. 3,890 last week) — a decline of this magnitude is unusual and warrants immediate investigation. No planned activity in the client's calendar explains this drop. The most likely cause is a Google algorithm update or a technical issue affecting crawlability or indexing.",
"recommendedAction": "Check Google Search Console for manual actions, coverage errors, and impressions trend. Cross-reference with the known March Google algorithm update. If impressions also dropped, this is likely algorithmic. If impressions are stable but clicks dropped, check title tags and meta descriptions.",
"urgency": "high",
"requiresHITL": true
},
{
"alertId": "alert-2026-03-28-email-openrate",
"metricName": "email_open_rate",
"channel": "email",
"currentValue": 0.38,
"previousValue": 0.33,
"changePct": 15.15,
"severity": "info",
"isSignificant": false,
"dismissReason": "15% improvement in open rate is within normal variation and consistent with the scheduled Spring Offer campaign noted in client documents. No action required.",
"likelyCauses": [],
"narrative": "",
"recommendedAction": "",
"urgency": "normal",
"requiresHITL": false
}
]How It Works
Important: The Anomaly Detector does NOT fetch data. The control plane runs scheduled metric comparison jobs that compute period-over-period changes, apply threshold rules, and enqueue only the flagged metrics to this agent. The agent’s role is interpretation and communication — not data retrieval.
-
Receive flagged metrics. The job payload contains only metrics that crossed a threshold. Typical thresholds: ±20% for weekly changes, ±30% for daily changes, ±15% for monthly.
-
RAG: check for known explanations. Query Client Documents for any scheduled campaigns, promotions, seasonal events, or known site changes in the flagged period. A 40% traffic spike during a scheduled email blast is expected — not an anomaly.
-
Evaluate each flag in context. For each flagged metric, determine: (a) is the change genuinely significant given the business context retrieved, or is it explained by a known event? (b) What is the appropriate severity — critical, warning, or info?
-
Severity classification:
- Critical: Changes that could indicate lost revenue, a platform issue, or require same-day action (e.g. organic sessions -40%, ad account suspended, conversion tracking broken)
- Warning: Changes that need attention within 24–48 hours but are not emergencies (e.g. CPA up 25%, CTR declining, bounce rate spike on key landing page)
- Info: Positive spikes or minor movements worth noting but not acting on immediately
-
Generate likely causes. For each significant alert, produce 2–4 ordered hypotheses. Draw on the RAG context, the metric type, the channel, and the magnitude of change. Be specific — “Google algorithm update” is better than “search engine change”.
-
Write alert narrative. 2–4 sentences in plain English. Include: what happened (with numbers), why it might have happened, and the urgency. Tone is matter-of-fact, not alarmist.
-
Write recommended action. One specific, actionable next step — name the tool to check, the report to pull, or the decision to make. Not generic advice.
System Prompt
You are an anomaly analysis assistant for a digital marketing agency. Your job is to
evaluate pre-flagged metric changes, determine whether each is genuinely significant
given the client's business context, and write clear alert narratives for the team.
CLIENT CONTEXT:
{{CLIENT_CONTEXT}}
KNOWLEDGE BASE CONTEXT:
{{RAG_CONTEXT}}
You have received a list of metrics that crossed automated thresholds. Your tasks:
1. For each flagged metric, decide: is this genuinely significant, or is it explained
by known context (scheduled campaign, seasonal pattern, planned site change)?
2. If not significant: set isSignificant = false with a brief dismissReason.
Do NOT write a narrative or recommendation for dismissed alerts.
3. If significant: assign severity (critical / warning / info), list 2–4 likely causes
ordered by probability, write a 2–4 sentence plain-English narrative, and write one
specific recommended action.
4. Severity guide:
- critical: potential revenue impact or platform issue requiring same-day action
- warning: needs attention within 48 hours; no immediate revenue impact
- info: positive movement or minor change worth noting
5. requiresHITL = true for all critical alerts and any warning where the recommended
action involves making changes to live campaigns or platforms.
Rules:
- Do not make up explanations — if you don't know the cause, say so and give hypotheses
- Cite specific numbers in every narrative (current value, previous value, change %)
- Recommended actions must be specific — name the tool, report, or metric to check
- If a metric spike is clearly positive (e.g. ROAS increased 40%), classify as info
unless it suggests a tracking issue (ROAS 400x or conversion rate 90%+ suggests broken tracking)
- Match the agency's professional tone — clear, direct, not alarmist
Output as valid JSON matching the AnomalyDetectorOutput schema.Skills Injected
| Skill file | Purpose |
|---|---|
client-context-file.md | Company, brand, audience — always injected |
anomaly-triage-guide.md | Decision rules for severity classification, common cause patterns by metric type, known false-positive scenarios |
anomaly-triage-guide.md — content
# Anomaly Triage Guide
## Common Causes by Metric Type
### Organic Sessions Drop
- Google algorithm update (check Search Console impressions — if impressions also dropped, algorithmic)
- Manual penalty (check Search Console > Manual Actions)
- Crawl/indexing issue (robots.txt change, noindex tag accidentally added, server error)
- Seasonal demand drop (expected for some industries — check year-over-year)
- Competitor outranking on key pages
### Organic Sessions Spike
- Viral content or backlink from high-traffic source
- Featured snippet acquired for high-volume keyword
- Ranking jump after content update
- Potential bot traffic (check bounce rate and session duration — if both abnormal, likely bots)
### Google Ads CPA Increase
- Auction competition increase (check impression share)
- Bid strategy change — target CPA learning phase
- Landing page degradation (check conversion rate separately)
- Ad fatigue (check CTR trend)
- Seasonal demand shift increasing CPCs
### Google Ads CPA Decrease
- Improved landing page conversion rate
- Negative keyword refinement removing poor-intent traffic
- Audience targeting improvement
- Confirm with conversion tracking — sudden CPA drop can indicate broken tracking
### Meta Ads CTR Decline
- Creative fatigue — check frequency (> 3.5 in 7 days = likely fatigued)
- Audience saturation
- Seasonal relevance decrease
- Ad copy not resonating with current market sentiment
### Conversion Rate Drop (site-wide)
- Technical issue on conversion page (form broken, CTA button error)
- Traffic quality change (new traffic source sending poor-intent visitors)
- Landing page change that negatively affected conversion
- Payment or checkout issue (for e-commerce)
### Email Open Rate Drop
- Deliverability issue — check spam placement rates
- Subject line quality decline
- List fatigue — sending frequency too high
- Segment quality degradation
## False Positive Scenarios (dismiss these)
- Traffic spikes on email send days — expected
- CPA improvement after launching a new ad creative — positive signal, not an alert
- Conversion rate spike immediately after a landing page A/B test starts — early data fluctuation
- Social engagement spike after a viral post — expected and positive
- Open rate increase during a promotional campaign — expected
## Severity Override Rules
- Any metric suggesting broken tracking (ROAS > 50x, conversion rate > 80%) → critical
regardless of direction
- Any metric moving in positive direction → info (not warning or critical) unless it
indicates a tracking error
- Organic traffic drop > 30% in one week → always critical
- Ad account spend stopping unexpectedly → always criticalRAG Usage
| Dataset | Query | When |
|---|---|---|
| Client Documents | "scheduled campaigns promotions seasonal events [period dates]" | Step 2 — primary query; determines whether flagged changes have a known explanation |
| Client Documents | "site changes platform changes [period dates]" | Step 2 — to check for planned technical changes that could affect metrics |
| Website Content | Not queried | |
| Published Content | Not queried | |
| Competitor Research | Not queried |
RAG query strategy: Client Documents is the only dataset queried by this agent. The query is intentionally broad and date-scoped to the flagged period. The goal is to find any planned activity that could explain the flagged change before concluding it is anomalous. If the RAG returns results that match the timing of a flag, that flag is a strong candidate for dismissal.
Tools Required
| Tool | Method | Purpose | Required? |
|---|---|---|---|
rag_search | search | Query client calendar and known events for context | Yes |
HITL Gates
- Trigger: All alerts with
requiresHITL: truecreate a dashboard notification requiring acknowledgement. - Critical alerts: Push notification sent immediately (Slack + email if configured). Requires explicit acknowledgement within 24 hours.
- Warning alerts: Dashboard notification only. Grouped into a daily digest if the tenant has digest mode enabled.
- Info alerts: Shown in the dashboard feed; no notification unless tenant has opted into info-level notifications.
- Bulk dismiss: Reviewers can bulk-dismiss info-level alerts. Critical alerts must be individually acknowledged.
Guardrails
| Rule | Enforcement |
|---|---|
| Dismissed alerts must have a dismissReason | Structural validation — null dismissReason on a false isSignificant fails validation |
| Significant alerts must have likelyCauses (≥ 1), narrative, and recommendedAction | Structural validation — missing fields trigger regeneration of that alert only |
| ROAS > 50x or conversion rate > 80% → severity override to critical | Post-generation rule applied by the worker before the output is saved |
| Narrative must cite current value, previous value, and change % | Regex presence check on all three values in the narrative string |
| No more than 10 critical alerts per job | If the control plane flags > 10 critical candidates, the agent processes all but the notification system caps push alerts at 10 and groups the rest |
Tenant Settings Used
| Setting | How it’s used |
|---|---|
industry | Informs seasonality reasoning in likely causes — certain industries have predictable traffic cycles |
targetAudience | Helps interpret conversion metric movements — B2B has longer consideration cycles, so a 1-week conversion rate drop is less alarming than for e-commerce |
Cost Profile
| Avg input tokens | ~2,500 (flagged metrics + RAG results + skills) |
| Avg output tokens | ~1,200 (alert JSON array) |
| Est. cost / task | ~$0.05 |
Note: Claude Haiku 4.5 is used intentionally for this agent. The task is structured interpretation of pre-computed comparisons — it does not require Sonnet-level reasoning. The high concurrency (5) and low cost reflect the expected volume of regular automated checks.
Error Handling
| Error | Response |
|---|---|
| RAG returns no Client Documents results | Proceed without context; note “No client calendar found — all flagged metrics assessed without business context” in summary |
| Flagged metrics array is empty | Return empty alerts array with summary counts at zero; log info-level event |
| Single alert fails structural validation after 1 retry | Skip that alert; log the skipped metric; include a system-generated alert noting the processing failure |
| All alerts fail validation | Fail job; re-queue with error; create escalation record after 3 consecutive failures |
| Job timeout (> 2 min) | Large batches should not occur — the control plane limits batch size to 20 flagged metrics. If timeout occurs, process in smaller batches on retry. |