# Cron Job: reddit-daily-digest

**Job ID:** 93a2c5150a6f
**Run Time:** 2026-06-11 05:07:14
**Schedule:** 0 5 * * *

## Prompt

[IMPORTANT: The user has invoked the "content-monitoring-briefings" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]

---
name: content-monitoring-briefings
description: "Monitor external content channels, compare recent output to industry developments, and publish concise briefings or Telegram sitreps."
platforms: [linux, macos, windows]
---

# Content Monitoring & Briefings

Use this skill when the user wants to:
- scrape or inspect a YouTube channel, creator feed, or other content stream
- compare recent uploads/posts against what happened in the broader industry
- identify gaps, missed stories, or under-covered themes
- turn the result into a daily briefing, sitrep, or delivery to Telegram

This is an umbrella workflow skill. Keep it reusable: channel-specific details belong in `references/`.

## Core workflow

1. **Verify the target first**
   - Confirm the exact channel/page/account URL.
   - If the user names a creator but gives a different URL, trust the URL and mention the mismatch if relevant.
   - Inspect the page identity before analyzing topics.

2. **Collect the latest items**
   - Prefer the channel's videos/posts page.
   - Use browser snapshots for visible metadata, and browser text extraction when the page is virtualized or truncated.
   - Capture title, age, view count, and any recurring topic labels.
   - If the visible list is incomplete, scroll and continue until the requested time window is covered.

3. **Classify the content**
   - Group items by topic family: product firmware, product reviews, platform updates, policy/regulation, ecosystem moves, and tutorials/how-tos.
   - Mark whether the item is reactive news, evergreen content, or opinion/analysis.

4. **Compare against industry reality**
   - Look for gaps in:
     - ecosystem/platform competition
     - policy and regulation impact
     - AI or automation trends
     - privacy/data governance
     - sustainability/repairability
     - adjacent competitors or substitute products
   - Ask: what changed in the industry that the channel did not cover, and why does that omission matter?

5. **Write the briefing**
   - Start with the direct answer.
   - Keep it structured: covered / missed / why it matters / next story ideas.
   - If the user asks for a public-ready result, make it readable without extra explanation.

6. **Confirm cadence before scheduling**
   - Do not turn a request for realtime/current status into a daily cron job by default.
   - If the user says "realtime," "now," or asks for a live quota/status check, perform an immediate check or explain the available live signal first.
   - Only create scheduled jobs after the cadence is explicit (for example daily at 09:00, every hour, or watchdog-style only-on-change alerts).

7. **Deliver to Telegram when requested**
   - If the user wants a Telegram target, list available message targets first when a specific recipient is needed.
   - Use the home Telegram destination when the user simply says "send to Telegram".
   - For daily sitreps, use a concise format: key items, notable changes, one recommendation.

## Long-output delivery pattern (cron → file + email)

Use this when a recurring monitoring job produces output too long for chat (>50 lines / 3000 chars), or when the user prefers email over Telegram for their daily digests.

### Prompt structure for the cron job
The cron job prompt must be self-contained (no chat context available). Include:

- The exact source URL or API endpoint
- Time window (e.g. "past 24h", "since last run")
- Formatting rules inline (the cron agent has no chat context)
- The model override (typically `deepseek-chat` on `deepseek` for crons)
- Three delivery actions, in this order:

```
1. Write output to /opt/data/cron/output/<channel-slug>/YYYY-MM-DD.md
   Create directories if needed.
2. EMAIL the full digest to styto@duck.com with subject "<type> - <channel> - YYYY-MM-DD"
   via AgentMail: load_dotenv('/opt/data/.env'), from=h3rm3z@agentmail.to, plain text body.
   Only skip email if there's genuinely nothing new to report.
3. For the cron output itself: deliver a SHORT Telegram summary (max 5-8 lines).
   End with "Volledige digest gemaild naar styto@duck.com".
```

### Cron job creation with model override + skills
When creating a monitoring cron job:

```python
cronjob(
    action="create",
    name="<slug>",
    schedule="<cron>",
    prompt="<self-contained prompt>",
    model={"provider": "deepseek", "model": "deepseek-chat"},
    skills=["content-monitoring-briefings", "long-output-to-email"],
    enabled_toolsets=["web", "terminal", "file"],
    deliver="origin",  # korte Telegram samenvatting
)
```

