<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MediBlackSand</title>
    <description>The latest articles on DEV Community by MediBlackSand (@mediblacksand_f0ea36c53fb).</description>
    <link>https://dev.to/mediblacksand_f0ea36c53fb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3990079%2Fc77a9545-3144-4249-bb3c-05314e6d981d.png</url>
      <title>DEV Community: MediBlackSand</title>
      <link>https://dev.to/mediblacksand_f0ea36c53fb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mediblacksand_f0ea36c53fb"/>
    <language>en</language>
    <item>
      <title>I Was About to Cancel Claude. Now Gemini Is Rate-Limiting Me Out of My Own Plan.</title>
      <dc:creator>MediBlackSand</dc:creator>
      <pubDate>Thu, 25 Jun 2026 06:02:05 +0000</pubDate>
      <link>https://dev.to/mediblacksand_f0ea36c53fb/i-was-about-to-cancel-claude-now-gemini-is-rate-limiting-me-out-of-my-own-plan-215g</link>
      <guid>https://dev.to/mediblacksand_f0ea36c53fb/i-was-about-to-cancel-claude-now-gemini-is-rate-limiting-me-out-of-my-own-plan-215g</guid>
      <description>&lt;h2&gt;
  
  
  The Almost-Cancellation
&lt;/h2&gt;

&lt;p&gt;About six months ago I was one renewal away from cancelling Claude. Not because it got worse, because I just wasn't opening it. Rate limits I kept hitting on the rare day I did, and a Gemini 3 Pro that had just landed and felt better at almost everything I cared about: Python, JavaScript for the artistic coding side projects (a whole separate post, another day), general "what can this thing actually do" exploring.&lt;/p&gt;

&lt;p&gt;Gemini 3 Pro earned the roughly 30 AUD a month on its own. Add the Drive storage I was already half-paying for elsewhere and the image and video generation that was genuinely solid, not a tacked-on afterthought, and the upgrade looked obvious. I downgraded Claude in my head before I'd even opened the app to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then Something Shifted
&lt;/h2&gt;

&lt;p&gt;Sometime this year that stopped being true. Not Gemini getting worse, Claude getting sharply better: coding accuracy, front-end output, MCP, agent behavior, all of it improving in a way I noticed week to week instead of release to release.&lt;/p&gt;

&lt;p&gt;I started running the same prompts through both, mostly out of curiosity at first. Then out of habit, because I kept trusting Claude's answer more often than not. Same task, same wording, and Claude's version was the one I'd actually ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Downgrade
&lt;/h2&gt;

&lt;p&gt;So I went the other way on Gemini. Dropped down to Google AI Plus, the cheap tier, around 15 AUD a month. I wasn't using it daily anymore, and I didn't want to keep paying full price for a tool that mostly sat there.&lt;/p&gt;

&lt;p&gt;These days Gemini is what I open for googling instead of the traditional "googling", or for the smaller stuff I don't want eating into my Claude usage. Nothing heavy. Nothing I'd call real work.&lt;/p&gt;

&lt;p&gt;And even at that, low-stakes level, I'm getting a lot more "I'm having a hard time fulfilling your request, can I help you with something else instead?" on requests that aren't unusual at all. Just now, checking back in to write this, I've lost access to the better model completely and landed in a flat rate limit. Not slower. Just off.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Actually Is
&lt;/h2&gt;

&lt;p&gt;I'm not saying Gemini is bad. Six months ago I'd have written the exact opposite post about Claude, and meant it just as much. What I'm noticing is smaller and more annoying than "which one wins": 15 AUD a month bought me a tool I can poke at, not one I can actually lean on. That's not really a capability problem. That's the cheap tier telling you, politely, that you're not the priority.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;I didn't downgrade because Gemini got worse. I downgraded because I wasn't using it enough to justify the higher plan. But the cheap tier doesn't meet you at "occasional and light," it meets you at "barely worth keeping." Pay less and you don't just get less model, you get less patience for using it at all.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>claude</category>
      <category>gemini</category>
      <category>opinion</category>
    </item>
    <item>
      <title>I Built Two AI Tools. The Second One Told Me How I Should Be Learning AI.</title>
      <dc:creator>MediBlackSand</dc:creator>
      <pubDate>Thu, 25 Jun 2026 01:46:26 +0000</pubDate>
      <link>https://dev.to/mediblacksand_f0ea36c53fb/i-built-two-ai-tools-the-second-one-told-me-how-i-should-be-learning-ai-5el0</link>
      <guid>https://dev.to/mediblacksand_f0ea36c53fb/i-built-two-ai-tools-the-second-one-told-me-how-i-should-be-learning-ai-5el0</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;TeachSim taught me LangGraph because the bot had to actually work, with real conversations running through it. GitHub Digest taught me about silent failure modes the same way, by breaking quietly until I went and figured out why. Both stuck because I needed the concept to function, not because I sat down and studied it first.&lt;/p&gt;

