Know which companies are cutting staff, while the candidates are still available.
A layoff is two openings at once: people to place, and a company to call. LayoffSignal watches public reporting for job cuts and hands you the company, the headcount and the source. We built it, so there is no vendor account to set up and no key to bring.
LayoffSignal starts a pipeline that would otherwise never begin. It names the company; sourcing and enrichment find the people.
A skill is a whole pipeline your agent already knows. These ones call Layoff Signal as part of the run.
Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.
Read the Layoff Signal docs →HOW in lib/layoffsignal.py. Index: reference/docs/layoffsignal/raw/endpoints.md.
https://news.google.com/rss · No authentication (native; no env var).LayoffSignal(). Discovery returns links only — fetch article bodies with the
firecrawl adapter (it also resolves the Google News redirector).layoff_news(when="7d") → Google News RSS with LAYOFF_TERMS OR-joined. Verified live
(2026-06-01) returning 50 dated articles (Meta, etc.).layoff_news(company="Microsoft", when="30d") — the poach trigger.google_news('"layoffs" site:techcrunch.com', when="7d") — full Google operators.site_feed(url) / site_feeds() over curated outlets (DEFAULT_SITES) — no
redirector to resolve. Bloomberg/Reuters are paywalled → rely on google_news to surface those.iter_layoff_news(when="7d", companies=[...]) — broad + per-company + site feeds.resolve_link(url) best-effort follows a redirector → publisher URL (prefer firecrawl).q accepts "exact phrase", OR, site:, intitle:, -exclude, plus News-native recency via the
when= arg (7d/24h/1h). layoff_news builds "layoffs" OR "job cuts" OR "cutting jobs" OR … when:7d.
google_news/layoff_news links are news.google.com/rss/articles/CBMi…
(encoded redirect), not the publisher URL. Resolve via resolve_link() (best-effort) or — more
reliably — hand the link to firecrawl, which follows it and returns the article body.site_feed() gives direct publisher URLs.Layoffs are a live recruiting trigger: a company cutting staff = a pool of available candidates to poach
reference/provider-precedence.md (natives are exempt) and the recipe below.recipes/layoff-signal-to-poach.md: sweep feeds → resolve+fetch article bodies (firecrawl) → Claude
extracts {company, headcount, %, date, location, source} (free, Model A) → dedupe → resolve company →
source affected roles (github for eng, apollo/aiark otherwise) → enrich (waterfall) → outreach/ATS.
lib/layoffsignal.pyImport: from lib.layoffsignal import LayoffSignal → instantiate LayoffSignal() (reads key from env). Base: https://news.google.com/rss. Generic passthrough: request(method, path, *, params, json).
google_news(query: str, *, when: str | None = None, hl: str = 'en-US', gl: str = 'US', ceid: str = 'US:en', limit: int | None = None) -> list[dict] — GET /search?q={query} — Google News RSS search (free, no key). when adds a recencyiter_layoff_news(*, when: str = '7d', companies: list[str] | None = None, include_sites: bool = True, **kw) -> Iterator[dict] — Walk a full sweep as one stream: the broad layoff query + one query per company (if given)layoff_news(*, when: str = '7d', company: str | None = None, terms: list[str] | None = None, **kw) -> list[dict] — Convenience: google_news() pre-built with LAYOFF_TERMS (OR-joined). Pass company to scoperesolve_link(url: str) -> str — Best-effort: follow a Google News redirector link → the real publisher URL (returns thesite_feed(feed_url: str, *, limit: int | None = None) -> list[dict] — GET {feed_url} — fetch ANY publisher RSS/Atom feed → items with CLEAN direct links (nosite_feeds(feeds: dict | None = None, *, limit_each: int | None = None) -> dict[str, list[dict]] — Fetch several publisher feeds → {feed_name: [items]}. Defaults to DEFAULT_SITES. Per-feed