Last refreshed: April 6, 2026

AI News Briefing
Comprehensive Project Wiki

End-to-end reference for the automated daily pipeline and on-demand deep research: scheduler triggers, multi-engine CLI execution (Claude, Codex, Gemini, Copilot), multi-agent research, Notion publishing, Teams and Slack delivery, custom topic briefs, and maintenance workflows.

View Architecture Open README

Current system topology

From scheduler trigger to Notion and optional multi-channel webhook delivery (Teams + Slack).

flowchart LR
    subgraph Schedulers
        A1["macOS launchd"]
        A2["Windows Task Scheduler"]
        A3["Manual / make run"]
    end
    A1 --> B["briefing.sh / .ps1"]
    A2 --> B
    A3 --> B
    B --> C["prompt.md"]
    C --> D["AI Engine (Claude/Codex/Gemini/Copilot)"]
    D --> E["WebSearch (9 topics)"]
    D --> F["Notion MCP"]
    F --> G["Notion Page"]
    D --> H["card.json"]
    B --> I{"Teams webhook?"}
    I -->|Yes| J["notify-teams"]
    J --> K["Teams Channel"]
    B --> L{"Slack webhook?"}
    L -->|Yes| M["notify-slack"]
    M --> N["Slack Channel"]
    

Runtime Topology

flowchart TD
    subgraph Triggers
        A1["macOS launchd"]
        A2["Windows Task Scheduler"]
        A3["Manual make run"]
    end

    A1 --> B1["briefing.sh"]
    A2 --> B2["briefing.ps1"]
    A3 --> B1
    A3 --> B2

    B1 --> C["prompt.md"]
    B2 --> C

    C --> D["AI Engine"]
    D --> E["WebSearch"]
    D --> F["Notion MCP"]
    F --> G["Notion briefing page"]

    D --> CS["logs/covered-stories.txt"]
    D --> H["logs/YYYY-MM-DD.log"]
    D --> I["logs/YYYY-MM-DD-card.json"]

    B1 --> JT{"AI_BRIEFING_TEAMS_WEBHOOK set?"}
    B2 --> JT
    JT -->|"No"| KT["Skip Teams"]
    JT -->|"Yes"| LT["notify-teams script"]
    LT --> MT{"card JSON exists and is valid?"}
    MT -->|"Yes"| NT["POST Adaptive Card to Teams webhooks"]
    MT -->|"No"| OT["Teams notify failed"]

    B1 --> JS{"AI_BRIEFING_SLACK_WEBHOOK set?"}
    B2 --> JS
    JS -->|"No"| KS["Skip Slack"]
    JS -->|"Yes"| LS["notify-slack script"]
    LS --> MS{"card JSON exists and conversion succeeds?"}
    MS -->|"Yes"| NS["Convert to Block Kit and POST to Slack webhooks"]
    MS -->|"No"| OS["Slack notify failed"]
      

Successful Execution Sequence

sequenceDiagram
    participant S as Scheduler/Manual
    participant E as Entry Script
    participant C as AI Engine
    participant W as WebSearch
    participant N as Notion MCP
    participant T as notify-teams
    participant TW as Teams Webhook(s)
    participant SL as notify-slack
    participant SW as Slack Webhook(s)

    S->>E: Start briefing script
    E->>E: Setup date, logs, env
    E->>E: Refresh webhook env (Windows)
    E->>C: invoke selected engine (fallback chain)

    C->>C: Step 0a read logs/covered-stories.txt
    C->>N: Step 0b fetch most recent briefing
    N-->>C: prior coverage

    loop 9 topic areas
      C->>W: search recent news
      W-->>C: results
    end

    C->>N: Step 3 create today's page
    N-->>C: page URL

    C->>C: Step 5 append to covered-stories.txt

    C-->>E: exit 0 + output
    E->>E: append logs/YYYY-MM-DD.log

    opt Teams webhook configured
      E->>T: call notify-teams --all
      T->>T: validate card.json
      T->>TW: POST payload
      TW-->>T: 2xx
    end

    opt Slack webhook configured
      E->>SL: call notify-slack --all
      SL->>SL: convert card via teams-to-slack.py
      SL->>SW: POST Block Kit payload
      SW-->>SL: 2xx
    end
      

Execution guarantees and gaps

What each stage expects, produces, and where failures usually happen.