&lt;p&gt;I already tried the conventional route once. (It probably applies to everything I do and learn throughout my life.) I opened Anthropic's own intro course for Claude Code, the official one, and gave up a few lessons in having retained almost nothing. Nice material, no stakes, nothing to actually break, so nothing stuck.&lt;/p&gt;

&lt;p&gt;I want to go deeper into AI engineering now, not just orchestration around an API. Fast.ai for the fundamentals, then something heavier for the practitioner-level material. And I caught myself about to repeat the exact same pattern: open a course, start at lesson one, hope the urgency turns up eventually.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Discovery
&lt;/h2&gt;

&lt;p&gt;GitHub Digest is supposed to surface tools I wouldn't find by scrolling GitHub Trending. It's already done that for real: RTK, &lt;code&gt;sst/opencode&lt;/code&gt;, &lt;code&gt;playwright-mcp&lt;/code&gt;, and a course called AI Engineering From Scratch all came out of the pipeline, not a deliberate search.&lt;/p&gt;

&lt;p&gt;The course is the part that actually got to me. I've shipped two production-ish projects on Claude Code and OpenCode, and the entire depth of my knowledge of either tool is "enough slash commands and CLAUDE.md conventions to get something running." I've never deliberately learned MCP, skills, subagents, hooks, plugins, or checkpoints. I just use whichever tool happens to work that day.&lt;/p&gt;

&lt;p&gt;Stacking real ML fundamentals on top of that felt like a bad idea. I'd be fighting the tools and the material at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;Two machines, two networks I switch between. Claude Desktop with filesystem access is the constant supervisor on both: it reads the actual files, checks claims against source, catches scope creep before anything ships. OpenCode, tunneled to a small VPS running DeepSeek through OpenRouter, and the Claude Code VS Code extension are the interchangeable workers that do the typing.&lt;/p&gt;

&lt;p&gt;I'd been treating both workers as interchangeable without understanding what makes them different underneath. That's the actual gap.&lt;/p&gt;

&lt;p&gt;The supervisor role isn't theoretical, either. Yesterday's task started with the usual pre-flight check: start the tunnel, confirm it's up, then begin. Partway through, OpenCode, running on DeepSeek, killed the tunnel itself and took the whole pipeline down with it mid-task. Claude Code hasn't done anything like that so far. I've now got a "don't touch the tunnel process" rule that only applies to OpenCode, which is a guardrail I built by getting burned, not by reading ahead to Phase 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;Eight phases was designed pulling from three resources, claude-howto, Anthropic Academy's official course catalog, and opencode.school, none of those orderings made sense to follow as is so the curriculum runs on its own sequence instead:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Theme&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Foundations (a self-check, not a lesson — already know this)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;MCP — extend what the agent can reach&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Skills — formalize what it now knows how to use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Subagents — split work across multiple agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Hooks — add guardrails before something destructive happens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Plugins — package it all into one install&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Checkpoints — undo a bad session without losing real work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Final Results&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each phase, I get to pick: solve a real problem in one of my live projects, or build against a notable open-source project picked because it's a strong production example, not a toy demo. For Phase 1, the real-project version is wiring GitHub's MCP server into GitHub Digest instead of hitting the REST API directly. The open-source version is installing &lt;code&gt;playwright-mcp&lt;/code&gt;, Microsoft's own browser-automation server, and pointing it at something real.&lt;/p&gt;

&lt;p&gt;I haven't done either yet. This is a design brief for a course I'm about to do slowly. The rule I'm holding myself to is that a phase isn't done when I've read about it, it's done when it produces a real fix in one of my actual projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why MCP First
&lt;/h2&gt;

