npx skills add ...
npx skills add affaan-m/ecc --skill data-scraper-agent
Build a fully automated AI-powered data collection agent for any public source — job boards, prices, news, GitHub, sports, anything. Runs on a schedule, enriches data with a free LLM (Gemini Flash), stores results in Notion/Sheets/Supabase, and learns from user feedback. Runs 100% free on GitHub Actions. Use when the user wants to monitor, collect, or track any public data automatically.
npx skills add affaan-m/ecc --skill data-scraper-agent
Build a production-ready, AI-powered data collection agent for any public data source. Runs on a schedule, enriches results with a free LLM, stores to a database, and improves over time.
Stack: Python · Gemini Flash (free) · GitHub Actions (free) · Notion / Sheets / Supabase
Every data collection agent has three layers:
| Layer | Tool | Why |
|---|---|---|
| Scraping | requests + BeautifulSoup | No cost, covers 80% of public sites |
| JS-rendered sites | playwright (free) | When HTML fetching fails |
| AI enrichment | Gemini Flash via REST API | 500 req/day, 1M tokens/day — free |
| Storage | Notion API | Free tier, great UI for review |
| Schedule | GitHub Actions cron | Free for public repos |
| Learning | JSON feedback file in repo | Zero infra, persists in git |
Build agents to auto-fallback across Gemini models on quota exhaustion:
Never call the LLM once per item. Always batch:
Every scraped field is written by the site being scraped, and this agent runs unattended on a schedule — nobody is watching the run to catch a hostile page. Scraped values are data all the way through: through LLM enrichment, into storage, and back out to whatever reads them.
Ask the user:
Common examples to prompt:
Generate this directory structure for the user:
Template for any data source:
HTML fetch pattern:
RSS feed pattern:
Integration with your storage layer: after each run, query your DB for items with positive/negative status and call save_feedback() with the extracted patterns.
| Anti-pattern | Problem | Fix |
|---|---|---|
| One LLM call per item | Hits rate limits instantly | Batch 5 items per call |
| Hardcoded keywords in code | Not reusable | Move all config to config.yaml |
| Scraping without rate limit | IP ban | Add time.sleep(1) between requests |
| Storing secrets in code | Security risk | Always use .env + GitHub Secrets |
| No deduplication | Duplicate rows pile up | Always check URL before pushing |
Ignoring robots.txt | Legal/ethical risk | Respect crawl rules; use public APIs when available |
JS-rendered sites with requests | Empty response | Use Playwright or look for the underlying API |
maxOutputTokens too low | Truncated JSON, parse error | Use 2048+ for batch responses |
| Service | Free Limit | Typical Usage |
|---|---|---|
| Gemini Flash Lite | 30 RPM, 1500 RPD | ~56 req/day at 3-hr intervals |
| Gemini 2.0 Flash | 15 RPM, 1500 RPD | Good fallback |
| Gemini 2.5 Flash | 10 RPM, 500 RPD | Use sparingly |
| GitHub Actions | Unlimited (public repos) | ~20 min/day |
| Notion API | Unlimited | ~200 writes/day |
| Supabase | 500MB DB, 2GB transfer | Fine for most agents |
| Google Sheets API | 300 req/min | Works for small agents |
Before marking the agent complete:
config.yaml controls all user-facing settings — no hardcoded valuesprofile/context.md holds user-specific context for AI matchingmaxOutputTokens ≥ 2048.env is in .gitignore.env.example provided for onboardingsetup.py creates DB schema on first runenrich_existing.py backfills AI scores on old rowsfeedback.json after each runA complete working agent built with this exact architecture would collect from 4+ sources, batch Gemini calls, learn from Applied/Rejected decisions stored in Notion, and run 100% free on GitHub Actions. Follow Steps 1–9 above to build your own.