Stage Input Output Primary File/Tool
Trigger08:00 schedule or manual commandScript execution startscom.ainews.briefing.plist, install-task.ps1, Makefile
BootstrapDate + environmentPrompt text + runtime contextbriefing.sh, briefing.ps1
Deduplogs/covered-stories.txt + latest Notion pageExclusion list for this runStep 0a (file) + Step 0b (Notion MCP)
AI Runprompt.mdNotion briefing + card.json + covered-stories updateAI engine (Claude/Codex/Gemini/Copilot), WebSearch, Notion MCP
Teams Notifylogs/YYYY-MM-DD-card.json + AI_BRIEFING_TEAMS_WEBHOOKAdaptive Card post(s)notify-teams.sh, notify-teams.ps1
Slack Notifylogs/YYYY-MM-DD-card.json + AI_BRIEFING_SLACK_WEBHOOKBlock Kit post(s)notify-slack.sh, notify-slack.ps1, teams-to-slack.py
Multi-URL RoutingSemicolon-separated webhook URLsFirst URL by default, all URLs with --all/-AllTeams + Slack notify scripts
CleanupHistoric log filesOld *.log removedEntry script cleanup step

Prompt/Runtime Aligned

Resolved: `prompt.md` Step 4 generates `logs/YYYY-MM-DD-card.json` directly. Teams notifier posts this file as-is, and Slack notifier converts the same file to Block Kit before POST.

flowchart TD
    A[Entry script exits success] --> B{card.json exists?}
    B -->|No| B1[Notify paths fail fast]
    B -->|Yes| T{Teams webhook env set?}
    B -->|Yes| S{Slack webhook env set?}

    T -->|No| T0[Skip Teams]
    T -->|Yes| T1[notify-teams]
    T1 --> T2{JSON valid + URL list valid?}
    T2 -->|No| T3[Teams notify failed]
    T2 -->|Yes| T4[POST to first URL or all URLs]

    S -->|No| S0[Skip Slack]
    S -->|Yes| S1[notify-slack]
    S1 --> S2{teams-to-slack conversion OK?}
    S2 -->|No| S3[Slack notify failed]
    S2 -->|Yes| S4[POST Block Kit to first URL or all URLs]
    

9 topic areas searched daily

The briefing targets short-horizon AI news (past 24 hours) across the following domains.

1

Claude Code / Anthropic

Releases, features, Anthropic updates

2

OpenAI / Codex / ChatGPT

Model changes, API updates, product launches

3

AI Coding IDEs

Cursor, Windsurf, Copilot, JetBrains, Xcode AI

4

Agentic AI Ecosystem

LangChain, CrewAI, AutoGen, MCP and agents

5

AI Industry

Major lab announcements, benchmarks, launches

6

Open Source AI

Llama, Mistral, DeepSeek, Hugging Face

7

AI Startups & Funding

Rounds, acquisitions, startup launches

8

AI Policy & Regulation

Government policy and AI safety regulation

9

Dev Tools & Frameworks

Vercel, Next.js, React Native, TypeScript tooling

Deep research on any topic, on demand

Pick a topic, choose your destinations, and get a comprehensive news-focused research briefing with linked citations and dates.