&lt;p&gt;It's the one concept every later phase either uses or assumes you've used. Skills often wrap MCP calls. Subagents delegate to MCP-equipped agents. Hooks govern what an MCP server is allowed to touch. Start there and everything later has something concrete to point back at.&lt;/p&gt;

&lt;p&gt;It's also the most demonstrable. Watching an agent drive a real browser for the first time is something you &lt;em&gt;see&lt;/em&gt; happen. A permission setting from Phase 0 is correct and completely invisible. If I want this to survive contact with my own attention span, the visible payoff has to come first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Coming Next
&lt;/h2&gt;

&lt;p&gt;Skills, subagents, hooks, plugins, checkpoints, in that order, against real projects wherever I can manage it. After that's the actual point: Fast.ai, then the heavier material, with the tools already out of the way instead of competing for attention with the harder stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;The bet is that learning the tools you already use makes you slower before it makes you faster. I could open OpenCode right now and ship something without understanding half of what's available to it. Spending real time on this first is a trade: less momentum this month for not relearning the same tool friction later, while I'm meant to be thinking about something harder. I'll find out if that's the right call once I've actually started.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is part of an ongoing series: TeachSim, GitHub Digest, and now the plan for the tool-mastery work sitting underneath the next phase of learning AI engineering properly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find me on GitHub: &lt;a href="https://github.com/mediblacksand" rel="noopener noreferrer"&gt;github.com/mediblacksand&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>opencode</category>
      <category>learning</category>
    </item>
    <item>
      <title>I Built a Personal Intelligence System That Curates GitHub and News for Me — Here's How It Works</title>
      <dc:creator>MediBlackSand</dc:creator>
      <pubDate>Mon, 22 Jun 2026 05:40:18 +0000</pubDate>
      <link>https://dev.to/mediblacksand_f0ea36c53fb/i-built-a-personal-intelligence-system-that-curates-github-and-news-for-me-heres-how-it-works-5fd4</link>
      <guid>https://dev.to/mediblacksand_f0ea36c53fb/i-built-a-personal-intelligence-system-that-curates-github-and-news-for-me-heres-how-it-works-5fd4</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Personal Intelligence System That Curates GitHub and News for Me — Here's How It Works
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A personal intelligence system that reads the news and scrapes GitHub for you, curates it with an LLM, and delivers it to your phone before you've finished your coffee. No dashboard. No login. Just three briefings, on a schedule you set.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I'd already built TeachSim, a multi-agent system running on an LLM via OpenRouter, delivered entirely through Telegram, hosted on a budget VPS. Once that stack existed, the obvious question was what else it could power. The quickest win turned out to be information consumption itself.&lt;/p&gt;

&lt;p&gt;The actual itch was how I was consuming news. Google had been pushing me daily feeds for years: algorithmically chosen, entirely passive. I never decided what showed up, I just scrolled what arrived. I wanted to try the opposite, same infrastructure, a completely different job. An LLM doing the choosing instead of an engagement optimized feed, for both the news I read and the open-source ecosystem I found increasingly interested to keep a tab on day to day.&lt;/p&gt;

&lt;p&gt;That second half turned out to matter as much as the first. I don't have time to manually browse GitHub Trending every day, and Trending rewards absolute popularity over genuine novelty. The bet was that an LLM scanning broadly and judging by relevance rather than star count would surface things I'd never have found otherwise.&lt;/p&gt;

&lt;p&gt;It has. Real tools the pipeline has actually surfaced for me, not things I went looking for: &lt;a href="https://github.com/rtk-ai/rtk" rel="noopener noreferrer"&gt;RTK&lt;/a&gt;, &lt;code&gt;sst/opencode&lt;/code&gt;, and &lt;a href="https://aiengineeringfromscratch.com/" rel="noopener noreferrer"&gt;AI Engineering From Scratch&lt;/a&gt;, among others. That alone justified building it: the self-directed version surfaces tools I'd never have found through a popularity-ranked feed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What GitHub Digest Is
&lt;/h2&gt;