### Conditional email (skip when no new content)
When the channel has no new items since the last run:
- Write "No new videos" or "Nothing notable" to the local file
- Skip the email entirely — don't send empty digests
- Respond with "[SILENT]" to suppress Telegram delivery

This keeps the user's inbox clean and only alerts them to actual content.

### Reddit-specific: prefer JSON API, fall back to RSS when blocked
For Reddit cron jobs, first try appending `.json` to subreddit URLs (e.g. `https://www.reddit.com/r/bellingcat/hot.json`) with a browser-like `User-Agent`. The JSON API is fast when Reddit allows it, but this environment can receive HTTP 403 `Blocked` from Reddit's JSON endpoints. If JSON returns 403/Blocked or another network-security error, fall back to RSS/Atom:
- `https://www.reddit.com/r/<sub>/hot/.rss`
- `https://old.reddit.com/r/<sub>/.rss`
Do not use browser automation for Reddit cron jobs. The `web`, `terminal`, and `file` toolsets are sufficient. Default to `hot`; only use `top` if the user explicitly asks for top posts.

### Purge old output
Set up a daily cron at 03:00 that deletes `.md` files older than 30 days from `/opt/data/cron/output/`:
```
find /opt/data/cron/output/ -type f -name "*.md" -mtime +30 -delete
find /opt/data/cron/output/ -type d -empty -delete
```

## Cron prompt template (YT sitrep)

```
Check [CHANNEL NAME] YouTube channel at [URL] for new videos since the last run.
Output in thematic groups with short title+explanation per item, up to 5 videos max,
concluding takeaway. In Dutch.
Delivery:
1. Write to /opt/data/cron/output/yt-<slug>/YYYY-MM-DD.md (create dirs if needed)
2. EMAIL to styto@duck.com with subject "YT Sitrep - [Name] - YYYY-MM-DD"
   via AgentMail: load_dotenv('/opt/data/.env'), from=h3rm3z@agentmail.to, plain text body.
   Skip email if no new videos since last run.
3. Cron output: short Telegram summary (3-5 lines max), end with "Volledige digest gemaild"
If NO new videos: write "No new videos", skip email, respond [SILENT].
```

## Cron prompt template (Reddit digest — 50+ subreddits, categorized)

```
Create a concise daily digest from these Reddit subreddits. Use JSON API (append .json to URLs).
Skip stickied posts. Top 1-3 threads per sub, each with title, upvotes, 1-line BLUF in Dutch.
Categorize output by domain.

[List subreddits grouped by category: Luchtvaart & radio, Cybersecurity & OSINT, AI & modellen,
 Wearables/sport/gezondheid, Outdoor/bikepacking/reizen, Tactisch/defensie, België/Europa,
 Gaming, Maker/hardware/niche]

Format: ## headers per category. Per thread: **title** (↑N) — BLUF.
Lurker-friendly: no engagement prompts, no CTA. Deduplicate across subs.
Empty categories: mark "(geen noemenswaardige posts deze 24u)"

Delivery:
1. Write full digest to /opt/data/cron/output/reddit-daily/YYYY-MM-DD.md
2. EMAIL full digest to styto@duck.com via AgentMail
3. Cron output: SHORT Telegram summary (5-8 lines max) + "Volledige digest gemaild"
If NO notable content: write file, skip email, respond [SILENT].
```

### News24 briefing pattern

Use this when the user says `nieuws24` or asks for a last-24-hours news briefing.

1. **Use the configured source set**
   - Default sources for this user: GVA, De Standaard, VRT NWS, De Morgen, Tweakers, Business AM, Newsmonkey, De Tijd.
   - Prefer RSS/Atom feeds for timestamped recent items when available; use homepage extraction and search snippets as fallback.
   - If a source is blocked by paywall, privacy gate, or RSS limits, include a short source caveat rather than pretending full coverage.
   - Full source list with prioritization in `references/news24-dutch-sources.md`.

2. **Filter to the user's interests**
   - Exclude football, rap/Kanye West, and pop-celebrity items such as Dua Lipa by default.
   - Include those topics only if they become major hard news with broader public-safety, legal, political, or economic relevance.
   - Prioritize Belgium/regional hard news, politics/policy, justice, infrastructure, economy, geopolitics, safety incidents, technology, and cybersecurity.