flowchart LR
    A["Topic Input
(CLI flags or REPL)"] --> B["custom-brief.sh / .ps1"] B --> C["prompt-custom-brief.md"] C --> D["AI Engine"] subgraph "Phase 1: Parallel Discovery" D --> A1["Agent 1: Breaking News"] D --> A2["Agent 2: Technical Analysis"] D --> A3["Agent 3: Industry Impact"] D --> A4["Agent 4: Trends"] D --> A5["Agent 5: Policy"] D --> A6["Agent 6+: Topic-specific"] end A1 --> DD["Phase 2: Deep Dive"] A2 --> DD A3 --> DD A4 --> DD A5 --> DD A6 --> DD DD --> S["Phase 3: Synthesis"] S --> OUT["Terminal Output"] S -->|"--notion"| N["Notion Page"] S -->|"--teams/--slack"| CARD["Card JSON"] CARD --> T["Teams"] CARD --> SL["Slack"]

Research Agent Architecture

flowchart TD
    subgraph "Entry Points"
        SH["custom-brief.sh"]
        PS["custom-brief.ps1"]
        SK["/custom-brief skill"]
    end

    SH --> PT["prompt-custom-brief.md"]
    PS --> PT
    SK --> CC["AI Engine"]
    PT --> CC

    subgraph "Phase 1: Parallel Discovery"
        CC --> A1["Agent 1: Breaking News"]
        CC --> A2["Agent 2: Technical Analysis"]
        CC --> A3["Agent 3: Industry Impact"]
        CC --> A4["Agent 4: Trend Trajectory"]
        CC --> A5["Agent 5: Policy and Ethics"]
    end

    subgraph "Phase 2-3: Synthesis"
        A1 --> DD["Deep Dive Follow-ups"]
        A2 --> DD
        A3 --> DD
        A4 --> DD
        A5 --> DD
        DD --> SYNTH["Thematic Synthesis"]
    end

    subgraph "Output"
        SYNTH --> STDOUT["Terminal"]
        SYNTH -->|"--notion"| NOTION["Notion Page"]
        SYNTH -->|"--teams/--slack"| CARD["Card JSON"]
        CARD --> NT["notify-teams"]
        CARD --> NS["notify-slack"]
    end
      
custom brief usage
# Full research with all destinations
./custom-brief.sh --topic "AI in healthcare" --notion --teams --slack

# Terminal + Notion only
./custom-brief.sh -t "quantum computing" -n

# Interactive mode (prompts for topic and destinations)
./custom-brief.sh

# PowerShell
.\custom-brief.ps1 -Topic "AI regulation EU" -Notion -Teams

# Make target
make custom-brief T="open source LLMs" NOTION=1 TEAMS=1
Aspect Daily Briefing Custom Brief
TriggerScheduled (8:00 AM daily)On-demand
Scope9 fixed AI topicsAny user-defined topic
DepthBroad scan (search per topic)Deep (5 parallel agents + follow-ups)
DeduplicationYes (covered-stories.txt)No (standalone)
Notion titleYYYY-MM-DD - AI Daily BriefingYYYY-MM-DD - Custom Brief: [Topic]
CLI outputLogged to file onlyPrinted to terminal + logged
Card filenamelogs/YYYY-MM-DD-card.jsonlogs/custom-TIMESTAMP-card.json

Install, run, backfill, inspect

Daily operation commands for both standard runs and historical date backfills.

quick start (make)
# Clone + install scheduler
git clone https://github.com/hoangsonww/AI-News-Briefing
cd AI-News-Briefing
make install

# Run now
make run

# Backfill a specific date
make run D=2026-03-15

# Watch logs
make tail
platform-native scheduling
# macOS install (launchd)
chmod +x briefing.sh
cp com.ainews.briefing.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.ainews.briefing.plist

# Windows install (Task Scheduler)
.\install-task.ps1

# Windows custom schedule example
.\install-task.ps1 -Hour 7 -Minute 30
Action macOS/Linux Windows
Run nowbash briefing.sh.\briefing.ps1
Backfill datebash briefing.sh 2026-03-15.\briefing.ps1 -BriefingDate 2026-03-15
Trigger schedulerlaunchctl kickstart "gui/$(id -u)/com.ainews.briefing"schtasks /run /tn AiNewsBriefing
Tail today logtail -f logs/$(date +%Y-%m-%d).logGet-Content .\logs\$(Get-Date -Format yyyy-MM-dd).log -Wait
Scheduler statuslaunchctl list | grep ainewsschtasks /query /tn AiNewsBriefing

Cross-platform command surface

Single interface for execution, logs, scheduler management, and validation.

Command Category Description
make runExecutionRun briefing in foreground
make run-bgExecutionRun briefing in background
make run D=YYYY-MM-DDExecutionBackfill for a target date
make run-scheduledExecutionTrigger via scheduler service
make custom-brief T="topic"ExecutionDeep-research a specific topic
make custom-brief T="..." NOTION=1 TEAMS=1ExecutionResearch + publish to Notion/Teams
make custom-brief-bg T="..."ExecutionCustom brief in background
make tailLogsTail today log
make logsLogsList all logs
make log-date D=YYYY-MM-DDLogsPrint date-specific log
make clean-logsLogsDelete logs older than 30 days
make installSchedulerInstall scheduler for current platform
make uninstallSchedulerRemove scheduler
make statusSchedulerShow scheduler status
make checkValidateVerify Claude binary path
make validateValidateValidate key project files and prompt steps
make infoInfoShow platform/model/topic summary

Utility Script Catalog

Script pairs exist for both `.sh` and `.ps1` variants.

Script Purpose Example
health-checkVerify install, prompt structure, scheduler, CLIbash scripts/health-check.sh
dry-runRun pipeline without writing to Notionbash scripts/dry-run.sh --model haiku --budget 1.00
test-notionTest Notion MCP connectivitybash scripts/test-notion.sh
log-summarySummarize recent run outcomesbash scripts/log-summary.sh 14
log-searchSearch logs with optional contextbash scripts/log-search.sh --search "Anthropic" --context 2
cost-reportEstimate spend by periodbash scripts/cost-report.sh --month 2026-03
export-logsArchive logs to tar.gz/zipbash scripts/export-logs.sh --from 2026-03-01 --to 2026-03-09
backup-promptVersion and restore prompt.mdbash scripts/backup-prompt.sh --list
topic-editAdd/remove/list topics in prompt.mdbash scripts/topic-edit.sh --list
update-scheduleAdjust scheduler timebash scripts/update-schedule.sh --hour 7 --minute 30
notifyNative OS status notificationbash scripts/notify.sh
notify-teamsValidate and POST Adaptive Card JSON to Teams webhook(s)bash scripts/notify-teams.sh --all --card-file logs/2026-03-24-card.json
notify-slackConvert Teams card JSON to Block Kit and POST to Slack webhook(s)bash scripts/notify-slack.sh --all --card-file logs/2026-03-24-card.json
uninstallRemove scheduler and optional artifactsbash scripts/uninstall.sh --all

Teams + Slack webhook paths

Both channels use the same generated logs/YYYY-MM-DD-card.json, with Slack converting it to Block Kit first.

flowchart LR
    A["Claude writes logs/YYYY-MM-DD-card.json"] --> B{"Channel notifier"}
    B --> C["notify-teams.sh / notify-teams.ps1"]
    B --> D["notify-slack.sh / notify-slack.ps1"]
    C --> E["POST Adaptive Card JSON to Teams webhooks"]
    D --> F["teams-to-slack.py conversion"]
    F --> G["POST Block Kit JSON to Slack webhooks"]
    
configure + test delivery (macOS/Linux)
# Configure multiple webhook URLs (semicolon-separated)
export AI_BRIEFING_TEAMS_WEBHOOK="https://teams-one;https://teams-two"
export AI_BRIEFING_SLACK_WEBHOOK="https://hooks.slack.com/services/T.../B.../one;https://hooks.slack.com/services/T.../B.../two"

# Default: first URL only
bash scripts/notify-teams.sh
bash scripts/notify-slack.sh

# Fan out to all configured URLs
bash scripts/notify-teams.sh --all
bash scripts/notify-slack.sh --all

# Explicit card file for replay/testing
bash scripts/notify-teams.sh --all --card-file logs/2026-03-24-card.json
bash scripts/notify-slack.sh --all --card-file logs/2026-03-24-card.json
configure + test delivery (Windows PowerShell)
# Persist multiple webhook URLs (semicolon-separated)
[Environment]::SetEnvironmentVariable("AI_BRIEFING_TEAMS_WEBHOOK", "https://teams-one;https://teams-two", "User")
[Environment]::SetEnvironmentVariable("AI_BRIEFING_SLACK_WEBHOOK", "https://hooks.slack.com/services/T.../B.../one;https://hooks.slack.com/services/T.../B.../two", "User")

# Default: first URL only
.\scripts\notify-teams.ps1
.\scripts\notify-slack.ps1

# Fan out to all configured URLs
.\scripts\notify-teams.ps1 -All
.\scripts\notify-slack.ps1 -All

# Explicit card file for replay/testing
.\scripts\notify-teams.ps1 -All -CardFile ".\logs\2026-03-24-card.json"
.\scripts\notify-slack.ps1 -All -CardFile ".\logs\2026-03-24-card.json"

Legacy note: `scripts/build-teams-card.py` remains for historical parser flow, but current runtime uses direct card generation in `prompt.md` Step 4. Slack reuses that same card through `scripts/teams-to-slack.py`.

247 non-blocking tests

Verify syntax, structure, arg handling, template substitution, card JSON, notification error paths, and cross-platform portability. No external services called.

flowchart TD
    subgraph "Bash (macOS / Linux / Git Bash)"
        R["tests/run-all.sh"] --> T1["test-custom-brief.sh\n37 tests"]
        R --> T2["test-daily-brief.sh\n56 tests"]
        R --> T3["test-notifications.sh\n37 tests"]
        R --> T4["test-portability.sh\n26 tests"]
    end
    subgraph "PowerShell (Windows)"
        PS["tests/test-all.ps1\n91 tests"]
    end
    T1 --> X["Args, templates,\nprompts, skills"]
    T2 --> Y["Steps, topics,\nchangelogs, scripts"]
    T3 --> Z["Card JSON, converter,\nerror handling"]
    T4 --> W["Bash 3.2, awk, date,\nANSI safety"]
    PS --> X
    PS --> Y
    PS --> Z
    
run tests
# All bash tests (macOS / Linux / Git Bash)
bash tests/run-all.sh

# Individual suites
bash tests/test-custom-brief.sh
bash tests/test-daily-brief.sh
bash tests/test-notifications.sh
bash tests/test-portability.sh

# PowerShell (Windows)
powershell -ExecutionPolicy Bypass -File tests\test-all.ps1
Suite Tests Coverage
test-custom-brief.sh37Args, template substitution, prompt structure, skill
test-daily-brief.sh56Prompt steps, 9 topics, 8 changelog URLs, entry scripts, dedup
test-notifications.sh37Card JSON validity, Adaptive Card structure, converter, errors
test-portability.sh26Bash 3.2 compat, awk, date, -f not -x, ANSI safety
test-all.ps191PowerShell syntax, all prompts, cards, converter, docs
Full test documentation: TESTS.md

Default operating envelope

Baseline estimates with Opus model, 9 topics, no hard budget cap.

Per Run
~$3-5
Opus model, uncapped
Monthly (Daily)
~$90-150
Typical: varies by news volume
Hard Cap
None
No --max-budget-usd set
Runtime
4-8 min
Search, dedup, compile, publish

Source docs and references

Primary docs to keep this wiki and runtime behavior aligned.

README.md

User-facing setup, topic scope, scheduler installation, Makefile commands, and Teams + Slack delivery overview.

ARCHITECTURE.md

Deep architecture walkthrough with component-level design decisions and operational constraints.

E2E_FLOW.md

Detailed end-to-end execution, sequence, failure paths, artifact contracts, and alignment options.

NOTIFY_TEAMS.md

Teams webhook setup, multi-webhook configuration, Adaptive Card behavior, and troubleshooting delivery issues.

scripts/teams-to-slack.py

Converter that transforms Teams Adaptive Card JSON into Slack Block Kit payloads for Slack webhook delivery.

prompt.md

Agent instructions for search scope, formatting requirements, and Notion write operation.

CUSTOM_BRIEF.md

Custom topic deep research: CLI usage, agent architecture, output formats, and comparison with daily briefing.

SETUP.md

Full setup guide: AI CLI engines, Notion MCP, webhook configuration, scheduler install, and verification.

NOTIFY_SLACK.md

Slack webhook setup, Block Kit conversion, multi-webhook configuration, and troubleshooting.

TESTS.md

Test suite documentation: architecture, per-suite coverage tables, run commands, design principles, how to add tests.

LOGS.md

Log tailing and management: live tail, read, search, summarize, export, and cleanup for daily and custom briefs.

Makefile

Cross-platform operator interface for run, schedule, custom-brief, log, validation, and status workflows.

ai-news-briefing/
  briefing.sh / briefing.ps1 # daily briefing entry points
  prompt.md # daily briefing agent prompt
  custom-brief.sh / custom-brief.ps1 # custom topic deep research CLI
  prompt-custom-brief.md # multi-agent research prompt template
  commands/ # Claude Code interactive skills
    ai-news-briefing.md # daily briefing skill
    custom-brief.md # custom topic skill
  scripts/ # diagnostics, maintenance, notify paths
    notify-teams.sh / .ps1 # Teams webhook notifier
    notify-slack.sh / .ps1 # Slack webhook notifier
    teams-to-slack.py # Adaptive Card to Block Kit converter
  tests/ # 221 non-blocking tests (bash + PowerShell)
  logs/ # runtime output (gitignored)
    covered-stories.txt # dedup headline tracker
  README.md # setup + usage
  ARCHITECTURE.md # deep architecture
  CUSTOM_BRIEF.md # custom brief documentation
  SETUP.md # full setup guide
  E2E_FLOW.md # execution contracts
  NOTIFY_TEAMS.md / NOTIFY_SLACK.md # integration guides
  index.html # this wiki page