Skip to content

Repository files navigation

agent-notes

Telegram 傳影片/論文連結 → Claude agent 用 notebooklm-skill 產「繁體中文、逐段整理、用 markdown header 分類」的網誌式報告 → 寫進 Notion → 回傳 Notion 連結。

骨架取自 cwc-long-running-agents第一優先是「證據 evaluator」 —— 回報「完成」前,必須真的把產出讀回來確認有內容, 否則狀態強制停在 passes:false 並如實告訴你哪裡失敗,絕不回假連結

防 silent failure 是設計核心

每個 job 都有一份 Default-FAIL 契約(jobs/<id>/contract.json),兩道閘門初始都是 false

builderA(產報告) → 閘A(報告) → builderB(寫Notion) → 閘B(Notion) → 只有兩閘皆 PASS 才回「✅ 完成」

每道閘門跑兩種獨立檢查、兩個都要過

  1. 確定性本地檢查evaluators.py,無網路):抓空白、登入頁、字數不足、分段 header 不足。
  2. fresh-context LLM 稽核員agent.run_evaluator,read-only、全新脈絡):語意上判斷是不是 真的對應來源的中文分段報告,而非錯誤頁或編造。

典型會被擋下的失敗:NotebookLM session 過期回空報告、Playwright 卡 login gate、Notion 頁建了卻空白。

行為細節

  • 整理既有筆記本(sweep):傳 #topic 整理現有(或 sweep/sync),bot 會把該 topic 筆記本裡 每個還沒匯出的來源各自產一份報告、各自一頁 Notion;已匯出的自動跳過(可反覆執行、不重做)。 URL 來源用正規化網址比對,所以跟 #topic <連結> 走的是同一套防重複——已用連結匯過的不會再做一次。
  • 連結或檔案都收:傳 http/https 連結,或直接上傳附件檔(PDF / DOCX / TXT / MD,NotebookLM 能吃的)。 附件的 #topic 標籤放在 caption。bot 用 Telegram getFile 下載到 .state/downloads/,再 source add --type file 進對應筆記本。限制:Telegram bot API 只能下載 ≤20MB 的檔;超過會如實回失敗(不假裝成功)。
  • 依 topic 分流(每個 topic 一本筆記本、一個 Notion DB):傳連結時用 #標籤 指定 topic,例如 #ai 你的連結你的連結 #phd。bot 依 topics.json 把來源加進對應的 NotebookLM 筆記本 (如 (AgentNote) AI agent),整理後寫進對應的 Notion 資料庫(如 NotebookLM 報告 - AI agent)。 好處是順手在 NotebookLM 建立分主題的 RAG 語料庫。沒標、標到不存在、或一次標多個 topic → bot 不處理, 直接回你目前可用的 topic 清單(fail-closed,避免 typo 汙染語料庫)。
  • 同一筆記本內仍鎖來源:每次提問用 ask -s <source_id> 把範圍鎖在這次新增的來源,避免被同一本裡其他來源汙染。
  • 防重複:每個 topic 一份「已處理索引」(.state/processed/<topic>.json,gitignored)。同一個 (topic, 連結) 成功處理過後再傳一次 → bot 不重跑,直接回你上次的 Notion 連結。比對用的是正規化後的 URLyoutu.bewatch?v=utm_*/si/fbclid 等追蹤參數、結尾斜線、www.http/https#fragment 都會被忽略)。 索引只在整條成功後才寫,失敗的 job 仍可重試。要強制重做就在訊息加 #force
  • topic 設定兩層:定義在 topics.json(進 repo:別名 + 筆記本名 + Notion DB 標題); 自動建出來的 topic -> notion_db_id 快取在 .state/topic_dbs.json(gitignored)。新增 topic = 在 topics.json 加一筆,之後該 topic 的筆記本與 Notion DB 會在第一次用到時自動建立。
  • Notion 頁開頭自動加目錄:每頁第一個區塊是 Notion 原生 Table of Contents block,依 ## 標題自動產生, 方便點擊跳轉。

架構