&lt;p&gt;GitHub Digest is a personal automation system that delivers three scheduled briefings straight to Telegram:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;morning news briefing&lt;/strong&gt;: dozens of RSS feeds across world events, technology, AI research, and a few specialist categories, curated down to a handful of stories that fed into Deepseek V4 Flash and judged actually worth my attention that day.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;GitHub Discovery digest&lt;/strong&gt;: a wide net of GitHub Search API queries surfacing repos I haven't seen before, tiered into "gem" (brand new, low stars, high velocity), "exploding" (star count accelerating fast), and "hot" (established but trending this week).&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;weekly Momentum briefing&lt;/strong&gt;: tracks a personal watchlist of tools over time and reports what changed, in plain language rather than a star-count delta.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus an on-demand command layer, so I can pull any of the three manually from my phone, check system health, or manage my watchlist without touching a terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sources (RSS feeds / GitHub Search API / personal watchlist)
            │
            ▼
       Scrapers (per-source rate limiting, per-feed age windows)
            │
            ▼
       Analyzers (LLM curation — picks what's actually worth surfacing)
            │
            ▼
       Delivery (Telegram bot, chunked for plain-text limits)
            │
            ▼
   Always-on command listener (on-demand pulls, watchlist management)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three independent scrape-to-analyze-to-deliver pipelines, each on its own schedule, sharing a single delivery layer and a single listener process. All running on a single-core, 1GB budget VPS, which turns out to be the single biggest constraint shaping every other decision in this build.&lt;/p&gt;

&lt;p&gt;The curation step runs through an OpenRouter-routed LLM call: currently a fast, cheap model chosen specifically because curation needs consistency and low cost at high frequency (three runs a day, every day) rather than frontier-level reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the Hood
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The model's real output isn't always where you'd expect it, and this one fails silently.&lt;/strong&gt; The LLM doing curation sometimes returns its actual content in a &lt;code&gt;reasoning&lt;/code&gt; field instead of the standard &lt;code&gt;content&lt;/code&gt; field, depending on how it worked through the ranking task internally. The first time this happened, nothing crashed and no error appeared anywhere in the logs. The pipeline ran to completion, the cron job reported success, and the briefing that arrived on Telegram was just empty. That's a worse failure mode than a clean exception: an empty message looks like "nothing happened to be newsworthy today," not "something broke," so it took a few quiet mornings before the pattern was obvious enough to investigate. The fix is a fallback chain every analyzer checks in order, &lt;code&gt;content → reasoning_content → reasoning → text&lt;/code&gt;, rather than assuming the model will always populate the field the API docs imply it should. It's a one-line change once you know to make it, and an invisible one until you've been burned by it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cron doesn't speak the same language as your terminal.&lt;/strong&gt; Every scheduled job activates the Python virtual environment with &lt;code&gt;. venv/bin/activate&lt;/code&gt; rather than &lt;code&gt;source venv/bin/activate&lt;/code&gt;, and the reason is more fundamental than a style preference. &lt;code&gt;source&lt;/code&gt; is a bash builtin; cron runs jobs through &lt;code&gt;sh&lt;/code&gt;, not &lt;code&gt;bash&lt;/code&gt;, and &lt;code&gt;sh&lt;/code&gt; doesn't recognize it. The job had been tested manually dozens of times in an interactive terminal, where &lt;code&gt;source&lt;/code&gt; works fine because the terminal &lt;em&gt;is&lt;/em&gt; bash, so the activation line looked correct right up until it ran unattended for the first time, failed to activate the environment, and silently used whatever Python and packages happened to be on the system path instead of the ones the project actually depends on. No error, no crash, just a job quietly running against the wrong environment until something it depended on wasn't there. &lt;code&gt;.&lt;/code&gt; is the POSIX-portable equivalent and works in both shells. The fix is one character, but only once you understand why an interactive test can pass while the unattended version of the exact same command fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Repos Actually Get Chosen
&lt;/h2&gt;

&lt;p&gt;"Show me what's new on GitHub" is a bad prompt on its own. You get either noise or the same dozen famous repos everyone already knows about. Getting to a daily handful that's actually worth reading took a few layers of filtering before an LLM ever sees a candidate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Casting a wide net first.&lt;/strong&gt; The scraper runs a large batch of targeted search queries across several broad technical categories, each phrased to surface different kinds of repos: some queries hunt for brand-new activity, others for established projects with recent momentum, others for specific technical niches. No single query style finds everything; the combination is the point. The constraint shaping all of it: GitHub's search-specific endpoint caps out at 30 requests per minute, tighter than the general API limit and easy to blow through with this many categories firing in a loop. The scraper sleeps 2.1 seconds between calls, landing at roughly 28 requests a minute: close enough to the ceiling to finish a full run in a few minutes, far enough under it to never trip the limiter. A 403 anyway triggers a full 60-second backoff before retrying, rather than hammering an endpoint that just said slow down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code search hides the one number that matters.&lt;/strong&gt; GitHub's code-search endpoint is useful for finding repos by what's actually in them, not just their name or description, but the nested repository object it returns is missing the star count entirely. Every code-search hit needs a second, separate API call to fetch the full repo record before any tiering logic can run. Skip that step and half your candidates silently sort as zero-star nobodies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tiering compares each repo against itself, not a fixed bar.&lt;/strong&gt; Three tiers, and none of them use a flat "must have N stars" threshold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gem&lt;/strong&gt;: very new (under two weeks old), low absolute stars, but high velocity relative to its own short life.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exploding&lt;/strong&gt;: older, but its star count over the last comparison window is accelerating sharply versus its own recent trend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot&lt;/strong&gt;: established, but trending this week compared to its own historical baseline. A popular repo having an ordinary week doesn't qualify; one having an unusually active week does.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last distinction matters: a repo with ten thousand stars and no LLM-relevant recent activity is no more interesting on a given day than one with two hundred. What's being measured is change against the repo's own pattern, not absolute popularity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The LLM is told explicitly not to just rank by stars.&lt;/strong&gt; The curation prompt frames the task as picking what's meaningful: genuine novelty, technical relevance, and whether it's something I'd plausibly have missed without this pipeline. A repo near the top of the star-velocity list can still get passed over if it's a fork, a tutorial repo, or something with no real substance behind the trending number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The weekly tracker measures change, not snapshots.&lt;/strong&gt; For repos on a personal watchlist, every run stores that day's stats and compares them against the last stored snapshot, so the weekly report is a genuine delta (stars gained, momentum direction) rather than a restated current state. The explanation style is deliberately written for someone encountering each tool for the first time, since a watchlist can easily span tools outside what you use day to day.&lt;/p&gt;

&lt;p&gt;This watchlist isn't auto-populated the way the daily Discovery digest is. It's a small, deliberately curated set I add to by hand through a chat command whenever something earns a permanent spot. Right now it's three repos: &lt;code&gt;langchain-ai/langgraph&lt;/code&gt; (the orchestration framework underneath the multi-agent architecture I run in Teachsim, so a breaking change there has direct downstream consequences for things I've already shipped), &lt;code&gt;pydantic/pydantic-ai&lt;/code&gt; (a newer agent framework from a team whose validation library I already trust, worth watching to see whether it earns the same trust in the agent space), and &lt;code&gt;sst/opencode&lt;/code&gt; (a coding agent I started to use when Claude is in rate limits or blocked etc, so velocity here is a signal about where that category of tool is heading). None of these were discovered by the pipeline. They're things I already knew mattered and wanted tracked automatically instead of checking manually. The weekly report tells me, in plain language, whether each one had a quiet week or a meaningful one.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the News Actually Gets Judged
&lt;/h2&gt;