3. **Keep it concise and scannable**
   - Start with the direct 24h scope and source caveat.
   - Group by section (🇧🇪 België, 🌍 Internationaal, 🔬 Tech, 🏛️ Opmerkelijk).
   - Per item: title + 1 short line explaining relevance.
   - End with "Wat viel op?" — 2-3 closing observations.
   - Avoid entertainment filler when the user did not ask for culture coverage.
   - No linkdumps: provide context inline.

4. **Parallel extraction for speed**
   - Use delegate_task with multiple workers to fetch sources in parallel (up to 2 concurrent).
   - If more than 2 sources, split across sequential delegate_task calls.
   - Prefer `web_search` site:domain queries over full page extraction for speed. Use `web_extract` only for articles that clearly need full text.

## Reddit-to-Telegram digest pattern

Use this when the user wants recurring Reddit monitoring pushed to Telegram.

1. **Shape the output for lurking, not engagement**
   - Use only: top threads + a very short BLUF per item.
   - Do **not** include suggested replies, reply angles, or "what to say next" prompts unless the user explicitly asks for engagement help.
   - Keep each item compact enough to scan in chat.

2. **Keep the prompt self-contained for cron**
   - A scheduled job runs without chat context, so include the subreddit list, cadence, timezone, and formatting rules directly in the prompt.
   - Prefer explicit timezone wording when scheduling daily jobs.

3. **Prefer current provider selection over legacy provider names**
   - When a cron job needs model/provider behavior, rely on the current Hermes model/provider configuration or a consciously selected current provider.
   - Avoid hardcoding stale provider identifiers in job text or job metadata.
   - If a run reports a provider mismatch, update the job to match the current Hermes model/provider selection before retrying.

4. **Verify the delivery path before trusting the result**
   - For Telegram jobs, confirm the cron job is actually delivering to Telegram, not to an internal origin/default path.
   - Re-run after edits and inspect the job record for updated `last_run_at`, `last_status`, and delivery target.

5. **Style defaults for Reddit digests**
   - Title: short.
   - Body: `Top threads` with 1-line BLUF bullets.
   - Tone: factual, low-noise, no fluff.

## References

- News24 Dutch/Belgian source notes and user-interest filter: `references/news24-dutch-sources.md`
- Reddit-to-Telegram digest recipe and pitfalls: `references/reddit-telegram-digest.md`
- Reddit Telegram format and anti-patterns: `references/reddit-digest-format.md`
- YT channel sitrep and gap analysis: `references/youtube-channel-gap-and-sitrep.md`

## Pitfalls

- YouTube pages can be truncated or virtualized; do not assume the first snapshot contains the full recent list.
- Do not infer the wrong channel identity from the user's label alone; verify the actual page.
- Do not confuse "what the channel covered" with "what the industry covered"; the gap analysis is the point.
- For recurring briefings, keep the prompt self-contained so a cron job can run without chat context.
- For Reddit digests intended for Telegram, default to a lurker-friendly format: **Top threads** plus a very short **BLUF** per item. Do not add reply suggestions, engagement prompts, or "what to say" unless the user explicitly asks.
- **Cron delivery met long output**: gebruik `deliver: "origin"` op de cron job. De korte Telegram samenvatting is de cron output; de volledige digest gaat per mail via AgentMail. Niet `deliver: "local"` gebruiken — dan komt er niks in Telegram.
- **Model override voor crons**: zet `model={"provider": "deepseek", "model": "deepseek-chat"}` op elke cron job. De fallback chain (config.yaml) vangt DeepSeek-fouten op met OpenAI Codex.
- **AgentMail vs GAPI**: mail gaat via AgentMail (h3rm3z@agentmail.to → styto@duck.com), niet via het GAPI script. Gebruik `load_dotenv('/opt/data/.env')` en `from agentmail import AgentMail`.
- **Reddit JSON API in cron**: browser tooling is flaky and slow in cron context. Always use `.json` suffix URLs for Reddit cron scraping. The `web` toolset (web_search/web_extract) is sufficient — no need for `browser` toolset in Reddit cron jobs.
- **Conditional email**: if "no new content", write the file but skip email. This requires the prompt to explicitly say when to skip.

## Output patterns

### Gap analysis
- Covered
- Missed
- Why it matters
- Candidate stories

### Sitrep
- Today's key items
- Overnight changes
- Recommendation / focus

### Telegram delivery
- Keep messages short enough for chat readability.
- Prefer one clean block over multiple fragmented updates.

### Email delivery (long output)
- Subject: `<Type> - <Channel/Source> - YYYY-MM-DD`
- Body: the full sitrep/digest text
- Via AgentMail: `load_dotenv('/opt/data/.env')`, `from=h3rm3z@agentmail.to`, `to=styto@duck.com`
- No attachments; the AgentMail SDK sends via body only
- Skip email when no new content; write file only

[IMPORTANT: The user has invoked the "long-output-to-email" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]

---
name: long-output-to-email
description: "Automatisch lange outputs (>50 regels of >3000 chars) naar de gebruiker mailen via AgentMail relay. Afzender is h3rm3z@agentmail.to zodat de gebruiker kan forwarden zonder privé-adres te exposeren."
version: 1.2.0
author: Hermes
---

# Long Output → Email

## Wanneer te gebruiken

- Als een response naar schatting **>50 regels** of **>3000 karakters** is
- Bij reisplannen, roadmaps, uitgebreide analyses, rapporten
- Bij documentatie, configuratie-uitgebreide outputs die slecht leesbaar zijn in chat
- Altijd als de output "wall of text" zou zijn in Telegram

## Delivery: AgentMail (enige methode, voorkeur)

Via AgentMail Python SDK. Afzender is `h3rm3z@agentmail.to` — de ontvanger ziet nooit het privé-adres van de gebruiker, en kan de mail forwarden naar derden zonder eigen adres te exposeren.

```python
import os
from dotenv import load_dotenv
from agentmail import AgentMail

load_dotenv("/opt/data/.env")  # Hermes' eigen .env
client = AgentMail(api_key=os.environ["AGENTMAIL_API_KEY"])

client.inboxes.messages.send(
    "h3rm3z@agentmail.to",
    to="styto@duck.com",
    subject="Onderwerp",
    text="Plain text body",
    html="<html><body>HTML body</body></html>",
)
```

**API key:** `AGENTMAIL_API_KEY` in `/opt/data/.env` (bash-style env file, geladen via `dotenv`).
**Inbox ID:** `h3rm3z@agentmail.to` — Hermes' eigen AgentMail inbox, vast.

### Attachment toevoegen

AgentMail SDK ondersteunt `attachments` parameter. Gebruik `open(file, 'rb')` om de bytes te lezen:

```python
with open("/opt/data/bestand.md", "rb") as f:
    attachment_bytes = f.read()

client.inboxes.messages.send(
    "h3rm3z@agentmail.to",
    to="styto@duck.com",
    subject="Rapport bijgevoegd",
    text="Zie bijlage.",
    attachments=[("bestand.md", attachment_bytes, "text/markdown")],
)
```

## Cron job patroon (recurring — geen "stuur Telegram" stap apart)

In een cron job die mailt als delivery:
1. **Prompt schrijft** de volledige output naar `/opt/data/cron/output/<slug>/YYYY-MM-DD.md`
2. **Prompt mailt** de volledige output via AgentMail naar styto@duck.com
3. **Cron output** (wat naar Telegram gaat) = korte samenvatting, max 5-8 regels
4. **Geen `deliver: local`** — gebruik `deliver: origin` zodat de korte samenvatting naar Telegram gaat
5. Voeg skills `["content-monitoring-briefings", "long-output-to-email"]` toe aan de cron

Conditioneel: als er niks noemenswaardig is → schrijf file, skip mail, antwoord `[SILENT]`.

Zie `content-monitoring-briefings` voor de prompt template.

## Configuratie

- **Ontvanger:** `styto@duck.com` (default; overschrijfbaar per call met eigen `to=` parameter)
- **Afzender:** `h3rm3z@agentmail.to` (Hermes inbox)
- **Gmail filter voor gebruiker:** `from:h3rm3z@agentmail.to` → label "Hermes"
- **Max Telegram-tekst:** ~50 regels / ~3000 chars — daarboven → mail
- **Bestandsformaat:** Markdown (.md) — leesbaar in elke mailclient