src/agentnotes/
  contract.py     Default-FAIL 證據契約(核心防線)
  evaluators.py   確定性檢查 + 稽核員 prompt(核心防線)
  agent.py        Agent SDK 封裝:builder(可寫/可 Notion)vs evaluator(read-only、新 context)
  pipeline.py     單一來源的證據閘 pipeline(_run_source);run_pipeline=新來源、run_sweep=整理既有
  notebooklm_cli.py  Python 直呼 notebooklm CLI(找筆記本 id、列來源)—— sweep 用來逐來源防重複
  topics.py       topic registry:#標籤 → (NotebookLM 筆記本, Notion DB) 路由 + db_id 快取
  dedup.py        防重複:URL 正規化 + 每 topic 的「已處理索引」(#force 可覆寫)
  ingest/base.py  InputAdapter 介面(Line 之後接同介面)
  ingest/telegram.py  getUpdates 長輪詢 + sendMessage + 解析 #topic + 下載附件檔
  main.py         派工迴圈
topics.json       topic 定義(別名 / 筆記本名 / Notion DB 標題)—— 進 repo
.state/topic_dbs.json  自動建立後的 topic → notion_db_id 快取(gitignored)
.claude/agents/evaluator.md   稽核員子代理人定義(產出 PASS/FAIL)
.claude/agents/test-runner.md 測試執行子代理人:全新脈絡跑 pytest+ruff 回報
deploy/com.ron.agentnotes.plist  launchd 常駐
.github/workflows/ci.yml  CI:push/PR 自動跑 ruff + pytest(含覆蓋率)

tests/                    pytest 套件(全離線,不需外部服務)
  conftest.py             共用 fixtures:cfg / registry / index / good_report /
                          fake_agents(可調 gate 結果的假 builder+evaluator)/ poll_once(驅動 poll)
  test_evidence.py        證據防線:確定性檢查 + Default-FAIL 契約
  test_evaluators.py      確定性檢查的邊界(marker、門檻、失敗標題、計數)
  test_contract.py        契約不變量(無證據不過、未知 gate 報錯、磁碟往返)
  test_config.py          .env 解析 + chat-id allowlist
  test_topics.py          #標籤 解析、別名正規化、db_id 快取
  test_dedup.py           URL 正規化、檔案雜湊、索引、跳過/入帳/#force
  test_gate.py            verdict 解析 + Gate B 對真實頁面正文做檢查
  test_attachments.py     附件型別 gate、報告 prompt 檔案分支、poll 文件路由
  test_sweep.py           整理既有:指令偵測、逐來源防重複/失敗/#force
  test_telegram.py        poll() URL 路由(topic 缺/多、多連結、白名單、offset)
  test_main.py            _title_hint / _job_id / handle_job 派工

認證:靠本機已登入的 Claude 訂閱(2026-06-15 分池計費),不要ANTHROPIC_API_KEY, Agent SDK 會走訂閱池、與終端機 Claude Code 額度分開。

安裝

# 1) Python 環境 + 依賴
python3 -m venv .venv
.venv/bin/python -m pip install -e .          # 或:pip install claude-agent-sdk httpx

# 2) 裝 notebooklm-skill 並登入 Google(一次性、互動)
bash scripts/install_notebooklm.sh
.venv/bin/python -m notebooklm login          # 開瀏覽器登入,session 存 ~/.notebooklm/

# 3) 設定
cp .env.example .env
#   填 TELEGRAM_BOT_TOKEN(BotFather 新開的一支 bot)
#   填 NOTION_PARENT_PAGE_ID(Notion MCP 能存取、讓 bot 在底下建資料庫的一頁)
#   NOTION_DATABASE_ID 第一次留空——首跑會自動建「NotebookLM 報告」DB,再把 id 填回 .env

# 4) Notion MCP 授權(hosted):首次會走 OAuth;用 .venv 的 claude 在本目錄跑一次互動指令完成授權,
#    或設 NOTION_MCP_TOKEN(internal integration token)。詳見 .env.example。

驗證(由內而外,全部證據導向)

# 0) 一次性:裝開發/測試工具(pytest、pytest-cov、ruff)
.venv/bin/python -m pip install -e ".[dev]"

# A) 整個離線測試套件(不需任何外部服務)—— pytest 自動 discovery
.venv/bin/python -m pytest                              # 跑全部
.venv/bin/python -m pytest --cov=agentnotes --cov-report=term-missing  # 帶覆蓋率
.venv/bin/ruff check src tests                          # lint
#   涵蓋:證據防線(防謊報)、contract、config、topic 路由、防重複、附件、sweep、
#         telegram poll 路由、main 派工。共用 fixtures 在 tests/conftest.py。
#   也可用「test-runner」子代理人在全新脈絡自動跑 pytest+ruff 並回報 PASS/FAIL
#   (.claude/agents/test-runner.md)。CI 在 push/PR 會自動跑同一套(.github/workflows/ci.yml)。

# B) NotebookLM 段:對一支已知影片實跑,人工讀 jobs/<id>/report.md 確認繁中、逐段、## header
# C) 整鏈:把一個連結傳給 bot → 收到 ✅ + 可開的 Notion 連結
#    反向:故意讓 NotebookLM 登出 → 應收到「需重登」失敗通知,而不是假完成

跑 / 常駐

# 前景測試
PYTHONPATH=src .venv/bin/python -m agentnotes.main

# 本機常駐(launchd,非 cron)—— 編輯 plist 內絕對路徑後:
cp deploy/com.ron.agentnotes.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.ron.agentnotes.plist
tail -f logs/agentnotes.err.log

設計取捨(為何不照搬 cwc 的 /goal 迴圈)

cwc 的 build→evaluate→rebuild 迴圈是給「自主寫 code」用的。本 pipeline 是固定單趟 (NotebookLM → Notion),所以只取 cwc 的兩塊:①Default-FAIL 證據契約 + fresh-context evaluator (最重要),②PROGRESS.md 續跑記錄。閘門失敗就停下通知你,不自動重試編造。

待辦 / 已知限制

  • 入口目前只有 Telegram;Line 之後接 ingest/base.py 的同一介面。
  • jobs 一次處理一個(避免兩個 NotebookLM/Playwright session 互撞)。
  • Notion MCP 的 hosted OAuth 授權是一次性手動步驟。

About

Telegram → NotebookLM 中文分段報告 → Notion bot, with an evidence-evaluator gate that never reports success without reading the output (Claude Agent SDK, cwc-style)

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages