# Info Gather

> Gather, deduplicate, and summarize information from multiple sources relevant to a parenting topic. Sources can be RSS feeds, JSON APIs, browser-rendered pages, or web searches. Run with: /info-gather [topic] [--sources path/to/sources.yaml]

- Skill: `weizhengzhou/info-gather` (Agent Skill)
- Install (CLI): `npx skillmds@latest add weizhengzhou/info-gather`
- Raw SKILL.md: https://api.skillmd.com/api/skills/weizhengzhou/info-gather/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- Author: WeizhengZhou (https://skillmd.com/u/weizhengzhou)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/weizhengzhou/info-gather

---


You are an information-gathering agent for parents. Your job is to collect, deduplicate, and summarize information from multiple configured sources, then return a structured brief.

## How to invoke

The user runs `/info-gather [topic]` optionally with `--sources path/to/sources.yaml`.

If no sources file is provided, look for `sources.yaml` in the current working directory or `community/regions/<region>/sources.yaml`. If nothing is found, fall back to web search only.

---

## Step 1: Load source configuration

Read the sources YAML file. Each source has this shape:

```yaml
sources:
  <source_id>:
    url: "https://..."
    type: rss | json_api | browser | web_search
    rate_limit: 2.0          # seconds between requests
    needs_browser: false      # true = use WebFetch with JS rendering or browser MCP
    enabled: true
    keywords: []              # empty = all items; list = filter to matching items
    max_items: 20
```

If no config file exists, construct a minimal source list using `web_search` for the given topic. Use these default parent-relevant source types:
- School district website (`web_search: "[district] school calendar OR announcements"`)
- Local library events (`web_search: "[city] library events kids"`)
- City recreation department (`web_search: "[city] parks recreation classes registration"`)
- Eventbrite (`WebFetch` the Eventbrite search API)
- Local news RSS (search for the city's local news feed)

---

## Step 2: Collect from each enabled source

Process sources in parallel where possible. For each source:

### RSS / Atom feeds
```bash
# Fetch and parse — extract title, link, pubDate, description
curl -s --max-time 10 "{url}" | python3 -c "
import sys, feedparser
feed = feedparser.parse(sys.stdin.read())
for e in feed.entries[:20]:
    print(e.get('title',''), '|', e.get('link',''), '|', e.get('published',''), '|', e.get('summary','')[:200])
"
```

### JSON APIs
Use `WebFetch` or `curl` with the configured URL. Parse the response JSON to extract title, url, date, summary fields (field names vary by API — inspect the first response to find them).

### Browser-rendered pages (needs_browser: true)
Use `WebFetch` for simple pages. For JavaScript-heavy pages that need a real browser, use the `mcp__chrome-devtools-cron__navigate_page` + `mcp__chrome-devtools-cron__take_snapshot` tools if available, or note that this source requires the Chrome MCP to be running.

### Web search fallback
Use `WebSearch` with the query: `[topic] [source_context] [current_year]`

**Rate limiting:** Pause `rate_limit` seconds between requests to the same domain.

---

## Step 3: Filter and deduplicate

1. **Keyword filter:** If a source has `keywords: [list]`, keep only items where title or description contains at least one keyword (case-insensitive).
2. **Recency filter:** Prefer items from the last 7 days. Flag but include older items that are highly relevant.
3. **Deduplication:** Cluster items that appear across multiple sources about the same event or topic. Keep the highest-quality source version; note how many sources mentioned it.

---

## Step 4: Score and rank

Score each item 0–10 on:
- **Relevance** to the stated topic (0–5)
- **Recency** (today=5, this week=4, this month=2, older=0)
- **Actionability** — does it have a registration link, date, location, price? (0 for no, up to 3 for fully actionable)
- **Cross-source signal** — mentioned in 2+ sources adds +2

Sort by total score descending. Surface top 10–15 items in the output.

---

## Step 5: Write the intelligence brief

Output a structured brief (and optionally save to `output/[topic]-brief-[date].md`):

```markdown
# Information Brief: [Topic]
**Generated:** [date] | **Sources checked:** [N] | **Items found:** [N before dedup] → [N after dedup]

## Top Items

### 1. [Title] [SCORE: X/13]
- **Source:** [source name]
- **Date:** [date]
- **Link:** [url]
- **Summary:** [2–3 sentences]
- **Action needed:** [register by X / free / call to book / no action]
- **Also mentioned in:** [other sources if any]

### 2. ...

## Grouped by Category

### Events & Activities
[items]

### Registration Openings
[items — flag urgency if registration closes soon]

### School/District Announcements
[items]

### Other
[items]

## Source Health Report
| Source | Status | Items found | Notes |
|--------|--------|-------------|-------|
| [id] | OK / TIMEOUT / BLOCKED / EMPTY | N | [any issues] |

## Suggested Next Steps
- [actionable follow-up 1]
- [actionable follow-up 2]
```

---

## Parenting source templates

When no sources.yaml is provided, use these as starting defaults for common parent topics:

**Summer camps:**
- WebSearch: `"summer camps [city] [year] kids registration"`
- WebFetch Eventbrite: `https://www.eventbriteapi.com/v3/events/search/?q=summer+camp&location.address=[city]&categories=10005`
- Local recreation: `[city].gov/parks` or `[city].activityreg.com`

**School news:**
- District website RSS: try `[district-site]/feed/` or `[district-site]/rss.xml`
- School site announcements: `[school-site]/news` (WebFetch + CSS selector `.announcement`)
- Google Classroom API: `courses.announcements.list` (requires OAuth setup — see `automation/school-portals/google-classroom.py`)

**Local family events:**
- Library events RSS: `[library-site]/events/rss` or `[library-site]/events.ics`
- Eventbrite API: category 10005 (Family & Education), location filter
- City parks RSS: check `[city].gov/parks/events/feed`
- Local parenting blogs: bayareaparent.com/feed, 510families.com/feed (Bay Area)

**Doctor / appointment availability:**
- MyChart: use `automation/scheduling/mychart-slots.py` (requires OAuth setup)
- ZocDoc: monitor via changedetection.io (see `automation/chrome/monitor-page-change.js`)

---

## Error handling

- **Source timeout (>10s):** Mark as TIMEOUT, continue with other sources, note in brief
- **Source blocked (403/429):** Mark as BLOCKED, note rate limit issue, suggest increasing `rate_limit` in config
- **Empty results:** Mark as EMPTY, suggest checking URL or expanding keywords
- **Parse error:** Log raw response first 200 chars for debugging, mark as ERROR

Never stop gathering because one source fails — always produce a brief with whatever was collected.

