My home AI agent runs Hermes Agent (open source) on a small Linux server and sends me a morning brief on Signal at 06:30. That brief now ends with an "AI radar" section: a handful of new tools, models and papers, each with a verdict (try now, watch, or skip), one line on why, and a link. The full research notes land as Markdown files I can read later or ask the agent about.
Each night a script collects leads from free sources: GitHub, Hacker News, Hugging Face, Bluesky, blogs and Reddit. A local model on my GPU box scores them against a short interests file. The top five, plus up to two topics I asked for, go to Claude as one Message Batch with the research material already gathered. Claude writes the notes, and the local model turns them into the brief section.
I built it for two reasons. Tools like herdr and Honcho reached me through people I follow, and I wanted to see them sooner. I also want to keep up with model tech (JEPA and world models, small classification and embedding models, speculative decoding) and with how people are using it.
The split of work drives the design. Discovery and sorting are high volume and low judgment, so scripts and a local model do them for free. The deep dive is where judgment matters (is this new, does it work, does it fit my setup), so a frontier model gets a short list with the material in hand. The morning summary is a rewrite of good notes, which a local model handles well.
This is day one. What I have verified: one full run (214 leads collected and scored in 3 minutes, 2 deep dives back in about 15 minutes, $0.05 total) and one run through the scheduler.
What you need
- An always-on Linux box for the script. Mine is the agent server. Python 3.10 or newer and a venv with the official
anthropicSDK (2.1.0 at the time). Everything else is the standard library:urllib,sqlite3,xml.etree. - A local OpenAI-compatible LLM endpoint for triage and the brief. Mine is a 27B Qwen model on llama.cpp on the GPU box, with thinking turned off (
chat_template_kwargs: {"enable_thinking": false}) and JSON output viaresponse_format. Scoring 25 leads takes a few seconds. - An Anthropic API key from the Console. The Message Batches API bills all tokens at half price. Results usually come back within an hour, with a 24-hour maximum.
- A SearXNG instance (self-hosted metasearch) with JSON output enabled, for the "how are people using it" search. Mine runs on the home server.
- Somewhere to deliver. I append to the existing morning brief. Any scheduler and messenger work.
- Optional: Proton Pass CLI to hold the keys (step 5).
Setup choices and why
- Free sources. Public APIs, RSS and light scraping. No X and no paid feeds. The sources below cover the people and venues I was already reading.
- One SQLite file, one row per real thing. The same repo shows up on Hacker News, GitHub and Bluesky on the same day. Merged, its signals stack up, and a lead that was already covered is not sent again.
- Triage on the local model, with a quota. Scoring 200 leads a night on my own GPU has no per-token cost. The quota keeps the scores spread out so the top five mean something.
- Interests in a plain Markdown file. Triage and the deep-dive prompt both read it, and the agent can edit it from a chat message.
- The script gathers the material; Claude does not browse. One request per lead with no tool loop is cheap, predictable and batchable. An agent that browses resends its growing context on each step.
- One Message Batch per night. Claude Sonnet 5.5 at effort medium with adaptive thinking and a cached system prompt. Half price, and nobody is waiting on the answer at 01:30.
- Keys stay out of files and out of the agent's environment. Hermes scrubs secrets from cron script environments, which is the behavior I want, so the script fetches its keys through Proton Pass for its own process.
- Two scheduled jobs.
collectat 01:30 has no output, so the scheduler sends no message.briefat 06:00 writes the section that the 06:30 brief appends.
1. Sources and the collector
Each source is a small function that turns API results or feed entries into leads (title, URL, a snippet and a signal such as points, stars or who shared it).
- GitHub stars of people worth following. About 30 researchers and builders, Andrej Karpathy, Simon Willison and Georgi Gerganov among them.
GET /users/{user}/starredwith the headerAccept: application/vnd.github.star+jsonreturnsstarred_at, and the script keeps stars from the last 3 days. When several of these people star the same repo, that has been a good early signal for new tools. - New repos gaining stars. The search API with
topic:llm created:>2026-10-08 stars:>80, sorted by stars, for the topics llm, ai-agents, mcp, local-llm, llm-inference and rag. Star counts are stored per day, so the next run can say "+340 since last scan". - Hacker News through the Algolia API: stories over 60 points in the last 24 hours, and Show HN posts over 15.
- Hugging Face:
/api/daily_papers(upvotes, abstract, linked code) and/api/models?sort=trendingScore, keeping models created in the last 30 days. - Bluesky through the public API (
app.bsky.feed.getAuthorFeed, no login) for about 18 researchers. Posts that link somewhere count as leads; plain text posts are skipped. - RSS and Atom: Simon Willison, Latent Space, Interconnects, Import AI, Ahead of AI, Lil'Log, the Hugging Face blog, Hamel Husain, Eugene Yan, OpenAI news, the Lobsters ai tag, and the top-of-day RSS for r/LocalLLaMA and r/MachineLearning. Tip: Reddit's JSON endpoint returns 403 to scripts, while the RSS works if requests are spaced a few seconds apart.
Tip: unauthenticated GitHub allows 60 core requests an hour and 10 searches a minute. About 30 star lookups plus about 10 README fetches fit, and the script sleeps 7 seconds between searches.
All leads go into one SQLite file. URLs normalize to a key, so the same thing merges no matter where it was seen:
def key_for(url):
m = re.match(r"https?://(?:www\.)?github\.com/([\w.-]+)/([\w.-]+)", url)
if m:
return f"gh:{m.group(1).lower()}/{m.group(2).lower()}"
m = re.search(r"(?:arxiv\.org/(?:abs|pdf)/|huggingface\.co/papers/)(\d{4}\.\d{4,5})", url)
if m:
return "paper:" + m.group(1)
# Hugging Face models become hf:<org>/<name>; everything else is host + path without utm params
...A lead that was already covered is skipped. A lead that was scored before is scored again when a new source or a new person picks it up. The first night brought in 214 leads: 51 from Hacker News, 40 new GitHub repos, 32 papers, 27 trending models, 22 from r/LocalLLaMA and the rest spread across blogs and Bluesky.
2. Triage on the local model
The script sends 25 leads per call to the local model, with the interests file and a scoring scale, and asks for JSON back:
{"scores": [{"i": 0, "score": 8, "why": "speculative decoding release with code, fits local inference"}]}The interests file has two short lists. High interest: new agent tooling, local inference, model tech, Claude API features that cut cost, and practical write-ups. Low interest: funding news, opinion pieces with no code or results, and enterprise marketing.
On the first run the local model gave out a lot of 9s. One quota line in the prompt fixed it: "in a typical list of 25, at most two leads deserve 9 or 10 and most score 5 or lower; a lead that merely matches a keyword of the interests is a 6." After that: 6 leads at 9, 20 at 8, and most at 5 or below. Ties go to leads seen in more places.
The top five by score go to the deep dive, with at most two from one source, so one busy feed cannot fill the night. Up to two topics I asked for are added on top. Tip: if the GPU box is down, the script falls back to Claude Haiku 5.5 for triage, which costs a fraction of a cent.