&lt;p&gt;"Is this worth reading" sounds like a single judgment call, but treating it that way is exactly how you get an inconsistent briefing: solid one day, padded with filler the next. The news analyzer runs off a fairly opinionated rubric instead, applied the same way across a few hundred headlines a day.&lt;/p&gt;

&lt;p&gt;It's told what not to include, explicitly. No celebrity news, no sports results, no weather unless it's catastrophic, no stock prices, no opinion pieces that don't contain any new information. That exclusion list does more work than any positive instruction: it's far easier to define "not worth your time" precisely than "worth your time" precisely.&lt;/p&gt;

&lt;p&gt;It's allowed to skip a category entirely. If a section has nothing worth including that day, the model is told to drop it rather than pad it with a weak story just to fill the slot, and it has to report which categories it skipped and why in a short line at the end. Silence has to be justified, not just defaulted into.&lt;/p&gt;

&lt;p&gt;Every kept item earns its place with two sentences, not one: what happened, and separately, why it matters. A story can be true and notable and still get cut if the model can't articulate the "so what" in one clean sentence. That forces an actual relevance judgment instead of a "this happened" summary.&lt;/p&gt;

&lt;p&gt;One section is deliberately anti-safe. There's a slot reserved for something unexpected: outside the normal categories, the kind of thing a curious person would find interesting precisely because nobody assigned it there. Without that forcing function, an LLM left to its own judgment tends to pick safe, obviously-important stories and nothing delightful or odd.&lt;/p&gt;

