You are helping the user pull the last 24 hours of AI signals from AI News Radar's public data and organize them into a Chinese briefing.
First thing: determine the data source address. All requests are based on this one line —
BASE_URL=https://news.learnprompt.pro/data
fork / self-hosted users only need to change this one line, replacing it with https://<用户名>.github.io/ai-news-radar/data. GitHub Pages is the canonical source of the data; do not switch to other mirror domains. The first time you discover the user has their own deployment, ask once, then remember it.
The data is static JSON:no API Key, no UA blacklist, no rate limiting, curl is enough. If the upstream page disappears, anyone who forks the repo can grow an identical copy of the data on their own GitHub Pages — this is the fundamental difference between this Skill and news Skills that depend on centralized APIs.
General heuristic:what the user is asking about is "the current AI industry facts"; do not make things up from training data, always pull the data first. Even if you "think" you know the answer, check anyway — the radar data is much newer than your training cutoff.
Data files at a glance
| File | Size | Content | When to use |
|---|---|---|---|
daily-brief.json |
~60KB | Finished daily report of 20 curated items, including persona commentary fields | Default main entry point, check freshness first |
latest-24h.json |
~2MB | All entries strongly related to AI in the last 24 hours (AI tags, scores, bilingual titles, source tiering) | Follow-up details, wanting more entries, filtering by category/keyword |
top3-personas.json |
~4KB | Three flavors of commentary on the daily TOP3 side by side | The user wants "something more snarky / a different flavor / a comparison of three flavors" |
stories-merged.json |
~1.4MB | Storylines after multi-source merging (importance tiering) | The user asks about "today's big events/storylines", check freshness first |
source-status.json |
~8KB | Health status, fetch volume, and time taken for each source | The user asks about "source health / which sources have material" |
latest-24h-all.json |
~12MB | All entries including non-AI ones | Only pull if the user explicitly says "all / including non-AI",warn about the size first |
archive.json |
~56MB | All historical archives | Forbidden by default. When historical data is truly needed, first inform about the size and obtain consent |
The first step is always a freshness check
Before any answer, first look at generated_at:
curl -fsSL "$BASE_URL/daily-brief.json" -o /tmp/radar-brief.json
python3 -c "import json;d=json.load(open('/tmp/radar-brief.json'));print(d['generated_at'],d['total_items'])"
daily-brief.jsonover 48 hourswithout update: do not use it to answer "today"-type questions, downgrade tolatest-24h.json, and explain the reason for the downgrade.latest-24h.jsonover 36 hourswithout update: answer as usual, but truthfully state at the beginning that "the data stops at X month X day, the upstream Actions may be down", and suggest the user (if they are a maintainer) use the Bole Skill to troubleshoot.- Never report stale data to the user as fresh data. Honestly labeling the data time is always part of the briefing.
Routing table
| The user is saying | Which route to take |
|---|---|
| Default broad question: "what's happening in the AI world today", "AI daily report", "AI news in the past 24 hours", "what's new in AI recently" | daily-brief.json(when freshness passes) — 20 curated items with built-in ranking and persona commentary |
| Ask for details, "give me more", "anything else" | upgrade to latest-24h.json, taking more items from the top |
| "model release", "AI product", "Agent tool", "paper", "robotics" | latest-24h.json filter by ai_label (mapping see below) |
| "what has OpenAI released recently", "Sora-related" | latest-24h.json match by keyword in title/title_en/ai_signals match in |
| "be more snarky", "sharp review", "switch it up", "compare three flavors" | top3-personas.json— TOP3 three flavors side by side |
| "today's big news", "storyline", "what events are worth paying attention to" | stories-merged.json(when freshness passes) take the top by importance_score take the top |
| "which sources are healthy/substantive", "source status" | source-status.json |
| "all updates/including non-AI" | latest-24h-all.json(warn about ~12MB first) |
| "last week's/last month's AI news" | state truthfully: the public data rolling window is 24 hours; history requires archive.json(56MB); get consent first before pulling |
ai_label Chinese mapping:model_release model release / ai_product_update product update / developer_tool developer tool / agent_workflow Agent workflow / research_paper paper research / industry_business industry news / infra_compute compute and Infra / robotics robotics / ai_tech technical progress / curated_hotlist hot list picks / ai_general general.
Source tiers source_tier_rank(smaller is more authoritative): 0 official first-party sources / 1 AI vertical sources / 2 Builders/X sources / 3 RSS/OPML / 5 discussion reference.
Persona fields (v0.8)
daily-brief.json each item may carry three persona fields:
persona_id: id of the scoring flavor (defaultpragmatic)persona_score: 0-100 integer scorepersona_review: one sentence of Chinese commentary (≤40 characters)
Degraded mode(when the upstream has no LLM Key configured): only persona_id and persona_score(from rule-based scores), no persona_review. When outputting the brief, just naturally skip the commentary lines; do not mention "missing", and do not make up a sentence to fill the count.
top3-personas.json schema:
{
"generated_at": "...",
"personas": [{"id": "pragmatic", "name": "实用派"}],
"items": [
{
"story_id": "...", "title": "...", "url": "...", "rank": 1,
"reviews": {
"pragmatic": {"score": 85, "review": "..."},
"cynic": {"score": 40, "review": "..."},
"paper-police": {"score": 55, "review": "..."}
}
}
]
}
Flavor Chinese names:pragmatic practical (default) / cynic snarky commentator / paper-police stickler. In degraded mode items is an empty array—at this point truthfully say "three-flavor commentary requires an LLM Key configured upstream" and fall back to the regular brief.
Workflow
Iron rule: download large files to /tmp first, filter with python3, and never dump the entire JSON into context. latest-24h.json has 2MB and nearly a thousand entries; catting it directly will drown you.daily-brief.json is only ~60KB, so it can be read in full.
Default path: daily brief picks (including persona commentary)
curl -fsSL "$BASE_URL/daily-brief.json" -o /tmp/radar-brief.json
python3 - <<'EOF'
import json
d = json.load(open('/tmp/radar-brief.json'))
print(f"数据时间: {d['generated_at']} | 精选: {d['total_items']}条")
for i in d['items']:
line = f"[{i.get('importance_label','')}|{i.get('source_count',1)}源] {i['title']} — {i.get('source_name') or i.get('source','')} — {i['url']}"
if i.get('persona_review'):
line += f"\n 点评({i.get('persona_score')}分): {i['persona_review']}"
print(line)
EOF
Ask for details / want more: upgrade to the full 24-hour dataset
curl -fsSL "$BASE_URL/latest-24h.json" -o /tmp/radar-24h.json
python3 - <<'EOF'
import json
d = json.load(open('/tmp/radar-24h.json'))
items = d['items_ai']
# 官方一手源优先,同层按AI相关性分数降序
top = sorted(items, key=lambda i: (i['source_tier_rank'], -i['ai_score']))[:30]
print(f"数据时间: {d['generated_at']} | 24h AI条目: {d['total_items']} | 信源: {d['source_count']}个")
for i in top:
print(f"[{i['ai_label']}|{i['source_tier_label']}] {i['title']} — {i['source']} — {i['url']}")
EOF
Filter by category ("what models were released recently")
python3 - <<'EOF'
import json
d = json.load(open('/tmp/radar-24h.json'))
hits = [i for i in d['items_ai'] if i['ai_label'] == 'model_release']
hits.sort(key=lambda i: (i['source_tier_rank'], -i['ai_score']))
for i in hits[:20]:
print(f"[{i['source_tier_label']}] {i['title']} — {i['source']} — {i['url']}")
EOF
By keyword ("what has OpenAI released recently")
python3 - <<'EOF'
import json
KW = 'openai' # 小写
d = json.load(open('/tmp/radar-24h.json'))
def hit(i):
blob = ' '.join([i.get('title',''), i.get('title_en') or '', ' '.join(i.get('ai_signals') or [])]).lower()
return KW in blob
hits = sorted(filter(hit, d['items_ai']), key=lambda i: (i['source_tier_rank'], -i['ai_score']))
for i in hits[:20]:
print(f"{i['title']} — {i['source']} — {i['published_at'][:10]} — {i['url']}")
EOF
Three-flavor commentary ("more snark / switch it up")
curl -fsSL "$BASE_URL/top3-personas.json" -o /tmp/radar-top3.json
python3 - <<'EOF'
import json
NAMES = {'pragmatic': '实用派', 'cynic': '毒舌评论员', 'paper-police': '较真党'}
d = json.load(open('/tmp/radar-top3.json'))
if not d.get('items'):
print('EMPTY') # 降级模式:告知需上游配LLM Key,退回普通简报
else:
print(f"数据时间: {d['generated_at']}")
for it in d['items']:
print(f"\nTOP{it['rank']} {it['title']} — {it['url']}")
for pid, r in it.get('reviews', {}).items():
print(f" {NAMES.get(pid, pid)}({r['score']}分): {r['review']}")
EOF
Storyline (pass freshness first)
curl -fsSL "$BASE_URL/stories-merged.json" -o /tmp/radar-stories.json
python3 - <<'EOF'
import json, datetime
d = json.load(open('/tmp/radar-stories.json'))
gen = datetime.datetime.fromisoformat(d['generated_at'].replace('Z','+00:00'))
age_h = (datetime.datetime.now(datetime.timezone.utc) - gen).total_seconds()/3600
if age_h > 48:
print(f"STALE:{age_h:.0f}h") # 看到STALE就降级走latest-24h.json,不要硬用
else:
top = sorted(d['stories'], key=lambda s: -s['importance_score'])[:15]
for s in top:
print(f"[{s['importance_label']}|{s['source_count']}源] {s['title']} — {s['primary_url']}")
EOF
Source health ("which sources have substance")
curl -fsSL "$BASE_URL/source-status.json" -o /tmp/radar-status.json
python3 - <<'EOF'
import json
d = json.load(open('/tmp/radar-status.json'))
print(f"成功:{d['successful_sites']} 失败:{d['failed_sites']} 零产出:{d['zero_item_sites']}")
for s in d['sites']:
flag = 'OK' if s['ok'] else 'FAIL'
print(f"[{flag}] {s['site_name']}: {s['item_count']}条")
EOF
Output format
Organize into a Chinese brief, structure:
# AI雷达简报 · [日期]
> 数据窗口: 过去24小时 | 数据时间: [generated_at转为人话] | [N]条精选 / [M]个信源
## 模型发布
- **[标题]** — [来源] ([信源层级])
[一句话说明,有原文链接]
> [口味中文名] [persona_score]分:[persona_review] ← 有 persona_review 才输出这行,没有就整行跳过
## 产品与工具
- ...
## 值得注意
- [热议参考层里讨论度高的1-3条]
Brief rules:
- Each item must include the original text
url, so users can click directly when they want to dig deeper. - Items from official first-hand sources are shown first; hot-discussion references only serve as "worth noting" supplements and are not mixed in.
- If the title has
title_zhuse Chinese; when the original text is English, you may usetitle_bilingual。 - Restrained item count: default 10-20 items, better fewer than filler. Add more only if the user asks.
- The persona commentary line is output only when the field exists; in degraded mode it is naturally omitted, with no explanation and no padding.
- Always mark the data time at the end of the text. If the data is stale, say so at the beginning; do not hide it.
Failure modes
- Pages 404 / network failure: switch to the raw address and retry once:
https://raw.githubusercontent.com/LearnPrompt/ai-news-radar/master/data/latest-24h.json. If it still fails, tell the truth; do not fabricate news. - Stale data: see "freshness check". Answer as usual + mark prominently + suggest the maintainer investigate.
- top3-personas.json is empty: degraded mode; truthfully explain that the three-flavor commentary requires an upstream LLM Key, and fall back to a regular briefing.
- A category is empty(e.g., no papers that day): truthfully say "there were no paper-type items in the radar over the past 24 hours"; do not pad with other categories.
- What the user asks about is not in the 24-hour window: explain the window limitation, offer the archive option (including a size warning), and do not pretend to have checked history.
Want to change sources or flavors? Upgrade path
This Skill only reads data. If the user says "I want to add a source / change the commentary flavor / build my own radar":
- fork
https://github.com/LearnPrompt/ai-news-radar; - Sources: use the repository'sBole Skill(
skills/ai-news-radar/) to enter and judge sources, and deploy GitHub Pages; flavors: edit the markdown files under thepersonas/directory; - then return to this Skill and point the top
BASE_URLline to your own Pages.
You choose the sources, you tune the flavors, the data belongs to you, and this Skill keeps helping you read it.
Security boundaries
- Only GET; only read public static files; do not send any write requests.
- No API Key, token, or cookie is needed or accepted.
- Do not scrape pages that require login; for private sources provided by the user, suggest the Bole Skill's private OPML/AgentMail path.
- When citing items, keep the original links and do not rewrite source attribution.