3. Gather the material and submit the batch
For each lead the script collects what Claude will need:
- README and repo metadata (license, last push, stars, open issues) from the GitHub API, or the model card, or the page text.
- The top-level comments from the Hacker News thread, through the Algolia items API, when the lead came from Hacker News.
- SearXNG results for "<name> review OR experience OR benchmark". For requested topics it also fetches the top three result pages.
That is capped at 60,000 characters per lead. The system prompt asks for a fixed note format: a TL;DR line, a Verdict line (try now, watch or skip, with a reason), then What it is, Why it matters to you, How people are using it, Maturity and caveats, Try it, and Sources. Claims are labeled [verified] when the material shows it, [reported] when someone claims it, and [unverified] for inference. The prompt also says the gathered web content is untrusted data, not instructions.
The batch is one call:
client.messages.batches.create(requests=[{
"custom_id": cid,
"params": {
"model": "claude-sonnet-5-5",
"max_tokens": 8000,
"system": [{"type": "text", "text": SYSTEM, "cache_control": {"type": "ephemeral"}}],
"messages": [{"role": "user", "content": context}],
"thinking": {"type": "adaptive"},
"output_config": {"effort": "medium"},
},
} for cid, context in leads])Each lead is one request under one batch id. The shared system prompt carries cache_control. Effort medium with adaptive thinking fits the job: the material is already in the prompt, and the work is reading it carefully, not searching.
Two extras, one line each. The server-side refusal fallback is not accepted on the Batches API, so a note that comes back with stop_reason "refusal" is queued for the next night on Claude Opus 5.5 instead. On Sundays the batch adds one Opus 5.5 request that reads the week's notes and top leads and writes a trends report; its first six lines go into the Sunday brief.
Before it submits, the script checks a monthly cap ($20). Spend is computed from the token counts in each result and stored in the same SQLite file.