&lt;p&gt;The model runs at a low temperature for this task. It's tuned for consistent judgment calls, not creative variation. I want the same story judged the same way today and next week, not a slightly different read each run.&lt;/p&gt;

&lt;p&gt;So it's not magic curation. It's a rubric, and the LLM's job is applying it consistently across a volume of headlines that doesn't scale if you're doing it by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest State of It
&lt;/h2&gt;

&lt;p&gt;This is a single-user, single-region tool, not a product. It runs on a deliberately cheap VPS with real RAM constraints, which has already ruled out some approaches I considered (self-hosted text-to-speech, for one: the model and codec overhead alone would compete with the always-on listener process for memory). The codebase isn't open source right now while I keep iterating on it.&lt;/p&gt;

&lt;p&gt;It's also entirely text-based today. Voice and richer formatting are designed but not yet built, more on that below.&lt;/p&gt;

&lt;p&gt;Deepseek V4 Flash via Openrouter seems to be doing a good enough job, it allows me to read the gist of interesting news sometimes behind paywall and there was only once that I read the LLM thinking process rather than the actual news. Re-generating the news fixed it straightaway. Is it providing me a wholesome view of news and the world? Maybe not but it sure beats Google providing me with generic news everyday.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Coming Next
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Voice layer.&lt;/strong&gt; The morning news briefing gets a parallel spoken version: a handful of top stories, rewritten for speech (no URLs, no markdown, abbreviations spelled out) and sent as a Telegram voice note via an API-based text-to-speech call. Self-hosting TTS isn't viable on this hardware, so this stays API-based and stays cheap. The cost estimate for daily voice generation lands at a few cents a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Email as the primary reading surface.&lt;/strong&gt; Telegram's plain-text formatting and message-length chunking work fine at the current volume, but there's no rich formatting and no searchable archive: real problems once content volume grows. The plan is to make HTML email the main place I actually read the full briefing, while Telegram steps back to a notification ping plus the voice note plus on-demand commands. Same underlying pipeline, a second delivery path added alongside the existing one, gated behind a feature flag so the live system never breaks while the new path gets built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Discovery, scaled up, and the math that constrains it.&lt;/strong&gt; The plan adds several more topic categories to the search net, which sounds like it just means "more queries," but the 30-requests-per-minute search ceiling doesn't move just because the scope does. Roughly tripling the query count means the per-call sleep interval has to widen too, from the current 2.1 seconds to something closer to 3.2, or the scraper starts tripping the same limiter it was built to respect. The tradeoff is a longer run time in exchange for broader coverage: still comfortably a single-digit number of minutes, just no longer the fastest pipeline of the three. Repo counts per category will also stop being uniform. The categories I care about most get more picks per day, the narrower ones get fewer, and that's a deliberate choice rather than an oversight.(It took me a long time to talk with Claude to decide what fields and topics to track, there are just way too many fields and repos in Github!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broader news scope, same constraint-driven approach.&lt;/strong&gt; The news pipeline scales similarly, more feeds, more output sections, with the per-feed age-window logic (different freshness lookback for daily-cadence sources versus slower-publishing ones) carrying over unchanged, since that part of the design already solved the problem correctly the first time.&lt;/p&gt;

&lt;p&gt;None of this changes the core shape of the system. It's still three pipelines, an LLM doing the judgment calls, and a phone that doesn't need an app to receive any of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;The bet here is that the bottleneck in personal information consumption usually isn't access, it's triage. There's no shortage of news, and no shortage of interesting open-source work. What's scarce is time spent deciding what's worth reading. Handing that decision to a cheap, fast model running on a five-dollar VPS, three times a day, has been a more useful experiment than I expected going in.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;GitHub Digest is a personal project, currently text-only with voice and email delivery in active development. Built with Python, scheduled via cron and systemd, curated with an LLM via OpenRouter.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find me on GitHub: &lt;a href="https://github.com/mediblacksand" rel="noopener noreferrer"&gt;github.com/mediblacksand&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