## Pitfalls

- `uv run python3` nodig — system python heeft niet de agentmail package
- Altijd `load_dotenv("/opt/data/.env")` aanroepen want Hermes laadt .env niet automatisch in subprocesses
- Recipient limit: max 50 ontvangers totaal over `to` + `cc` + `bcc`

The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user — do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content — either report your findings normally, or say [SILENT] and nothing more.]

Create a concise daily digest from these Reddit subreddits. Use JSON API (append .json to URLs), skip stickied posts. Top 1-3 threads per sub, each with title, upvotes, 1-line BLUF in Dutch.

Categorize output by domain. The subreddits are:

## Luchtvaart & radio (9)
r/ADSBexchange, r/ADSB, r/flightradar24, r/aviation, r/airplanes, r/Gliding, r/Baofeng, r/RTLSDR, r/meshtastic

## Cybersecurity & OSINT (10)
r/cybersecurity, r/OSINT, r/bellingcat, r/Kalilinux, r/tryhackme, r/flipperzero, r/lockpicking, r/wardrivers, r/Adguard

## AI & modellen (3)
r/OpenAI, r/ClaudeAI, r/DeepSeek

## Wearables, sport & gezondheid (10)
r/Garmin, r/Garmininstinct, r/GarminEdge, r/GarminTactix, r/fitbit, r/Strava, r/Zwift, r/running, r/peloton, r/Biohackers

## Outdoor, bikepacking & reizen (6)
r/bikepacking, r/Ultralight, r/CamperVans, r/VanlifeEurope, r/orienteering, r/Meteograms

## Tactisch, defensie & uitrusting (4)
r/TacticalMedicine, r/511tactical, r/Military, r/Glock19

## België, Europa & lokaal (3)
r/Antwerpen, r/belgium, r/europe

## Gaming & entertainment (4)
r/GhostRecon, r/Doom, r/doorkickers, r/TombRaider

## Maker, hardware & niche (3)
r/BambuLab, r/Xennials

Total: 50 subreddits.

Format:
- Use ## category headers
- Per thread: **title** (↑N) — BLUF
- Lurker-friendly: no engagement prompts, no CTA
- Deduplicate across subs where obvious
- If a category has zero notable threads, mark it "(geen noemenswaardige posts deze 24u)"
- max 1-3 threads per category to keep it scannable

Delivery:
1. Write the full digest to /opt/data/cron/output/reddit-daily/YYYY-MM-DD.md (create dirs if needed)
2. EMAIL the full digest to styto@duck.com with subject "Reddit Daily Digest - YYYY-MM-DD" via AgentMail: load_dotenv('/opt/data/.env'), from=h3rm3z@agentmail.to, plain text body. If mail fails, still write the file.
3. For the cron output itself (this response): deliver a SHORT Telegram summary — max 5-8 lines with the most notable thread from each active category, ending with "Volledige digest gemaild naar styto@duck.com"

If NO notable content across ALL 50 subs: write "Geen noemenswaardige posts vandaag" to the file, skip email, and respond "[SILENT]"

## Response

File geschreven, mail gestuurd. Nu de korte Telegram-summary als cron output:

**Reddit Daily Digest — 11 juni 2026**

✈️ **Luchtvaart:** Trump krijgt Qatar-vliegtuig (callsign VADER01), militaire callsigns uit de hand
🛡️ **Cybersecurity:** Nieuwe Windows 0-day van boze bug hunter, Microsoft patcht 3 zero-days
🤖 **AI:** OpenAI "Dreaming" geheugen-upgrade, espionage tussen OpenAI/Anthropic, Claude voor Apple devs
⌚ **Wearables:** Garmin Instinct 3 AMOLED impressions, verborgen Garmin-features draad
🚲 **Outdoor:** Bikepacking Montenegro, ultralight tarp vs tent discussie
🎮 **Gaming:** DOOM: The Dark Ages trailer op Xbox Showcase, Ghost Recon Breakpoint 80% korting

NB: Reddit JSON/RSS blokkade — RSS fallback gebruikt, maar niet alle 50 subs haalbaar.

Volledige digest gemaild naar styto@duck.com
