Building a Morning Briefing Agent with the News Search API

Sarah Choy2026年5月2日 發佈約 8 分鐘閱讀
尚無翻譯,顯示英文版本。
Building a Morning Briefing Agent with the News Search API

Every founder, PM, and analyst wants the same thing at 8am: a clean digest of what changed overnight. With a News Search API, an LLM, and an HTTP-cron platform, you can ship one in an afternoon.

一句話總結

  • Architecture: cron → News Search → URL Extract for promising stories → LLM summary → Slack/email post.
  • Tune freshness with <code>start_date</code> = today − 1; tune locale with <code>country_code</code>.
  • Chunk briefings by topic with parallel News Search queries; the LLM merges and de-duplicates.
  • Total cost is ~15 credits per topic per day, plus LLM tokens. A 5-topic briefing is &lt; $0.10/day at list price.

The shape of a useful briefing

A morning briefing agent should answer one question: \"what changed overnight that I need to know about?\" The bar is harder than it sounds. A dump of headlines fails — it's the same as RSS and gets muted within a week. The output that survives is a 5-bullet digest with links, organised by topic, in the user's voice.

That decomposes into a small pipeline:

  • Fetch recent news across N topics — News Search API.
  • Extract the body of any link the model wants to quote — URL Extract API.
  • Summarise + cluster with an LLM — your model of choice.
  • Post to Slack / email / Notion — your existing comms channel.
  • Schedule with a cron — Vercel Cron, GitHub Actions, n8n, etc.

Step 1: Pick your topics

Keep it to 3–6 topics. Briefings with 12 topics are scrolled past. Examples:

  • For a B2B SaaS founder: \"AI funding rounds\", \"OpenAI / Anthropic news\", \"competitor moves\".
  • For a financial analyst: \"FOMC and Treasury\", \"semiconductor supply chain\", \"specific tickers\".
  • For a healthcare PM: \"FDA approvals\", \"clinical-trial readouts\", \"reimbursement changes\".

Step 2: Fetch the raw signal

Run one News Search call per topic in parallel. Use start_date to cap freshness:

from datetime import date, timedelta
import asyncio, aiohttp

KEY = "pk_yourkey"
TOPICS = [
    "AI agent infrastructure funding",
    "OpenAI Anthropic Google new releases",
    "RAG and LLM tool calling research",
]

async def fetch_topic(session, q):
    yesterday = (date.today() - timedelta(days=1)).isoformat()
    async with session.post(
        "https://www.apipick.com/api/search/news",
        headers={"x-api-key": KEY},
        json={"query": q, "start_date": yesterday},
    ) as r:
        return q, await r.json()

async def fetch_all():
    async with aiohttp.ClientSession() as s:
        return await asyncio.gather(*[fetch_topic(s, q) for q in TOPICS])

Each call returns up to 5 ranked headlines (max 10 with num_results). For a 3-topic briefing that's 3 × 15 = 45 credits per run. At the $5 / 5,000-credits rate, $0.045/day. Daily cost is dominated by the LLM, not the news API.

Step 3: Selectively extract bodies

You don't need the full content of every story — just the ones the model wants to quote in detail. A simple heuristic: extract the top 2 stories per topic. With API Pick that's a single batch call:

import requests

urls = [r["url"] for topic, payload in results for r in payload["results"][:2]]

extracted = requests.post(
    "https://www.apipick.com/api/extract",
    headers={"x-api-key": KEY},
    json={"urls": urls, "extract_effort": "auto"},
).json()

At 2 credits per URL, the extract step adds ~12 credits/day for a 3-topic briefing.

Step 4: The summariser prompt

The prompt is where the briefing's voice lives. A starter:

You are an assistant that writes a morning briefing in <Sarah's> voice:
direct, no fluff, no marketing language.

Input: a JSON list of {topic, headlines, extracted_bodies}.

Output rules:
- 1 short paragraph per topic, max 60 words.
- Each paragraph ends with up to 3 inline source links.
- If a topic has fewer than 2 substantive stories overnight, omit it.
- If the entire briefing has fewer than 2 substantive topics, output the
  literal token SKIP and nothing else.
- Never editorialise. Quote facts and figures verbatim from the sources.

Output format: Slack-flavoured markdown.

The \"SKIP if low-signal\" instruction is the single highest-leverage rule. It's why your briefing won't get muted.

Step 5: Post and schedule

For a Python cron, the entire script is < 80 lines. The Slack post:

if briefing.strip() == "SKIP":
    return
requests.post(
    SLACK_WEBHOOK_URL,
    json={"text": briefing, "username": "Morning Briefing", "icon_emoji": ":sunrise:"},
)

Schedule with Vercel Cron (in vercel.json), GitHub Actions, AWS EventBridge, or n8n. Run at 7:45am in your timezone — the goal is for it to be waiting when you sit down at 8.

Doing it in n8n if you prefer no-code

  • Schedule trigger — daily, 7:45 user-tz.
  • HTTP Request nodes (one per topic), POST /api/search/news with start_date from yesterday.
  • Merge node combines the topic results.
  • HTTP Request node calls /api/extract with top URLs.
  • OpenAI / Anthropic node runs the summariser prompt.
  • If node checks the output isn't SKIP.
  • Slack node posts the briefing.

What to watch for in production

  • Topic drift. \"AI agents\" is too broad after 6 months — the API's index grows; your briefing stays specific. Tighten queries quarterly.
  • Repetition across days. Pass the prior day's URLs to the model with \"don't re-cover stories from this list\" if the same story keeps appearing.
  • Quiet weekends. The SKIP rule already handles this; just don't pin your daily check-in habit to the briefing.

Iterate, don't ship-and-forget

Read the briefing every morning for a week. Note where the model lied, miscategorised, or missed something. Update the prompt. After a week of iteration the briefing becomes a habit — and you've built a working agent with about 80 lines of code and three API calls.

常見問題

Why not just use Google News or an RSS aggregator?

Both work — and both leave you doing the boring part: clustering, deduplicating, summarising, and writing the actual briefing. An agent does that part with an LLM. RSS gives you headlines; an agent gives you a paragraph that says what matters and links to sources.

How fresh is the News Search API?

The API indexes major outlets in near-real-time. For an 8am briefing covering the prior 24 hours, set start_date to yesterday. For breaking-news bots that run hourly, set start_date to today and re-run the agent with deduplication against your last run.

What if the briefing has nothing new to say?

Build that into the prompt: 'If fewer than 3 substantive stories changed overnight, return SKIP.' Your cron job should respect SKIP and not post a low-signal briefing. Briefing-fatigue is the fastest way to get a Slack channel muted.

Can I run this without n8n?

Yes. The same flow runs as a 30-line Python script on a cron — see the example below. n8n is convenient for visual debugging and Slack integration, but it's not required.

How do I prevent the same story being summarised across topics?

Pass the model the URLs from prior queries in the same run with the instruction: 'do not re-mention any URL already covered.' Or run a single multi-topic search and let the model partition. Both work; the second is cheaper.

本文使用的 API

作者
Sarah Choy
CEO, API Pick

Sarah Choy 是 API Pick 的 CEO,專注於為 AI Agent 與 LLM 工作流打造可用於正式環境的 API。