</description>
      <category>python</category>
      <category>ai</category>
      <category>telegrambot</category>
      <category>automation</category>
    </item>
    <item>
      <title>I Built a Three-Agent AI Training Simulator on Telegram — Here's How It Works</title>
      <dc:creator>MediBlackSand</dc:creator>
      <pubDate>Thu, 18 Jun 2026 04:27:26 +0000</pubDate>
      <link>https://dev.to/mediblacksand_f0ea36c53fb/i-built-a-three-agent-ai-training-simulator-on-telegram-heres-how-it-works-1c8b</link>
      <guid>https://dev.to/mediblacksand_f0ea36c53fb/i-built-a-three-agent-ai-training-simulator-on-telegram-heres-how-it-works-1c8b</guid>
      <description>&lt;p&gt;&lt;em&gt;A working Telegram bot that stress-tests trainees with a pressure character, coaches them in real time with Socratic hints, and scores their performance. All from a single message.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most AI training tools do one of two things: they quiz you, or they roleplay with you. Neither is quite right for professional skill training. A quiz tells you what you know. A roleplay with a helpful AI tells you what you should have said.&lt;/p&gt;

&lt;p&gt;The missing piece is pressure. Something that watches how you respond under realistic conditions, nudges you when you're heading the wrong way, and then gives you an honest account of how you actually performed.&lt;/p&gt;

&lt;p&gt;That's what I wanted to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  What TeachSim Is
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://t.me/teachsim_bot" rel="noopener noreferrer"&gt;TeachSim&lt;/a&gt; is a Telegram-based training simulation. A trainee starts a session, gets dropped into a realistic workplace scenario, and has to navigate it in real time. What they don't see: two additional AI agents are watching the whole conversation. One is ready to offer a Socratic hint if the trainee stalls or heads in the wrong direction. The other is building a scored performance report that fires the moment the session ends.&lt;/p&gt;

&lt;p&gt;Three agents. One conversation. The trainee only ever talks to one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The three agents run as nodes in a &lt;strong&gt;LangGraph StateGraph&lt;/strong&gt;, sharing a single state object that tracks everything (conversation history, escalation level, hints used, resolution signals, scoring dimensions) across every exchange.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User message → Chaos node → Mentor node → [conditional]
                                               │
                                  session_active=False → Score → END
                                  session_active=True  → wait  → END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each agent gets its own LLM client tuned for its role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;get_chaos_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="c1"&gt;# temperature=0.75 — natural, varied character dialogue
&lt;/span&gt;&lt;span class="nf"&gt;get_mentor_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;# temperature=0.3  — measured Socratic hints
&lt;/span&gt;&lt;span class="nf"&gt;get_scoring_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# temperature=0.1  — deterministic JSON report
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three call DeepSeek V4 Flash via OpenRouter. The model string is &lt;code&gt;deepseek/deepseek-v4-flash&lt;/code&gt;. Switching providers means changing one file in the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two Live Scenarios
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Girls in STEM: Responding to an Excluded Student&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The trainee receives a message from a student named Jamie who feels pushed out of a STEM group. They have to draft a reply. The Chaos Persona (Jamie) escalates if the trainee stalls, over-apologises, or writes something technically correct but emotionally tone-deaf.&lt;/p&gt;

&lt;p&gt;This scenario is grounded in the &lt;strong&gt;Brooks (2025) TALK framework&lt;/strong&gt;, with three patterns the scoring rubric explicitly tracks: responsiveness (did you address what Jamie actually said, not just the emotional category?), superfluous apology (hedging that signals your discomfort rather than addressing hers), and topic pyramid (connection first, explanation second, practical close third). The mentor reads the trainee's actual drafted reply before deciding whether to intervene, not just a keyword trigger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code Assessment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The trainee is assessed by an AI trainer persona, Alex (warm, patient) or Jordan (direct, challenging), against a tiered competency framework before being granted access to Claude Code. Up to 16 exchanges, three difficulty levels, coverage thresholds that change by tier.&lt;/p&gt;

