Loading...
Loading...
Proactive Intelligence enables agents to autonomously seek out external information — web searches, API re-pulls, data freshness checks — during analysis without waiting for explicit user requests
npx skill4agent add itallstartedwithaidea/agent-skills proactive-intelligencesearch_webgraph TD
A[Agent Analysis] --> B[Trigger Evaluator]
B -->|No Trigger| C[Continue Analysis]
B -->|Trigger Fired| D[Search Strategy Selector]
D --> E{Search Type}
E -->|Web Search| F[search_web Tool]
E -->|API Re-pull| G[Data Refresh]
E -->|Benchmark Lookup| H[Industry Database]
F --> I[Result Scorer]
G --> I
H --> I
I --> J{Relevance Score}
J -->|High| K[Integrate into Analysis]
J -->|Low| L[Discard + Note]
K --> M[Update Confidence Score]
L --> M
M --> Cclass TriggerEngine:
def __init__(self):
self.triggers = [
AnomalyTrigger(),
StalenessTrigger(max_age_days=7),
KnowledgeGapTrigger(),
CompetitorMentionTrigger(),
]
def evaluate(self, context: dict) -> list[dict]:
fired = []
for trigger in self.triggers:
result = trigger.check(context)
if result["fired"]:
fired.append(result)
return sorted(fired, key=lambda t: t["priority"], reverse=True)
class AnomalyTrigger:
THRESHOLDS = {
"ctr": (0.005, 0.15),
"cpc": (0.10, 50.00),
"conversion_rate": (0.005, 0.30),
"roas": (0.5, 20.0),
}
def check(self, context: dict) -> dict:
metrics = context.get("campaign_metrics", {})
anomalies = []
for metric, (low, high) in self.THRESHOLDS.items():
value = metrics.get(metric)
if value is not None and (value < low or value > high):
anomalies.append({
"metric": metric,
"value": value,
"expected_range": (low, high),
})
return {
"fired": len(anomalies) > 0,
"trigger": "anomaly",
"priority": 0.9,
"details": anomalies,
"search_query": self.build_query(anomalies) if anomalies else None,
}
def build_query(self, anomalies: list) -> str:
metrics = [a["metric"] for a in anomalies]
return f"Google Ads {' '.join(metrics)} unusual values industry benchmark 2026"
class StalenessTrigger:
def __init__(self, max_age_days=7):
self.max_age_days = max_age_days
def check(self, context: dict) -> dict:
data_date = context.get("data_date")
if not data_date:
return {"fired": False, "trigger": "staleness"}
age_days = (datetime.utcnow() - datetime.fromisoformat(data_date)).days
return {
"fired": age_days > self.max_age_days,
"trigger": "staleness",
"priority": 0.7,
"details": {"age_days": age_days, "threshold": self.max_age_days},
"search_query": f"Google Ads recent changes updates {datetime.utcnow().strftime('%B %Y')}",
}class ProactiveSearchAgent:
def __init__(self, search_tool, model, max_searches_per_session=5):
self.search_tool = search_tool
self.model = model
self.searches_remaining = max_searches_per_session
self.search_log = []
async def search_if_triggered(self, context: dict) -> list[dict]:
if self.searches_remaining <= 0:
return []
engine = TriggerEngine()
triggers = engine.evaluate(context)
if not triggers:
return []
results = []
for trigger in triggers[:2]:
if self.searches_remaining <= 0:
break
query = trigger.get("search_query")
if not query:
continue
search_results = await self.search_tool.execute(query)
scored = self.score_results(search_results, trigger)
relevant = [r for r in scored if r["relevance"] > 0.5]
self.search_log.append({
"trigger": trigger["trigger"],
"query": query,
"results_found": len(search_results),
"relevant_results": len(relevant),
})
self.searches_remaining -= 1
results.extend(relevant)
return results
def score_results(self, results: list, trigger: dict) -> list[dict]:
scored = []
for result in results:
freshness = self.freshness_score(result.get("date"))
relevance = self.relevance_score(result.get("snippet", ""), trigger)
scored.append({
**result,
"freshness": freshness,
"relevance": relevance,
"combined_score": freshness * 0.3 + relevance * 0.7,
})
return sorted(scored, key=lambda r: r["combined_score"], reverse=True)
def freshness_score(self, date_str: str | None) -> float:
if not date_str:
return 0.5
try:
age = (datetime.utcnow() - datetime.fromisoformat(date_str)).days
return max(0, 1 - (age / 365))
except ValueError:
return 0.5
def relevance_score(self, text: str, trigger: dict) -> float:
keywords = trigger.get("search_query", "").lower().split()
text_lower = text.lower()
matches = sum(1 for kw in keywords if kw in text_lower)
return min(1.0, matches / max(len(keywords), 1))async def analyze_with_proactive_intelligence(campaign_data: dict, user_query: str):
search_agent = ProactiveSearchAgent(search_tool=WebSearchTool(), model=model)
context = {
"campaign_metrics": campaign_data.get("metrics", {}),
"data_date": campaign_data.get("date"),
"user_query": user_query,
}
proactive_results = await search_agent.search_if_triggered(context)
knowledge_block = ""
if proactive_results:
knowledge_block = "\n<proactive_research>\n"
for r in proactive_results[:5]:
knowledge_block += f"Source: {r.get('url', 'N/A')}\n{r.get('snippet', '')}\n\n"
knowledge_block += "</proactive_research>\n"
messages = [
{"role": "system", "content": f"""You are Buddy™ by googleadsagent.ai™.
{knowledge_block}
Analyze the campaign data and provide recommendations. If proactive research is included above, integrate those findings into your analysis and cite sources."""},
{"role": "user", "content": json.dumps(campaign_data) + f"\n\n{user_query}"},
]
return await model.generate(messages)| Feature | Claude Code | Cursor | Codex | Gemini CLI |
|---|---|---|---|---|
| Web search tool | ✅ MCP/custom | ✅ MCP/built-in | ⚠️ Custom | ✅ Built-in |
| Trigger evaluation | ✅ Full | ✅ Full | ✅ Full | ✅ Full |
| Result integration | ✅ Full | ✅ Full | ✅ Full | ✅ Full |
| Search budget limits | ✅ Custom | ✅ Custom | ✅ Custom | ✅ Custom |
| Citation tracking | ✅ Full | ✅ Full | ✅ Full | ✅ Full |