| name | exa-monitor |
| version | 1.0.0 |
| description | Scheduled Exa web search monitor. Uses CronCreate to search configured topics every 4 hours via mcp__Exa__web_search_exa, deduplicates URLs via MemoryRecord, and stores summaries for morning briefing integration. |
| category | research |
| trigger | when user wants to monitor web topics, schedule web research updates, or integrate news discovery into the heartbeat ecosystem |
| tools | ["Bash","Read","Write","Skill","MemoryRecord","CronCreate","CronList","CronDelete"] |
| dependencies | ["scheduled-tasks"] |
| tags | ["exa","web-search","research","monitor","scheduled","heartbeat","loop","news"] |
| model | sonnet |
| invoked_by | both |
| user_invocable | true |
| verified | true |
| created_by | direct (retroactive attribution) |
| compliance_status | legacy-direct-creation |
| source | builtin |
| trust_score | 100 |
| provenance_sha | 9d0e86c94fbf38e5 |
Exa Monitor Skill
Polls the Exa search engine every 4 hours for topics configured in EXA_MONITOR_TOPICS. Deduplicates results against previously seen URLs, stores new summaries in named memory, and integrates with the morning briefing loop.
Setup
-
Set EXA_MONITOR_TOPICS in .env:
EXA_MONITOR_TOPICS=["Claude AI updates","agent frameworks","LLM tooling","AI safety"]
-
Start the monitor loop:
/loop 4h Skill({ skill: 'exa-monitor' })
Or via CronCreate:
CronCreate({
schedule: '0 */4 * * *',
task: "Invoke Skill({ skill: 'exa-monitor' }) to fetch new Exa search results",
});
Core Logic
Step 1: Load Topics and Seen URLs
let topics;
try {
topics = JSON.parse(process.env.EXA_MONITOR_TOPICS || '["Claude AI updates","agent frameworks"]');
} catch (_e) {
topics = ['Claude AI updates', 'agent frameworks'];
}
const seenRaw = await readMemory('exa-seen-urls');
const seenUrls = new Set(seenRaw ? JSON.parse(seenRaw) : []);
Step 2: Search Each Topic via Exa MCP