&lt;p&gt;Novice difficulty always routes to Alex regardless of selection. Expert difficulty requires 80% coverage across all three tiers before the readiness verdict fires.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the Hood
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Chaos Persona escalates.&lt;/strong&gt; Escalation level runs from 0 to 4 and never decrements. If the trainee stalls, makes repeated mistakes, or produces something clearly off-target, the persona gets more direct and less patient. The trainee can't reset the mood by being polite. They have to solve the actual problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Mentor is silent until it identifies an issue.&lt;/strong&gt; Mentor triggers are defined per scenario as structured conditions with IDs (&lt;code&gt;MT-01&lt;/code&gt; through &lt;code&gt;MT-99&lt;/code&gt;), severity weights, and a &lt;code&gt;max_fires&lt;/code&gt; ceiling. The same trigger won't fire twice. When it does fire, the hint appears as a coaching note, separate from the main conversation. The trainee knows the system is watching; they don't know exactly when it will speak.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New scenarios need no Python.&lt;/strong&gt; The entire scenario definition lives in a JSON file: persona, escalation arc, resolution conditions, mentor triggers, scoring rubric, difficulty variants. Pydantic validates every JSON at startup. Adding a new simulation topic is a schema problem, not a code problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The bot is live at &lt;a href="https://t.me/teachsim_bot" rel="noopener noreferrer"&gt;@teachsim_bot&lt;/a&gt;. Start a session, pick a scenario and difficulty, and see how the Chaos Persona responds to a weak first reply.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Open Telegram → search @teachsim_bot
2. /start
3. Pick a scenario
4. Pick a difficulty (novice / standard / expert)
5. Send your first message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sessions time out after 20 minutes. The score report fires automatically when the session resolves or the trainee runs out of exchanges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest State of It
&lt;/h2&gt;

&lt;p&gt;Two scenarios in production. Four were built; two are deprecated because the training value is not as high as the two in production. The repo is currently private while I decide whether to open source it. The bot is single-instance, single-region, not designed for concurrent scale yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  On Open Sourcing
&lt;/h2&gt;

&lt;p&gt;I'm still deciding. There's enough going on here (three-agent LangGraph with per-agent temperature tuning, data-driven scenario schema, Socratic mentor triggering) that it might be more useful as a reference implementation than as a closed tool. If there's interest from people who want to build domain-specific training simulations on top of it, open source makes sense. If you'd use this for something, tell me what.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Coming Next
&lt;/h2&gt;

&lt;p&gt;TeachSim was built around workplace and tool scenarios: high stakes, clear right answers, measurable outcomes. The architecture works well for that. But the same three-agent design (pressure character, silent mentor, scored report) maps onto a much older and harder problem: everyday conversation.&lt;/p&gt;

&lt;p&gt;I'm planning a second, more substantial simulation platform on the same foundation. This one is grounded in &lt;strong&gt;Alison Wood Brooks' conversation research&lt;/strong&gt;, specifically her work on topic flow, follow-up questions, the patterns that make people feel genuinely heard versus politely processed. The mentor in TeachSim watches for technical mistakes. The mentor in this one watches for the conversational habits most people don't know they have: the question that shuts a topic down instead of opening it, the pivot that signals discomfort, the apology that's really about the speaker.&lt;/p&gt;

&lt;p&gt;38 situations are designed across six tiers, from a first meeting and a first date through to emotionally complex, high-stakes conversations. Nine JSON files are built. Two are bot-tested. The architecture is the same; the theory layer underneath is different and deeper.&lt;/p&gt;

&lt;p&gt;More on that when it's ready. If conversation science and AI simulation overlap with something you're working on, follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;The bet TeachSim makes is that pressure-testing is the missing layer in AI training tools. Most tools will tell you the right answer after you get it wrong. This one makes you find it under conditions that feel like the real thing. Whether that produces better retention, faster skill transfer, or just higher stress is something I'd like to measure. If you run a session and have a reaction, good or bad, I want to hear it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;TeachSim is live at &lt;a href="https://t.me/teachsim_bot" rel="noopener noreferrer"&gt;@teachsim_bot&lt;/a&gt;. Built with LangGraph, DeepSeek V4 Flash, and python-telegram-bot. Repo currently private; open source decision pending. A second simulation platform based on Alison Wood Brooks' conversation research is in development on the same architecture.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find me on GitHub: &lt;a href="https://github.com/mediblacksand" rel="noopener noreferrer"&gt;github.com/mediblacksand&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference:&lt;/strong&gt; Brooks, Alison Wood. &lt;em&gt;Talk: The Science of Conversation and the Art of Being Ourselves.&lt;/em&gt; Crown, 2025.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;In loving memory of Zhang Fu, 1950–2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>langgraph</category>
      <category>ai</category>
      <category>telegrambot</category>
    </item>
  </channel>
</rss>
