← all tools
Hyreflow Nativesbuilt by us

Layoff Signal

Know which companies are cutting staff, while the candidates are still available.

Cost per callfree · built by us
Your own keynot needed
CategoryHyreflow Natives
Vendorfirst-party

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.

things you can ask for

  • Who has had layoffs in tech this week? Read the articles with Firecrawl
  • Has this company announced cuts in the last month?
  • Find engineers displaced by that round using GitHub and Prospeo
  • Turn this week's layoffs into a BD list and sequence it through Lemlist

works well with Layoff Signal

  • Firecrawl

    resolve the news link and read the article behind it

  • GitHub

    find the engineers inside a company that just cut staff

  • Prospeo

    contact details for displaced candidates

  • Lemlist

    the BD outreach to the survivors

Skills that use Layoff Signal

A skill is a whole pipeline your agent already knows. These ones call Layoff Signal as part of the run.

What your agent reads before it touches Layoff Signal

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 →
Show the raw playbookwritten for the agent

HOW in lib/layoffsignal.py. Index: reference/docs/layoffsignal/raw/endpoints.md.

Kind: Hyreflow Native — read this first

  • First-party capability, no external vendor. Built on free public RSS (Google News + per-site feeds).
  • No BYOK, no env key. A native has no third party to bring a key for → it runs on hyreflow infra and is metered in hyreflow credits — 0 credits under current pricing. The provider-precedence waterfall does not apply.
  • ToS-clean. Surfaces facts from primary public reporting (the same sources a human tracker reads). Does not scrape or resell anyone's curated database (e.g. layoffs.fyi's Airtable). Attribute the originating publisher. Use as a signal/trigger, not a redistributed dataset for customers to browse.

Auth & config

  • Base: https://news.google.com/rss · No authentication (native; no env var).
  • Instantiate LayoffSignal(). Discovery returns links only — fetch article bodies with the firecrawl adapter (it also resolves the Google News redirector).

Operations

  • Broad sweep: layoff_news(when="7d") → Google News RSS with LAYOFF_TERMS OR-joined. Verified live (2026-06-01) returning 50 dated articles (Meta, etc.).
  • Targeted employer: layoff_news(company="Microsoft", when="30d") — the poach trigger.
  • Custom query: google_news('"layoffs" site:techcrunch.com', when="7d") — full Google operators.
  • Clean direct links: 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.
  • Whole-stream: iter_layoff_news(when="7d", companies=[...]) — broad + per-company + site feeds.
  • Resolve: resolve_link(url) best-effort follows a redirector → publisher URL (prefer firecrawl).

Query operators (Google News RSS)

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.

⚠️ Two gotchas

  1. Redirector links. 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.
  2. Prefer per-site feeds for clean links. site_feed() gives direct publisher URLs.

Why it's here — the signal model (the product angle)

Layoffs are a live recruiting trigger: a company cutting staff = a pool of available candidates to poach

  • a BD opening with the survivors. As a native it runs on free public RSS and costs 0 credits under current pricing, so sweeping broadly is safe — spend starts downstream, on enriching the people you keep. See reference/provider-precedence.md (natives are exempt) and the recipe below.

Handoff (the recipe)

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.

Callable surface — lib/layoffsignal.py

Import: 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 recency
  • iter_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 scope
  • resolve_link(url: str) -> str — Best-effort: follow a Google News redirector link → the real publisher URL (returns the
  • site_feed(feed_url: str, *, limit: int | None = None) -> list[dict] — GET {feed_url} — fetch ANY publisher RSS/Atom feed → items with CLEAN direct links (no
  • site_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