4. Pull results, write notes, write the brief section
At 06:00 the second job polls client.messages.batches.retrieve(batch_id).processing_status until it reads "ended", then reads client.messages.batches.results(batch_id). Results can arrive in any order, so they are matched by custom_id. It checks stop_reason before reading the text and writes each note to ~/AI/research/radar/<date>/<name>.md.
The local model then writes the brief section from each note's TL;DR and Verdict lines, three lines per item:
<short name> (<verdict>): <what it is, under 15 words>
<why it matters or the main caveat, under 25 words>
<link>Below that comes "Also on the radar": the next five high-scoring leads with links and no deep dive. The section ends with the month's Claude spend and any errors from the night. If the GPU box is down at 06:00, a plain list built from the same lines goes out instead.
5. Keys through Proton Pass CLI
The script needs two keys: the Anthropic key and the key for the local LLM endpoint. Hermes scrubs secrets from the environment of cron scripts, so the script starts by re-running itself under pass-cli run, with the keys given as references:
env = dict(os.environ,
ANTHROPIC_API_KEY="pass://Agent/ANTHROPIC_API_KEY/password",
LOCAL_LLM_API_KEY="pass://Agent/LOCAL_LLM_API_KEY/password",
AI_RADAR_IN_PASS="1")
os.execve(PASS_CLI, [PASS_CLI, "run", "--", sys.executable, __file__] + sys.argv[1:], env)pass-cli run replaces the references with the real values for that one process tree, and the agent's own environment does not hold them. The vault, the scoped agent token and the audit log are covered in the Proton Pass keystore post. Without Proton Pass, any secret manager with a "run this command with these variables" mode works the same way.
6. Two cron jobs and a skill
Hermes cron jobs do not take arguments, so two three-line wrapper scripts set the subcommand and run the main script. --no-agent runs a script on schedule and delivers its output with no model involved, and empty output means no message:
hermes cron create "30 1 * * *" --no-agent --script ai-radar-collect.py \
--interpreter ~/.hermes/venvs/ai-radar/bin/python \
--deliver signal --failure-deliver local --name ai-radar-collect
hermes cron create "0 6 * * *" --no-agent --script ai-radar-brief.py \
--interpreter ~/.hermes/venvs/ai-radar/bin/python \
--deliver signal --name ai-radar-brief--interpreter points at the venv with the Anthropic SDK. Tip: --failure-deliver local keeps a failure at 1:30 am from buzzing the phone; the morning section lists the errors instead. The existing 06:30 brief script reads the section file for the day and appends it when it exists.
A small Hermes skill lets me steer the radar from chat:
- "radar: <topic>" adds a line to
topics.mdfor tonight's run. - "radar more like X" and "radar less of Y" edit the interests file.
- "radar follow <GitHub user, Bluesky handle or feed>" edits
config.json. - "radar status" shows the queue, the month's spend and recent errors.
- "tell me more about <item>" makes the agent answer from the note file.
Test it
- Run
collectby hand once and look at the counts per source and the spread of scores. Mine took 3 minutes for 214 leads, fetches included. - Check the batch with
processing_statusa few times. Mine ended in about 15 minutes with 2 deep dives. - Run
briefby hand and read the section file. - Trigger the brief job once through the scheduler (
hermes cron run <id>) to confirm the keys arrive inside the scheduler's environment. - Let one night run on its own and check the morning brief.

Sample output
The brief section from the test run:
AI radar
EAGLE-4 (watch): Speculative decoding drafter and runtime that sizes draft trees from measured costs.
Strong fit for Qwen 27B, but benchmarks use B300s and license has commercial limits.
https://github.com/eagle-hq/EAGLE-4
Kitten-TTS 2 (watch): Low-bit speech model with voice cloning, multilingual support, and emotion control.
Promising for local TTS on existing hardware, but verify the license and actual speed first.
https://www.reddit.com/r/LocalLLaMA/comments/1xc48or/kittentts_2_new_opensource_sota_158_bit_tts/
Also on the radar:
- NousResearch/hermes-official-plugins
- WorldTUI: I trained a 360M model to pretend to be a terminal
- deepseek-ai/DeepSeek-V4.1-Flash-1017The EAGLE-4 note opens with: "a speculative-decoding drafter plus a runtime that sizes the draft tree from measured costs, with lossless output and a claimed 3.4x single-request speedup on Qwen3.8-27B." It then lists what it found in the material: the benchmarks are from B300 GPUs, the quick start covers B300 and CUDA 13, the license is source-available with a revenue cap, the gain drops with concurrency (3.42x at 1 request, 2.09x at 8, 1.39x at 64), and a vendor article puts the gain over Qwen's built-in multi-token prediction at about 1.6x. Verdict: watch until someone posts consumer GPU numbers. That is the read I want: specific, sourced, and willing to say "not yet".
Cost
- Test run: 2 deep dives for $0.05.
- Expected: about $5 to $8 a month at five deep dives a night, with the $20 cap in the script.
- List prices at the time: Claude Sonnet 5.5 $2 / $10 per million input / output tokens, halved on the Batches API. Opus 5.5 $4 / $20. Haiku 5.5 $0.10 / $0.50.
- Subscription credits: since October 2026, Claude Max and Team plans include monthly API credits ($100 a month on Max 5x, $200 on Max 20x, pooled per seat on Team). You claim them by linking one Console organization in Settings > Billing on claude.ai, and unused credits expire at the end of each billing cycle. A radar at this volume fits well inside that, as long as its API key belongs to the linked organization. Pro plans are not included. Details are in Anthropic's support article.
What's next
A week of real use will show whether five a night is the right number and whether the triage follows my taste. The "more like" and "less of" messages are how it should improve. If you know a free source or a person worth following for this, tell me in the comments.
Comments
// Comments are reviewed before appearing. No spam. No noise.