尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Weekly AI newsletter pipeline: multi-agent system that scores ArXiv papers and news with Claude, composes an HTML email, and sends it on Google Cloud.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗
What's different: one spotlight research paper and the week's top AI news, picked, summarized and sent by a team of AI agents that checks its own work every run.
Stage-by-stage detail: docs/architecture.md
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 26, "rankSpacing": 40, "padding": 10, "curve": "basis"}}}%%
flowchart LR
ORC["☁️ Sun 12 PM<br/><b>Orchestrator</b>"] --> A1A["<b>Agent 1a</b><br/>Pick paper"]
ORC --> A1B["<b>Agent 1b</b><br/>Fetch news"]
A1A --> A2A["<b>Agent 2a</b><br/>Summarize"]
A1B --> A2B["<b>Agent 2b</b><br/>Summarize"]
A2A --> FAN{"<b>Fan-in</b><br/>2 of 2"}
A2B --> FAN
FAN --> A3["<b>Agent 3</b><br/>Compose"]
A3 --> DB[("Firestore<br/>run state")]
DB --> A4["☁️ Mon 7 AM<br/><b>Agent 4</b> · Send"]
DB --> HC1["☁️ Sun 1:15 PM<br/><b>Draft check</b>"]
DB --> HC2["☁️ Mon 7:10 AM<br/><b>Send check</b>"]
classDef agent fill:#4f46e5,stroke:#312e81,color:#fff
classDef fan fill:#7c3aed,stroke:#4c1d95,color:#fff
classDef store fill:#d97706,stroke:#92400e,color:#fff
classDef health fill:#059669,stroke:#065f46,color:#fff
class ORC,A1A,A1B,A2A,A2B,A3,A4 agent
class FAN fan
class DB store
class HC1,HC2 health
| Agent | What it does |
|---|---|
| 1a Papers | Picks the week's spotlight paper from Hugging Face's trending list and scores it with Claude. |
| 1b News | Gathers Hacker News and NewsAPI stories, filters by language and sorts them into 7 categories. |
| 2a / 2b Summaries | Write a short summary of the paper (2a) and of each article (2b), in parallel. |
| 3 Compose | Picks the best articles per category, writes the editor's note and builds the HTML email. |
| 4 Send | Sends each subscriber their personalized version through SendGrid on Monday morning. |
| Health checks | A draft check on Sunday and a send check on Monday email a report on every run. |
Agents hand work to each other through Pub/Sub; Firestore holds each run's state. Cloud Scheduler triggers the pipeline, the send and both health checks.
AGENT1B_MODE=single_pass restores the original linear code without a redeploy.%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 28, "rankSpacing": 44, "padding": 10, "curve": "basis"}}}%%
flowchart LR
COL["<b>Collect</b><br/>HN + NewsAPI<br/>drop paywalls"] --> LANG["<b>Language</b><br/>English or<br/>French only"]
LANG --> CAT["<b>Categorize</b><br/>7 topics +<br/>confidence 1-5"]
CAT -->|"confident"| FIN["<b>Finalize</b><br/>write results<br/>+ audit log"]
CAT -->|"unsure"| LLM["<b>Review: think</b><br/>Claude decides"]
LLM -->|"needs text"| TOOL["<b>Review: act</b><br/>fetch the article"]
TOOL --> LLM
LLM -->|"answer"| FIN
classDef step fill:#4f46e5,stroke:#312e81,color:#fff
classDef loop fill:#7c3aed,stroke:#4c1d95,color:#fff
classDef out fill:#059669,stroke:#065f46,color:#fff
class COL,LANG,CAT step
class LLM,TOOL loop
class FIN out
Agent 3 has a second, smaller graph that removes duplicate stories from each section's picks, once per section and selection pass. One Claude call checks all the picks, the highest-scoring article of each duplicate group is kept, and replacements from the ranked runners-up are checked one at a time until the section is back to its size. Any error falls back to the original picks, and AGENT3_DEDUP_MODE=off disables it without a redeploy.
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 28, "rankSpacing": 44, "padding": 10, "curve": "basis"}}}%%
flowchart LR
SEL["<b>Select</b><br/>picks + ranked<br/>runners-up"] --> CHK["<b>Check</b><br/>one call finds<br/>duplicate groups"]
CHK -->|"none found"| FIN["<b>Finalize</b><br/>section + audit log"]
CHK -->|"duplicates"| RES["<b>Resolve</b><br/>keep top HN score,<br/>drop the rest"]
RES -->|"section full"| FIN
RES -->|"gap to fill"| REF["<b>Refill</b><br/>check next runner-up<br/>against all seen"]
REF -->|"still a gap"| REF
REF -->|"full, or out of<br/>runners-up or tries"| FIN
classDef step fill:#4f46e5,stroke:#312e81,color:#fff
classDef loop fill:#7c3aed,stroke:#4c1d95,color:#fff
classDef out fill:#059669,stroke:#065f46,color:#fff
class SEL,CHK step
class RES,REF loop
class FIN out
Why LangGraph runs inside agents but not between them: ADR 0001 and ADR 0002.
Every weekly run ends in an email report to the maintainer, whether or not anything is wrong, so a missing email is itself a signal.
| Signal | What it watches | Response |
|---|---|---|
| 🟢 Health checks | Every pipeline stage, the composed newsletter and delivery | Email report: all clear or problem detected |
| 🟢 Failure recording and watchdog | Agent errors and hung or crashed runs | Written to Firestore; hung runs are killed |
| 🔵 Drift | Agent 1b's confidence, category mix and review rate | Flagged only for large, significant shifts |
| 🔵 Token and cost | LangSmith token and cost totals per run | Flagged on big jumps versus prior weeks |
| ⚪ Summary judge | A weekly sample of summaries checked against their sources | Report only (see Results) |
| ⚪ Click signal | Aggregate link clicks, with no subscriber data | Informational section in the report |
🟢 acts on failures 🔵 flags large shifts ⚪ informational only
Details: docs/monitoring.md
| Area | What's in place |
|---|---|
| Cloud | 10 Cloud Run services from one Docker image, Pub/Sub, Firestore, Cloud Scheduler, Secret Manager, Firebase Hosting and Auth |
| Build and deploy | Cloud Build builds every image in parallel; deploys are separate, deliberate steps; API keys are mounted from Secret Manager |
| CI | GitHub Actions runs the full test suite (stubbed Claude client, no keys) and a Docker build check on every push and pull request |
| Evaluation | Paid evals run on demand behind a cost estimate and a hard cap; results are JSON files with confidence intervals |
| Observability | LangSmith tracing, the weekly health check report, structured logs |
| Reliability | Idempotent fan-in, isolated retries, a 24-hour stale-newsletter guard, rollback switches |
| Stack | Python 3.11, Anthropic Claude, LangGraph, FastAPI, SendGrid, Firebase Auth |
Deployment and local setup: docs/development.md
Each weekly issue now costs about $0.55 in model calls, down from about $2.06 at the start of the cost work (a 73% cut, measured on one production run on 2026-10-28). Picking the paper (agent 1a) and summarizing the news (agent 2b) are the two big lines: agent 1a reads the full text of only its top 8 papers after scoring all 35 abstracts, and agent 2b summarizes only a shortlist of about 70 articles instead of all 500. Sorting the news (agent 1b, the language filter and categorizer) moved from Claude Haiku to DeepSeek V4.1 Flash, which cut its line by about 90% with no measurable change in what gets through; the paper scoring and summaries stay on Haiku because DeepSeek scored noisier on papers and was easier to prompt-inject on summaries.
Costs are list-price estimates per run (LangSmith's for Claude, the provider's list for DeepSeek), archived by the health check. Generated by python -m evals.fetch_pipeline_cost and python -m evals.make_charts. More: docs/monitoring.md and the full step-by-step record in docs/cost-reduction-roadmap.md.
All charts below are generated from evals/results/*.json by python -m evals.make_readme_table, never drawn or typed by hand. Each has its table in docs/evaluation.md.
Agent 1b's review loop was compared with the original single-pass code on the same hand-labeled articles. It did not measurably help: the differences sit inside the noise, and the model's own confidence did not predict its mistakes. Reported plainly.
Hand-written attacks (forced categories, tag breakouts, prompt leaks, planted URLs) were run through the real agent code paths, once with the injection and once without. The attacks that worked before the fixes were stopped by input sanitising, guard text on every Claude call and a fetch guard. The checks catch canary-style compliance only, and small samples mean "none observed" is not "safe".
A second Claude model checks a weekly sample of summaries against the text they were written from. Calibrated against 40 summaries I labeled by hand, it agreed with me no better than chance (kappa in the chart), so it runs report-only and can never trigger an alert.
Agent 3 checks each section's picks for the same story told by several outlets and swaps duplicates for the next-best article. On 57 hand-labeled article sets (33 duplicate groups), both Haiku and Sonnet found roughly nine in ten duplicates and removed a unique article in under 1% of cases; the intervals overlap, so the cheaper Haiku stays. Small sample, and only the first check is scored, not the replacement path.
Full results and caveats: docs/evaluation.md
MIT.