rss-digest · v1.0.0 · 2026-08-18 · sha256 cf6c71ad20ad03d2
rss-digest v1.0.0A
Immutable. This exact content never changes and is served at /api/v1/blob/cf6c71ad20ad03d2.
---
name: rss-digest
description: Read an RSS or Atom feed and summarize the newest entries. Use when the user gives a feed URL, asks what a blog or release feed has published lately, or wants a digest of a site that offers a feed.
license: MIT
version: 1.0.0
metadata:
gaia:
security_tier: community
permissions:
- network:read
requirements:
python: ">=3.10"
tools:
- name: fetch_rss
description: Fetch an RSS or Atom feed and return its entries as structured data.
parameters:
url:
type: string
required: true
max_entries:
type: integer
required: false
default: 10
returns:
type: object
atomic: true
provenance:
source: starter-pack
---
# RSS Digest
The pack's one **tool-providing** skill. Every other starter skill is a
procedure over tools the agent already has; this one ships its own code in
`tools.py` and registers it as `rss-digest/fetch_rss`.
It exists to show the shape: a manifest entry per `@tool` function, matching the
signature exactly, plus the `network:read` permission the tool actually uses.
## Procedure
1. **Fetch the feed** with `rss-digest/fetch_rss(url, max_entries=10)`. It
returns `{"feed_title": ..., "entries": [{"title", "link", "published",
"summary"}], "count": N}` in feed order — conventionally newest first, but
the feed decides, so read the `published` values rather than assuming.
2. **If the call returns an `error` key, report it verbatim.** A malformed feed,
a 404, a blocked host, a feed with no recognizable entries, and a feed
carrying a DTD are all real answers; an invented digest is not.
3. **Digest the entries.** One line per entry: what it is and why it might
matter, with its link. Group by theme when more than five entries share one.
4. **Lead with the exception.** If one entry is materially different from the
usual traffic on this feed — a breaking change, a security release, a
shutdown notice — put it first and label it.
5. **Say the range you covered** — feed title, entry count, and the oldest date
included — so the user knows what was and was not read.
## Notes
- The tool follows GAIA's `WebClient`, so private and loopback addresses are
refused. Point it at a public feed.
- Feeds declaring a DTD are refused rather than parsed: entity expansion is a
denial-of-service vector, and no real feed needs one.
- RSS 1.0 / RDF feeds are not supported and report an error rather than an empty
digest — "nothing published" and "I could not read this" must never look alike.
- Entry summaries in feeds are frequently truncated or HTML-laden. Treat them as
a headline, not the article; say so rather than over-reading a stub.
## Fork this
Copy the directory and edit `tools.py` — that is the whole point of a tool
skill. Parse a JSON API instead of XML, or add a `since` parameter for
date-bounded fetches. Whatever you change in the signature, mirror in
`metadata.gaia.tools`: the loader compares them and refuses the skill if they
disagree, so a stale manifest can never ship.