<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Level Up Coding - Medium]]></title>
        <description><![CDATA[Coding tutorials and news. The developer homepage gitconnected.com &amp;&amp; skilled.dev &amp;&amp; levelup.dev - Medium]]></description>
        <link>https://levelup.gitconnected.com?source=rss----5517fd7b58a6---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Level Up Coding - Medium</title>
            <link>https://levelup.gitconnected.com?source=rss----5517fd7b58a6---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 07 Oct 2026 16:13:12 GMT</lastBuildDate>
        <atom:link href="https://levelup.gitconnected.com/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Building Fast Computer Agents to Solve Complex Tasks]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/building-fast-computer-agents-to-solve-complex-tasks-cf2bda5c54e7?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/1491/1*JzOCZa2WVbmhenQPCOq3iQ.png" width="1491"></a></p><p class="medium-feed-snippet">The Case for Interface Lifting in AI Agents</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/building-fast-computer-agents-to-solve-complex-tasks-cf2bda5c54e7?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/building-fast-computer-agents-to-solve-complex-tasks-cf2bda5c54e7?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/cf2bda5c54e7</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Fareed Khan]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:35:07 GMT</pubDate>
            <atom:updated>2026-10-07T15:35:05.881Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[The Last Mile of RAG: From Retrieved Chunks to a Trustworthy Answer]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/the-last-mile-of-rag-from-retrieved-chunks-to-a-trustworthy-answer-e873ff2fffbe?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/2600/0*-rLPdHyM-5cHlJFv" width="6000"></a></p><p class="medium-feed-snippet">Retrieval gives us evidence. But building a good RAG system also means deciding whether that evidence is enough, generating only from it&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/the-last-mile-of-rag-from-retrieved-chunks-to-a-trustworthy-answer-e873ff2fffbe?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/the-last-mile-of-rag-from-retrieved-chunks-to-a-trustworthy-answer-e873ff2fffbe?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/e873ff2fffbe</guid>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[retrieval-augmented-gen]]></category>
            <dc:creator><![CDATA[Rahul Gite]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:34:54 GMT</pubDate>
            <atom:updated>2026-10-07T15:34:52.710Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[What Is AGI? And Are We There Yet?]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/what-is-agi-and-are-we-there-yet-0e4df4d35887?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/2600/0*LV6cF2D1iZLzTW4E" width="3840"></a></p><p class="medium-feed-snippet">A clear map of AGI, ASI, and the walls in between</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/what-is-agi-and-are-we-there-yet-0e4df4d35887?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/what-is-agi-and-are-we-there-yet-0e4df4d35887?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/0e4df4d35887</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Vivedha Elango]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:34:41 GMT</pubDate>
            <atom:updated>2026-10-07T15:34:40.195Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[From Device to Device to Agent to Agent: The Pattern That Keeps Repeating]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/from-device-to-device-to-agent-to-agent-the-pattern-that-keeps-repeating-1b5100c33f6d?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/1376/1*FtGZ4oOrZZSh-5qtyU39AQ.jpeg" width="1376"></a></p><p class="medium-feed-snippet">Every decade, the actors in our systems change. The integration pattern stays the same. We are not building something new with&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/from-device-to-device-to-agent-to-agent-the-pattern-that-keeps-repeating-1b5100c33f6d?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/from-device-to-device-to-agent-to-agent-the-pattern-that-keeps-repeating-1b5100c33f6d?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/1b5100c33f6d</guid>
            <category><![CDATA[a2a-protocol]]></category>
            <category><![CDATA[system-architecture]]></category>
            <category><![CDATA[platform-engineering]]></category>
            <category><![CDATA[mcp-protocol]]></category>
            <category><![CDATA[microservices]]></category>
            <dc:creator><![CDATA[Sriram Mahalingam]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:34:26 GMT</pubDate>
            <atom:updated>2026-10-07T15:34:25.247Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[The Leadership Test Nobody Tells You About: Blame the User or Fix the Door]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/leadership-test-design-model-vs-deficit-model-62fc914ffda8?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/2600/0*B2UH3ji39_i5uegW" width="10451"></a></p><p class="medium-feed-snippet">The design model vs. the deficit model</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/leadership-test-design-model-vs-deficit-model-62fc914ffda8?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/leadership-test-design-model-vs-deficit-model-62fc914ffda8?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/62fc914ffda8</guid>
            <category><![CDATA[leadership]]></category>
            <category><![CDATA[ux-design]]></category>
            <category><![CDATA[marketing]]></category>
            <category><![CDATA[user-experience]]></category>
            <category><![CDATA[product-design]]></category>
            <dc:creator><![CDATA[Rakia Ben Sassi]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:34:14 GMT</pubDate>
            <atom:updated>2026-10-07T15:34:13.430Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Adaptive Streaming: How YouTube Changes Video Quality Without Stopping Playback]]></title>
            <link>https://levelup.gitconnected.com/adaptive-streaming-how-youtube-changes-video-quality-without-stopping-playback-6cb0a70d57e2?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/6cb0a70d57e2</guid>
            <category><![CDATA[hls]]></category>
            <category><![CDATA[video-streaming-service]]></category>
            <category><![CDATA[mpeg-dash]]></category>
            <category><![CDATA[adaptive-streaming]]></category>
            <category><![CDATA[youtube]]></category>
            <dc:creator><![CDATA[Prince Kumar Sharma]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:34:01 GMT</pubDate>
            <atom:updated>2026-10-07T15:34:00.105Z</atom:updated>
            <content:encoded><![CDATA[<p><em>A guide to ABR, HLS, MPEG-DASH, buffering, CDN, and how video quality changes in real time.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nHDss0uYKFCk8GcTbJJuSg.png" /></figure><p>You’re watching a YouTube video in 1080p.</p><p>Suddenly, your internet connection slows down.</p><p>The picture becomes slightly blurry.</p><p>The quality drops to 720p.</p><p>A few seconds later, your connection recovers.</p><p>The video returns to 1080p.</p><p>You didn’t press anything.</p><p>The video didn’t restart.</p><p>There was no page reload.</p><p>So, <strong>how did YouTube change the video quality while you were watching it?</strong></p><p>The answer is <strong>Adaptive Bitrate Streaming (ABR)</strong>.</p><p>And although YouTube’s web playback primarily uses <strong>MPEG-DASH rather than HLS</strong>, HLS is an excellent way to understand the underlying concept because both technologies use the same fundamental idea:</p><blockquote><strong><em>Provide multiple versions of the same video and allow the player to dynamically select the most appropriate one.</em></strong></blockquote><h3>What Is Adaptive Bitrate Streaming?</h3><p>Imagine the same video is available in several quality levels:</p><pre>| Quality | Illustrative Bitrate |<br>|---------|----------------------|<br>| 360p    | 800 Kbps             |<br>| 480p    | 1.5 Mbps             |<br>| 720p    | 3 Mbps               |<br>| 1080p   | 6 Mbps               |</pre><p>These are not four different videos.</p><p>They are different encoded representations of the same video.</p><p>Each representation may have a different:</p><ul><li>Resolution</li><li>Bitrate</li><li>Frame rate</li><li>Codec</li><li>Encoding profile</li></ul><p>If your network is fast and stable, the player can choose 1080p.</p><p>If your network becomes slower, it can switch to 720p or 480p.</p><p>The goal isn’t simply to provide the highest possible quality.</p><p>The real goal is:</p><blockquote><strong><em>Deliver the highest sustainable quality while avoiding buffering.</em></strong></blockquote><h3>Why Can’t the Player Just Change the Video Quality?</h3><p>This is where adaptive streaming gets interesting.</p><p>Suppose the server has a single file:</p><pre>movie.mp4</pre><p>The browser downloads and plays it.</p><p>Now imagine the network suddenly becomes slower.</p><p>The player can’t simply say:</p><blockquote><em>“I’m switching this same file from 1080p to 720p.”</em></blockquote><p>Instead, adaptive streaming prepares multiple versions of the content in advance.</p><p>More importantly, each version is divided into small pieces called <strong>segments</strong>.</p><p>For example:</p><pre>360p<br>[Segment 1] [Segment 2] [Segment 3] [Segment 4]<br><br>720p<br>[Segment 1] [Segment 2] [Segment 3] [Segment 4]<br><br>1080p<br>[Segment 1] [Segment 2] [Segment 3] [Segment 4]</pre><p>All three versions represent the same timeline.</p><p>The player can therefore do something like this:</p><pre>Segment 1 → 360p<br>Segment 2 → 360p<br>Segment 3 → 720p<br>Segment 4 → 720p<br>Segment 5 → 1080p</pre><p>The video keeps playing.</p><p>Only the representation used for upcoming segments changes.</p><p>That’s the fundamental trick behind adaptive streaming.</p><h3>How HLS Works</h3><p><strong>HLS (HTTP Live Streaming)</strong> is an adaptive streaming protocol originally developed by Apple.</p><p>HLS uses playlists to describe available streams and media segments.</p><p>A simplified HLS architecture looks like this:</p><pre>                 master.m3u8<br>                      |<br>          +-----------+-----------+<br>          |           |           |<br>         360p        720p        1080p<br>          |           |           |<br>      playlist     playlist     playlist<br>          |           |           |<br>      segments     segments     segments</pre><p>The top-level playlist tells the player which quality levels are available.</p><p>For example:</p><pre>#EXTM3U<br><br>#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360<br>360p/playlist.m3u8<br><br>#EXT-X-STREAM-INF:BANDWIDTH=3000000,RESOLUTION=1280x720<br>720p/playlist.m3u8<br><br>#EXT-X-STREAM-INF:BANDWIDTH=6000000,RESOLUTION=1920x1080<br>1080p/playlist.m3u8</pre><p>The player now knows:</p><pre>360p  → ~800 Kbps<br>720p  → ~3 Mbps<br>1080p → ~6 Mbps</pre><p>It can choose whichever representation it believes is appropriate.</p><h3>What Is Inside a Variant Playlist?</h3><p>A variant playlist points to the actual media segments.</p><p>For example:</p><pre>#EXTM3U<br><br>#EXTINF:6,<br>720p/segment001.ts<br><br>#EXTINF:6,<br>720p/segment002.ts<br><br>#EXTINF:6,<br>720p/segment003.ts<br><br>#EXTINF:6,<br>720p/segment004.ts</pre><p>Each segment represents a small portion of the video.</p><p>If the segment duration is six seconds, the player might have:</p><pre>0–6 sec<br>6–12 sec<br>12–18 sec<br>18–24 sec<br>...</pre><p>The exact segment duration can vary depending on the streaming system.</p><p>The important point is that the player doesn’t need to download the entire video before making a quality decision.</p><p>It can make decisions continuously as playback progresses.</p><h3>So How Does the Player Know When to Switch?</h3><p>This is where the <strong>ABR algorithm</strong> comes in.</p><p>The player continuously monitors several signals.</p><p>The two most important ones are:</p><h4>1. Available bandwidth</h4><p>How quickly can the player download the next segment?</p><h4>2. Buffer health</h4><p>How much video has already been downloaded and is waiting to be played?</p><p>Conceptually:</p><pre>              +------------------+<br>              |  Network Speed   |<br>              +--------+---------+<br>                       |<br>                       v<br>              +------------------+<br>              |   Buffer Level   |<br>              +--------+---------+<br>                       |<br>                       v<br>              +------------------+<br>              |   ABR Algorithm  |<br>              +--------+---------+<br>                       |<br>                       v<br>              +----------------------+<br>              | Next Quality Level   |<br>              | 360p → 480p → 720p   |<br>              |        → 1080p       |<br>              +----------------------+</pre><p>The algorithm uses these signals to decide what should be downloaded next.</p><h3>Bandwidth Is Not the Same as Internet Speed</h3><p>Suppose your internet connection is capable of 100 Mbps.</p><p>That does not necessarily mean your video player should immediately choose the highest-quality stream.</p><p>Why?</p><p>Because available bandwidth can fluctuate.</p><p>You might see:</p><pre>20 Mbps<br>↓<br>15 Mbps<br>↓<br>8 Mbps<br>↓<br>5 Mbps<br>↓<br>12 Mbps</pre><p>If the player reacts aggressively to every measurement, quality could constantly oscillate:</p><pre>1080p<br>↓<br>720p<br>↓<br>1080p<br>↓<br>720p<br>↓<br>1080p</pre><p>That would be a terrible viewing experience.</p><p>Therefore, ABR algorithms generally use some combination of:</p><ul><li>Recent throughput measurements</li><li>Throughput history</li><li>Buffer level</li><li>Safety margins</li><li>Current representation</li><li>Device capabilities</li><li>Playback conditions</li></ul><p>The exact algorithm depends on the player implementation.</p><h3>The Buffer Is Your Safety Net</h3><p>The second major concept is the <strong>playback buffer</strong>.</p><p>Imagine the player has already downloaded 20 seconds of video:</p><pre>Buffer<br><br>████████████████████<br>        20 sec</pre><p>If the network temporarily slows down, playback can continue because the player already has video waiting.</p><p>Now consider:</p><pre>Buffer<br><br>██<br>2 sec</pre><p>A slowdown is much more dangerous.</p><p>The player needs to become conservative.</p><p>This leads to a simple principle:</p><pre>Healthy buffer + good bandwidth<br>            ↓<br>       Higher quality<br><br><br>Low buffer + poor bandwidth<br>            ↓<br>       Lower quality</pre><p>The player isn’t simply asking:</p><blockquote><em>“How fast is my internet?”</em></blockquote><p>It’s effectively asking:</p><blockquote><strong><em>“Can I continue playing this quality without running out of buffered video?”</em></strong></blockquote><h3>A Real Example: 1080p → 720p → 1080p</h3><p>Let’s walk through a realistic scenario.</p><p>You’re watching a video at 1080p.</p><pre>1080p<br>6 Mbps</pre><p>Your network is stable.</p><p>The player continues downloading 1080p segments:</p><pre>1080p → 1080p → 1080p → 1080p</pre><p>Then your network slows down.</p><p>The player observes:</p><pre>Throughput ↓<br>Buffer ↓</pre><p>Continuing to download 1080p becomes risky.</p><p>Instead of waiting for the buffer to reach zero, the player proactively switches:</p><pre>1080p<br>   ↓<br>720p</pre><p>Now the required bitrate is lower.</p><p>The buffer stabilises.</p><p>A few seconds later, your network recovers:</p><pre>Throughput ↑<br>Buffer healthy</pre><p>The player determines that 1080p is sustainable again.</p><p>So it switches back:</p><pre>720p<br>   ↓<br>1080p</pre><p>From your perspective, it looks like YouTube simply changed the quality.</p><p>Underneath, something more interesting happened:</p><pre>1080p segment<br>1080p segment<br>720p segment<br>720p segment<br>1080p segment<br>1080p segment</pre><p>The timeline never stopped.</p><h3>Why Doesn’t Quality Change Every Second?</h3><p>Because that would create <strong>quality oscillation</strong>.</p><p>Imagine bandwidth fluctuates around the boundary between 720p and 1080p.</p><p>Without any protection, the player could repeatedly switch:</p><pre>720p → 1080p → 720p → 1080p</pre><p>A good ABR implementation therefore doesn’t necessarily switch immediately after every bandwidth change.</p><p>It can use:</p><ul><li>Hysteresis</li><li>Switching thresholds</li><li>Moving averages</li><li>Buffer thresholds</li><li>Safety margins</li></ul><p>Conceptually:</p><pre>Switch DOWN<br>when the current quality becomes unsafe.<br><br>Switch UP<br>only when the higher quality is comfortably sustainable.</pre><p>This is why quality often drops relatively quickly when the network deteriorates but takes a little longer to increase again.</p><p>The player is trying to avoid making a decision it will immediately have to reverse.</p><h3>HLS vs MPEG-DASH: An Important Distinction</h3><p>There’s a common misconception:</p><blockquote><em>“YouTube uses HLS to switch video quality.”</em></blockquote><p>That’s not technically accurate for YouTube’s primary web playback architecture.</p><p>YouTube has historically used <strong>MPEG-DASH</strong> together with <strong>Media Source Extensions (MSE)</strong> for web video playback.</p><p>HLS and MPEG-DASH are different technologies.</p><p>HLS uses concepts such as:</p><pre>.m3u8<br>Variant Streams<br>Media Segments</pre><p>MPEG-DASH uses:</p><pre>.mpd<br>Adaptation Sets<br>Representations<br>Media Segments</pre><p>But the underlying idea is very similar:</p><pre>Multiple qualities<br>       ↓<br>Segmented video<br>       ↓<br>Player measures conditions<br>       ↓<br>ABR algorithm<br>       ↓<br>Select next representation<br>       ↓<br>Continue playback</pre><p>So if you understand adaptive streaming through HLS, you’ve already understood a large part of the conceptual foundation behind DASH-based streaming as well.</p><h3>Where Does the CDN Come In?</h3><p>There is another important component:</p><p><strong>The Content Delivery Network (CDN).</strong></p><p>Imagine millions of users watching videos simultaneously.</p><p>You wouldn’t want every request to go directly to one central origin server.</p><p>Instead, video segments are distributed through CDN infrastructure.</p><p>A simplified architecture looks like this:</p><pre>                 Video Origin<br>                       |<br>                       v<br>                  CDN Network<br>                /      |      \<br>               /       |       \<br>          Edge A    Edge B    Edge C<br>             |         |         |<br>           Users     Users     Users</pre><p>When your player requests a video segment, the request can be served by a nearby CDN edge.</p><p>For example:</p><pre>Player<br>   |<br>   v<br>CDN Edge<br>   |<br>   v<br>Video Segment</pre><p>This reduces latency and allows streaming platforms to serve enormous numbers of concurrent viewers.</p><h3>What Happens Inside the Browser?</h3><p>For modern web playback, the architecture can be simplified to:</p><pre>Network<br>   |<br>   v<br>Streaming Player<br>   |<br>   v<br>ABR Algorithm<br>   |<br>   v<br>Media Buffer<br>   |<br>   v<br>Browser Media Pipeline<br>   |<br>   v<br>Decoder<br>   |<br>   v<br>GPU<br>   |<br>   v<br>Screen</pre><p>With technologies such as <strong>Media Source Extensions</strong>, a web application can control how media segments are supplied to the browser’s media pipeline.</p><p>The browser then handles the heavy lifting of decoding and rendering the video.</p><p>For a frontend engineer, this is an important distinction.</p><p>The &lt;video&gt; element may look simple:</p><pre>&lt;video controls&gt;&lt;/video&gt;</pre><p>But behind that simple UI is an entire streaming system involving:</p><pre>Manifest<br>↓<br>ABR<br>↓<br>HTTP requests<br>↓<br>CDN<br>↓<br>Segments<br>↓<br>Buffer management<br>↓<br>Media Source Extensions<br>↓<br>Codec<br>↓<br>Decoder<br>↓<br>GPU</pre><h3>The Complete Adaptive Streaming Flow</h3><p>Putting everything together:</p><pre>                 Original Video<br>                       |<br>                       v<br>                    Encoder<br>                       |<br>          +------------+------------+<br>          |            |            |<br>         360p         720p        1080p<br>          |            |            |<br>          +------------+------------+<br>                       |<br>                  Segmentation<br>                       |<br>                       v<br>                      CDN<br>                       |<br>                       v<br>                 Player/Browser<br>                       |<br>              +--------+--------+<br>              |                 |<br>        Bandwidth            Buffer<br>              |                 |<br>              +--------+--------+<br>                       |<br>                       v<br>                  ABR Algorithm<br>                       |<br>                       v<br>               Select Next Quality<br>                       |<br>                       v<br>                 Download Segment<br>                       |<br>                       v<br>                    Buffer<br>                       |<br>                       v<br>                    Decode<br>                       |<br>                       v<br>                    Display</pre><p>This cycle repeats throughout playback.</p><p>The player continuously evaluates the situation and decides what should happen next.</p><h3>Why Adaptive Streaming Is So Important</h3><p>Without adaptive streaming, a video player would have to choose between two bad options.</p><h4>Option 1: Always use high quality</h4><p>Great picture.</p><p>But when the network slows down:</p><pre>Buffer ↓<br>Buffer ↓<br>Buffer ↓<br><br>BUFFERING</pre><h4>Option 2: Always use low quality</h4><p>Playback is more reliable.</p><p>But users with fast connections receive unnecessarily poor video quality.</p><p>Adaptive streaming provides a middle ground:</p><pre>Fast network<br>     ↓<br>Higher quality<br><br>Slow network<br>     ↓<br>Lower quality<br><br>Network recovers<br>     ↓<br>Higher quality again</pre><p>The player continuously adapts rather than committing to one bitrate for the entire session.</p><h3>The Bigger Picture</h3><p>The next time YouTube changes from 1080p to 720p, it isn’t necessarily “changing the video.”</p><p>It’s selecting a different representation of the same content.</p><p>The complete system looks something like this:</p><pre>Video Encoding<br>      ↓<br>Multiple Representations<br>      ↓<br>Segmentation<br>      ↓<br>Manifest / Playlist<br>      ↓<br>CDN<br>      ↓<br>Streaming Player<br>      ↓<br>Bandwidth + Buffer Monitoring<br>      ↓<br>ABR Decision<br>      ↓<br>Next Segment<br>      ↓<br>Browser Decoder<br>      ↓<br>Screen</pre><p>What looks like a tiny quality change in the YouTube UI is actually the result of multiple distributed systems working together.</p><h3>Final Takeaway</h3><p>Adaptive streaming is not about making one video dynamically change its resolution.</p><p>It’s about creating <strong>multiple representations of the same video</strong>, dividing them into manageable segments, and allowing the player to intelligently choose which representation to download next.</p><p>HLS does this through playlists and variants.</p><p>MPEG-DASH does it through MPDs, adaptation sets, and representations.</p><p>The ABR algorithm sits at the centre of the experience, continuously balancing:</p><p><strong>Bandwidth</strong></p><p><strong>Buffer health</strong></p><p><strong>Video quality</strong></p><p><strong>Re-buffering risk</strong></p><p>And that leads to the most important principle in adaptive streaming:</p><blockquote><strong><em>The best streaming experience isn’t the highest possible quality. It’s the highest sustainable quality without interrupting playback.</em></strong></blockquote><p>That’s why YouTube can move from 1080p to 720p and back again without you ever seeing the video stop.</p><p>The quality changed.</p><p><strong>The playback didn’t.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6cb0a70d57e2" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/adaptive-streaming-how-youtube-changes-video-quality-without-stopping-playback-6cb0a70d57e2">Adaptive Streaming: How YouTube Changes Video Quality Without Stopping Playback</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[API & Database Design: Why a Payment Ledger Should Never Be a Document Store]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/api-database-design-why-a-payment-ledger-should-never-be-a-document-store-60dc2eb4ea75?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/1408/1*nvNoP6ntagitua8PwoV2qg.jpeg" width="1408"></a></p><p class="medium-feed-snippet">System Design Interview Prep &#x2014; Day 2 of 8</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/api-database-design-why-a-payment-ledger-should-never-be-a-document-store-60dc2eb4ea75?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/api-database-design-why-a-payment-ledger-should-never-be-a-document-store-60dc2eb4ea75?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/60dc2eb4ea75</guid>
            <category><![CDATA[system-design-interview]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Vladyslav Kekukh]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:33:46 GMT</pubDate>
            <atom:updated>2026-10-07T15:33:45.571Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Four AI Apps, Zero Print Buttons, and One 100KB Cap in the Wrong Place]]></title>
            <link>https://levelup.gitconnected.com/four-ai-apps-zero-print-buttons-and-one-100kb-cap-in-the-wrong-place-54d73a1cc5ac?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/54d73a1cc5ac</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[chrome-extension]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Adi Leviim]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:33:32 GMT</pubDate>
            <atom:updated>2026-10-07T15:33:31.635Z</atom:updated>
            <content:encoded><![CDATA[<p><em>No assistant ships a Print option. The export that replaces it broke on an exact-match path allowlist.</em></p><figure><img alt="A white A4 sheet on a deep coral background, tilted slightly, showing browser print-preview chrome: a date and the word Conversation along the top, the URL chatgpt dot com slash c slash 68f2a1 and the page counter 1 slash 17 along the bottom. The page itself is completely blank. Large white type beside it reads Your whole chat, with the word chat in yellow, and the word PRINTED underneath." src="https://cdn-images-1.medium.com/max/1024/1*cxCJQTRz3pjPcLCdTrj4aQ.png" /><figcaption>Chrome prepared a 17-page job from a long ChatGPT conversation. Every page came out like this one. Credit: Illustration by author</figcaption></figure><p>I co-build a browser extension that exports AI conversations, so people write to us about this a lot: they want a chat on paper. A transcript for a lawyer, a research log for a supervisor, a record of a diagnosis conversation to take to an appointment.</p><p>Last week I went looking for the Print button in ChatGPT, Claude and Grok. There isn’t one. Not in any of them, and not documented anywhere by any of the three vendors.</p><p>So I pressed Cmd+P. Chrome prepared a 17-page print job, and every page was blank.</p><p>This is the story of what the apps do give you instead, why the browser’s own print capture fails, and the one-line Express configuration mistake that made our replacement for it fail in exactly the same way, for completely different reasons.</p><h3>Nobody Ships a Print Button</h3><p>Start with what is actually documented, because the gap is wider than it looks.</p><p>ChatGPT has no print option. What it added instead, in a February 13, 2026 release note, is a change to text selection: Cmd+A “now selects only the conversation content, excluding surrounding interface elements.” That is a copy-to-clipboard improvement, shipped by a team that clearly knows people are trying to get the text out. It is not printing. Deep research reports download as PDF, Word or Markdown, but ordinary conversations do not.</p><p>Claude has no print option either. Public share links are view-only. Artifacts created from a template export properly (Documents to Word, PDF, Markdown or Google Docs; Decks to PPTX or PDF), and Claude can create files directly. But the conversation around the artifact is not covered by any of it.</p><p>Grok has a share link, revocable at grok.com/share-links, and a full account data download in Settings under Data Controls whose format is not documented anywhere. There is no single-chat export.</p><p>Three products that people use for hours a day, and the only documented way to get one conversation out as a document is to make it into something else first.</p><h3>Why Ctrl+P Comes Out Blank</h3><p>The browser can always print a page, so why 17 blank sheets?</p><p>Because the transcript is not there. ChatGPT renders messages as you scroll, and the print capture takes the page in its unrendered state. The DOM the printer serialises contains the scroll container and almost nothing else.</p><p>This is not a bug in the usual sense. Virtualising a long transcript is the correct call for scroll performance, and every chat UI of any size does it. But virtualisation makes an implicit trade that nobody writes down: the document only exists in the places you have looked at. Print, Find in page, Reader mode and “save page as” all assume the opposite.</p><p>The workaround everyone discovers is to scroll from the first message to the last, slowly, so the whole thing is realised, and then print. That works. It is also an instruction you cannot give a non-technical user with a straight face.</p><p>Worth saying plainly: I tested this on ChatGPT. I have not run the same test on claude.ai or grok.com, so treat the print preview as the proof on any app. If the pages are blank or the end is missing, the capture failed.</p><h3>So We Built the Export Instead</h3><p>Our extension renders a conversation to PDF server-side, which sidesteps the virtualisation problem entirely: the messages come from the API, not the DOM, so there is nothing to scroll.</p><figure><img alt="Screenshot of the AI Toolbox Select Export Format dialog, with radio buttons for Text, Markdown, JSON and PDF. Markdown is selected. Markdown, JSON and PDF each carry a purple Premium badge; Text has none. Close and Export buttons sit at the bottom." src="https://cdn-images-1.medium.com/max/1024/1*WmFliipbS3mMSrlb4CkhTQ.png" /><figcaption>Text is on the free plan. The PDF path is the one with all the interesting failure modes. Credit: Screenshot by author</figcaption></figure><p>That worked until a paying customer told us it did not. They had bought the plan specifically to export one long chat as a PDF, and got this instead:</p><blockquote><em>“This chat is too long to build as a PDF in your browser”</em></blockquote><h3>Three Limits, Three Units</h3><p>The reason that message appeared turned out to be three separate ceilings, none of which knows about the others.</p><figure><img alt="Illustration of a cream electrical breaker panel on an olive wall, headed What Trips on a Long Chat Export. Three breakers are flipped to OFF. 30 seconds, Chrome’s fetch limit for a background worker, so a server render of a long chat dies in flight. 200 pages, what the in-browser renderer refuses above, which is the fallback where the user sees an error. 100 kilobytes, the first global body parser the jobs route still sits behind." src="https://cdn-images-1.medium.com/max/1024/1*zaE5qKV5H2MR5JRDPusaFg.png" /><figcaption>Three numbers in three different units, in three different layers, and only the last one is visible to the user. Credit: Diagram by author</figcaption></figure><p>A Chrome extension’s background worker gets about 30 seconds for a fetch. A server render of a very long conversation takes longer than that, so the request died in flight. The export then fell back to the in-browser rasteriser, which refuses anything above 200 pages. The customer saw the 200-page refusal and reasonably concluded the product could not do the thing they had paid for.</p><h3>The Fix: Render It as a Job</h3><p>The fix was to stop trying to do it in one request. Above a threshold, the conversation goes to the backend as a job: start it, poll, download.</p><pre>/**<br> * Content characters above which a conversation is rendered as a job.<br> *<br> * Equal to the backend&#39;s PART_BUDGET_CHARS: below it the backend would print<br> * the job as a single part anyway, and the single request is measured at about<br> * 1.2s there, far inside every timeout. Above it, the job path.<br> */<br>export const LONG_PDF_CHARS = 300_000;</pre><pre>export function shouldRenderAsJob(messages: readonly HasContent[]): boolean {<br>  return contentChars(messages) &gt; LONG_PDF_CHARS;<br>}</pre><p>Three requests, each of which answers immediately, so none of them can outlast the 30-second worker limit. The backend prints the document in parts and joins them. Everything below the threshold keeps the single request it always had.</p><p>That shipped, and it worked.</p><h3>The Bug the Fix Created</h3><p>Now the part I actually want to write about.</p><p>Our Express app caps request bodies globally. Two routes legitimately carry a whole conversation as JSON, so they are exempted:</p><pre>// The global parsers below cap bodies low (jsonWithRawBody defaults to 100kb;<br>// express.json to 1mb), so they&#39;d reject a long conversation with 413 *before*<br>// it reached the route&#39;s own larger parser.<br>const LARGE_BODY_PATHS = new Set([&quot;/export/pdf&quot;, &quot;/context-mentions/summarize&quot;, &quot;/usage/sync&quot;]);</pre><pre>const skipLargeBody =<br>  (mw: RequestHandler): RequestHandler =&gt;<br>  (req, res, next) =&gt;<br>    LARGE_BODY_PATHS.has(req.path) ? next() : mw(req, res, next);</pre><pre>app.use(skipLargeBody(jsonWithRawBody));<br>app.use(skipLargeBody(express.json({ limit: &quot;1mb&quot; })));</pre><p>Read the set, then read the route the fix added:</p><pre>router.post(&quot;/export/pdf/jobs&quot;, exportJson, extensionAuth, pdfExportRateLimit, handler);</pre><p>Set.has() is an exact match. /export/pdf/jobs is not /export/pdf. The route carries its own 10MB parser, but the global 100KB parser runs first and rejects the body before the route&#39;s parser is ever reached.</p><figure><img alt="Illustration of three cream envelopes in an oak pigeonhole rack on a pale blue-grey wall, labelled slash export slash pdf, slash context-mentions slash summarize, and slash usage slash sync. A fourth envelope labelled slash export slash pdf slash jobs lies on the floor below the rack. The heading reads LARGE_BODY_PATHS dot has, open bracket, req dot path, close bracket, and a note reads Not in the set." src="https://cdn-images-1.medium.com/max/1024/1*GkQDVgH77Va1470XIIlVQw.png" /><figcaption>The route built specifically for the largest payloads is the only one still behind the smallest cap. Credit: Diagram by author</figcaption></figure><p>The whole point of the jobs route is conversations too big to render in one request. It is, by construction, the route with the largest bodies in the application. And it is the one route not on the list of routes allowed to have large bodies.</p><h3>One 413, Four Steps to the Error</h3><p>What makes this worth a thousand words is not the mistake. It is that the mistake is invisible.</p><figure><img alt="Illustration on an espresso brown background of four cream domino tiles leaning progressively to the right, ending beside a red card. Tile 01, POST /export/pdf/jobs, refused 413 by a parser the route was meant to skip. Tile 02, readJobStart, not 404 not 429 no job id, returns failed. Tile 03, renderPdfAsJob, returns undefined like any failed render. Tile 04, in-browser rasteriser, refuses above 200 pages. The red card reads, this chat is too long to build as a PDF in your browser." src="https://cdn-images-1.medium.com/max/1024/1*kmUIYu_CEOC6t9PHJtfGMg.png" /><figcaption>Every step in this chain behaves exactly as designed. The only thing that is wrong is a missing string in a Set. Credit: Diagram by author</figcaption></figure><p>Follow the 413 through:</p><pre>export function readJobStart(status: number | null, body: unknown): JobStart {<br>  if (status === 404) return { kind: &quot;unsupported&quot; };<br>  if (status === 429) return { kind: &quot;busy&quot; };<br>  // ...<br>  return { kind: &quot;failed&quot; };<br>}</pre><p>A 413 is not 404, so the client does not conclude the backend is too old. It is not 429, so it does not retry. There is no job id, so it returns failed. renderPdfAsJob then returns undefined, which is the same value it returns for any render that genuinely could not be produced, and the caller does what it does for every failed render: falls back to the in-browser rasteriser, which refuses above 200 pages.</p><p>So the user gets the exact error the job path was built to eliminate. No alert fires. The 413 never surfaces as a 413. A graceful degradation path, which is a good thing to have, is also a very effective way to hide a configuration bug for weeks.</p><h3>What I Would Take From This</h3><p>Four things, in rough order of how much they would have saved me.</p><p>An allowlist keyed on an exact path is a trap the moment a route grows a sub-path. req.path.startsWith() over a prefix list, or attaching the limit to the router rather than to a central set, both survive the next route. A Set of strings does not, and nothing warns you.</p><p>Put the limit next to the thing it limits. The body cap for /export/pdf/jobs lives in index.ts, about four hundred lines from the route it governs. Anyone adding a route in routes/export.ts sees the route&#39;s own 10MB parser and reasonably assumes that is the operative number.</p><p>Treat every fallback as a place a bug can hide. A fallback converts a loud failure into a quiet degradation, which is exactly what you want in production and exactly what you do not want while finding this. If a fallback fires, log why, with the status code, at a level someone actually reads.</p><p>Test the case the feature exists for. Every test we had used a normal conversation. The jobs route exists only for abnormal ones, and a fixture above 300,000 characters would have caught this on the first run.</p><h3>Key Takeaways</h3><ul><li>None of ChatGPT, Claude or Grok documents a Print option for a conversation. Printing from the browser is the only universal route, and on a virtualised transcript it can produce blank pages.</li><li>Virtualised rendering silently breaks Print, Find in page and save-as. The document only exists where the user has scrolled.</li><li>A Set.has(req.path) allowlist stops covering a route the moment that route gains a sub-path, and the failure mode is a 413 that looks like something else entirely.</li><li>Keep request-size limits next to their routes, not in a central list in the app entry point.</li><li>A fallback path is a bug silencer. Log the reason it fired.</li></ul><h3>FAQ</h3><p>Can you print a ChatGPT conversation? Not with a built-in option, because there isn’t one. Press Ctrl+P or Cmd+P in a desktop browser, but scroll the whole conversation first and check the print preview before sending it, because a long chat can come out blank.</p><p>Why does my ChatGPT printout come out blank? ChatGPT renders messages as you scroll. If the print capture happens before a message has been rendered, that message is not in the DOM and does not reach the page.</p><p>Is there a free way to get a long chat onto paper? Yes. Export it as plain text and print that from any text editor. TXT export is on the free plan in our extension; the formatted PDF is the paid one.</p><h3>Resources</h3><ul><li><a href="https://www.ai-toolbox.co/ai-toolbox-chatgpt-features/how-to-print-chatgpt-claude-grok-conversation-2026">How to print a ChatGPT, Claude or Grok conversation</a>, the step-by-step version of this, with the per-app detail</li><li><a href="https://support.google.com/chrome/answer/1069693">Chrome Help: print from Chrome</a></li><li><a href="https://expressjs.com/en/api.html#express.json">Express body-parser limits</a></li></ul><p>About the author: Adi Leviim is the co-founder of AI Toolbox (formerly ChatGPT Toolbox), a Chrome extension with four modules (ChatGPT, Gemini, Claude, Grok) used by 40,000+ people across 150+ countries to search, organize, and export their AI conversations. He writes about the reality of building AI products with 7+ years of full-stack development experience. Follow him on Medium for honest takes on SaaS, AI tools, and shipping software that people actually use.</p><p>Try it free on the <a href="https://chromewebstore.google.com/detail/ai-toolbox-folders-prompt/jlalnhjkfiogoeonamcnngdndjbneina">Chrome Web Store</a>. TXT export is on the free plan; Markdown, JSON and PDF are Premium at $9.99 a month or $99 lifetime per module, and All Access is $199 one time for all four. These are extension features, not an AI subscription.</p><p><a href="https://ai-toolbox.co/">AI Toolbox</a> | <a href="https://medium.com/@adi_leviim">Medium</a> | <a href="https://x.com/adileviim">Twitter/X</a> | <a href="https://www.linkedin.com/in/adi-leviim/">LinkedIn</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=54d73a1cc5ac" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/four-ai-apps-zero-print-buttons-and-one-100kb-cap-in-the-wrong-place-54d73a1cc5ac">Four AI Apps, Zero Print Buttons, and One 100KB Cap in the Wrong Place</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making a Rust Crossword Compiler with 16,000 Words and a Basic Knowledge of Cryptography]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/making-a-rust-crossword-compiler-with-16-000-words-and-a-basic-knowledge-of-cryptography-ff96aabf2f51?source=rss----5517fd7b58a6---4"><img src="https://cdn-images-1.medium.com/max/2600/0*MQLaaidt5WlO2HY9" width="5760"></a></p><p class="medium-feed-snippet">On Anagrams, Cryptic Clues, and the Moral Character of the Borrow Checker</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/making-a-rust-crossword-compiler-with-16-000-words-and-a-basic-knowledge-of-cryptography-ff96aabf2f51?source=rss----5517fd7b58a6---4">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/making-a-rust-crossword-compiler-with-16-000-words-and-a-basic-knowledge-of-cryptography-ff96aabf2f51?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/ff96aabf2f51</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[crossword-puzzles]]></category>
            <category><![CDATA[rust]]></category>
            <dc:creator><![CDATA[S.A. Routh]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:33:20 GMT</pubDate>
            <atom:updated>2026-10-07T15:33:19.078Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[How to Ditch Gemini: A Step-by-Step Breakup Recipe]]></title>
            <link>https://levelup.gitconnected.com/how-to-ditch-gemini-a-step-by-step-breakup-recipe-85b37ad9c669?source=rss----5517fd7b58a6---4</link>
            <guid isPermaLink="false">https://medium.com/p/85b37ad9c669</guid>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[database]]></category>
            <category><![CDATA[sre]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <dc:creator><![CDATA[Boris Dali]]></dc:creator>
            <pubDate>Wed, 07 Oct 2026 15:33:07 GMT</pubDate>
            <atom:updated>2026-10-07T16:12:01.786Z</atom:updated>
            <content:encoded><![CDATA[<h4>They say breakups are hard. aiHelpDesk proves otherwise. Model-neutrality isn’t a slogan until you’ve actually done it. Here’s the procedure, not the promise</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uoWWEI8MKrrWyIbrXhv68A.jpeg" /></figure><p>First off, aiHelpDesk is model neutral. When we claim that we are agnostic to swapping models, we mean it.</p><p><a href="https://github.com/borisdali/helpdesk/blob/main/docs/PRINCIPLES.md#11-model-neutral-by-design">That’s one</a> of our core principles (along with trust being the other core value, not something bolted as an afterthought, made explicit because it’s backed by our formal Customer <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CUSTOMER_RIGHTS.md">Bill of Rights</a>). That is, from the ground up aiHelpDesk was engineered to not depend on any particular LLM, treat models as <a href="https://medium.com/google-cloud/llms-are-functions-not-brains-aihelpdesk-perspective-e12e5432a9ed">a disposable commodity</a> and make it as one of our explicit goals to allow seamless, easy, non-engineering migrations from one model to another, be it with the models of the same vendor (e.g. going from Sonnet to Opus) or switching the model vendors altogether (e.g. from Gemini to Anthropic).</p><p>I already <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">wrote about it</a> a number of times, advising customers to invest into their own teams and intelligence in favor building dependencies on a specific model’s feature. This in turn often results in customers and prospects asking to actually <em>prove</em> that models are indeed easily replaceable. Specific steps that an aiHelpDesk customer can execute on their own without taking our word for it.</p><p>This request typically doesn’t come out of some idle, academic curiosity. More often than not, there’s a business urgency to it, accompanied with the specifics of what model / vendor a customer is not happy with and wants to migrate away from. In particular, the request/question that we answer often is how to ditch Gemini and move up to one of the frontier model XYZ. That XYZ varies, but the model to migrate away from is often Google’s, so instead of repeating ourselves we figured we can just share the standard recipe we follow.</p><p>The recipe below works well for us and a broader community can perhaps benefit from our experience, so here goes: the breakup without drama or tears, start to finish, using the real tooling, not a diagram.</p><h3>The breakup recipe</h3><p>The scenario: your team has been evaluating Google suite of products for three months and in particular your database fleet has been relying on Gemini for triage and remediation. In this piece we won’t be speculating as to why customers are eager to ditch Google, but let’s assume the trial hasn’t been particuarly successful or Anthropic shipped Fable or other model that you want to evaluate or for any other reaosn, you decide to abandon ship. Now, one thing you don’t want is a vibe-based migration. You want confidence. You want a number to avoid wasting another three months of your team.</p><p>I use “from Gemini to XYZ” in this article because that’s what we see in the field, but the same principles apply to any from/to models as well.</p><h4>Step 0: What you’re actually proving</h4><p>Before touching anything, be precise about the claim. You are not about to prove “the new model is smarter according to MMLU, DeepEval or similar generic benchmarks”. You’re about to prove something narrower and more useful <strong>to you</strong>: the new model reasons about <strong>your specific failure modes</strong> at least as consistently as the one it’s replacing. That’s it. Consistency, not Intelligence and as it applies to <strong>your</strong> databases and <strong>your</strong> workload in particular.</p><p>The <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md#2-where-certification-fits-in-the-flywheel">Consistency Gate</a> doesn’t have an opinion about which model is “better”. It has a pass/fail threshold on a pass rate, a confidence spread and it doesn’t care whose logo is on the API response.</p><h4>Step 1: Baseline the incumbent</h4><p>Before you can claim a successful upgrade, you need a number for what you’re upgrading from. The baseline. This is not optional because after the upgrade you need something to refer back to how things looked with Google, compare the two numbers and claim the improvement. People that report problems with swapping models, in our experience, skip this step. You don’t want to be one of them. No victory dance for you if you have no baseline to compare to.</p><p>If Gemini doesn’t already have a cert on file already, generate one:</p><pre>  export HELPDESK_GATEWAY_URL=http://localhost:8080<br>  export HELPDESK_MODEL_VENDOR=google<br>  export HELPDESK_MODEL_NAME=gemini-3.5-flash<br>  export HELPDESK_API_KEY=$GOOGLE_API_KEY<br><br>  make recertify RECERTIFY_REPEAT=5<br><br>  go run ./testing/cmd/faulttest vault accuracy db-lock-contention \<br>    --gateway $HELPDESK_GATEWAY_URL \<br>    --api-key $HELPDESK_API_KEY<br></pre><p>That <em>-repeat 5</em> under the hood is five independent inject→diagnose→score cycles per fault, not one lucky run. Once <a href="https://github.com/borisdali/helpdesk/blob/main/docs/FAULTTEST.md"><em>faulttest</em></a> finishes, pull up the receipt:</p><pre>Triage consistency<br>    Fault         : db-lock-contention  (Transaction lock chain / deadlock)<br>    Verdict       : STABLE<br>    Runs          : 5<br>    Pass rate     : 80%<br>    Conf range    : 8pp  (primary hypothesis, passing runs only)<br>    Clean         : yes<br>    Playbook      : pbs_lock_chain_triage<br>    Diagnosis model: gemini-3.5-flash<br>    Judge model   : gemini-3.5-flash<br>    Tested at     : 2026-10-01 14:02 EDT  (3 days ago)</pre><p>That’s your baseline, on the record, not in a Slack thread.</p><p>Now, note that in the printout above the diagnosis model (the model used for triaging the the problem, reviewing the artifacts, coming up with the primary and alternative hypotheses, attaching the confidence level to each, etc.)… is the same model as the judge model. Is this a typo?</p><h4>Step 2: Pin an independent judge</h4><p>Well, let’s step back and review first if we need <a href="https://github.com/borisdali/helpdesk/blob/main/docs/LLM_AS_JUDGE.md">a judge</a> at all, shall we?</p><p>Breakups aren’t easy, as they say, so it helps to have an independent, unbiased, fair and preferably third-party observer overseeing the process. The judge offers <a href="https://github.com/borisdali/helpdesk/blob/main/docs/SECOND_OPINION.md">a second opinion</a>, scoring both the outgoing and incoming candidates, so yes, we recommend a judge for swapping models.</p><blockquote>And yes, this is still a model judging a model, so not ideal as <a href="https://itnext.io/aws-says-its-wrong-not-broken-but-who-does-the-grading-c832d5fbaf8d">I pointed out earlier</a>, but for this type of work we find that judging works surprisingly well.</blockquote><p>Now, the model that <em>assesses the quality</em> of the diagnosis to see if it’s correct or not, doesn’t have to be the same model <em>doing</em> the actual diagnosis. In fact, it’s usually preferrable if it isn’t. You can absolutely use the same model for both and, somewhat surprisingly, a model that isn’t your first choice for primary reasoning can still do a perfectly adequate job as a judge, but it’s it isn’t ideal.</p><p>In practial terms we’ve seen three schemes, in descending order of rigor:</p><ul><li>Ideal, in principle: pin a genuinely independent third-party judge, which is a vendor that’s neither the one you’re leaving nor the one you’re moving to, used for both the baseline run and the new model’s evaluation (aka re-certify). This is the textbook-correct setup: it removes judge variance as a confound entirely, so if you go from Gemini to Fable, you probably want the judge to be Open AI or similar. Now, we don’t offer support for Open AI yet. <em>agentutil.NewLLM is </em>the function every model call in aiHelpDesk routes through, diagnosis or judge and as it stands today, it doesn’t yet know about Open AI, but we are actively looking for an excuse to add it. Please consider it and open a FR with us and we’d be happy to oblige 😉.</li><li>Compromise 1: same model used for both roles where you effectively use your primary reasoning model as its own judge. Yes, ideally, the referee shouldn’t be the vendor you’re leaving behind and we can see why many move away from Gemini, but as a judge it often does good enough of a job to offer a qualified second opinion. So not the most scientific option because you’re letting the model grade its own breakup letter, but it works better than you’d expect in practice. If you go down this path, just expect some judge-specific noise and budget for more repeated runs to average it out.</li><li>Compromise 2: cross-reference, which is what we see most used today: get Anthropic to judge the outgoing Gemini model and Gemini to judge the incoming Anthropic model. Neither judge shares a vendor with the model it’s scoring, so you still get rid of the worst version of the conflict-of-interest problem, i.e. the model never grades its own work. Now, with this option you get the true third-party independence and not the true apples-to-apples comparison because if a referee is not constant across both runs, it’s more difficult to tell whether the score shift comes from the <em>diagnosis model</em> changing or the <em>judge</em> changing, but in practice this option typically works well for most use cases.</li></ul><p>To summarize: option 1 is ideal because keeping/pinning the judge constant across the baseline run and the comparison runs makes it easy to see the only thing changing: the model. Swap the judge along with the diagnosis model and it’s more difficult to tell which change produced the score difference.</p><p>Now, if your judge is different from the primary reasoning model, remember to set the <em>-judge-model,</em> <em>-judge-vendor</em> and -<em>judge-api-key</em> because those are the separate flags from the diagnosis model flags. But there’s a quirk. Experienced aiHelpDesk customers typically rely on the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md#5-running-a-certification"><em>make recertify</em></a>’s [<a href="https://github.com/borisdali/helpdesk/blob/12d3431e59184ef8e01526ed3f86bd098b8c6937/Makefile#L362">code link</a>] Makefile target, but while the three flags above are the real <em>judge</em> flags for <a href="https://github.com/borisdali/helpdesk/blob/main/docs/FAULTTEST.md"><em>faulttest</em></a>, the <em>make recertify</em>’s own wrapper doesn’t expose them yet (there’s already an approved FR to fix this, slatted to land in the upcoming v0.31 release, see <a href="https://github.com/borisdali/helpdesk/commit/16a0648ae7d95fd5f0b4d5be9066d14080b5128e">this commit</a>). But for now, as of this writing, the wrapper only has a blanket RECERTIFY_JUDGE=1 toggle, which defaults the judge to whatever HELPDESK_MODEL_NAME / HELPDESK_MODEL_VENDOR happen to be set to at the time. That doesn’t work for this particular exercise because it would silently make the judge and the model under test the same vendor once you swap in Step 3.</p><p>As such, to actually pin a judge that stays constant across both runs, skip the Makefile target and call the CLI directly, setting <em>-judge-model, -judge-vendor </em>and -<em>judge-api-key</em> explicitly:</p><pre>  export HELPDESK_JUDGE_VENDOR=google<br>  export HELPDESK_JUDGE_MODEL=gemini-3.5-flash<br>  export HELPDESK_JUDGE_API_KEY=$GOOGLE_API_KEY</pre><p>(This just shows the shell env vars of convenience here , passed explicitly in the command below, not anything the harness reads directly)</p><h4>Step 3: The actual swap</h4><p>This is often the shortest and the fastest step because the actual model swap is trivial. Just restart the agents with an env var pointing to the new/incoming model:</p><pre># Stop the agents currently running on Gemini<br>  pkill -f &quot;agents/database&quot;<br>  pkill -f &quot;agents/sysadmin&quot;<br><br># Restart them pointed at the new model<br># Here are the simplified instructions for a Database and SysAdmin Agents:<br>  HELPDESK_MODEL_VENDOR=anthropic \<br>  HELPDESK_MODEL_NAME=claude-fable-5-1 \<br>  HELPDESK_API_KEY=$ANTHROPIC_API_KEY \<br>  go run ./agents/database &amp;<br><br>  HELPDESK_MODEL_VENDOR=anthropic \<br>  HELPDESK_MODEL_NAME=claude-fable-5-1 \<br>  HELPDESK_API_KEY=$ANTHROPIC_API_KEY \<br>  go run ./agents/sysadmin &amp;</pre><p>Nothing about the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/PLAYBOOKS.md">Playbook</a> library changed. Nothing about the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/TOOL_REGISTRY.md">Tool Registry</a> changed. You just restarted two processes with a different model. That’s the entire blast radius of a model swap, by design 😉. Now, the above is for running from source, but see specifics of this for your particular platform: <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md#52-host--vm-binary">host</a> (VM/Bare Metal), <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md#53-docker-compose-binary--auto-db">containers</a> (Docker/Podman) and <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md#54-kubernetes-helm">K8s</a>.</p><h4>Step 4: Recertify the new model</h4><p>This is the step that is almost identical to step 1, but on the new model:</p><pre>  HELPDESK_MODEL_VENDOR=anthropic \<br>  HELPDESK_MODEL_NAME=claude-fable-5-1 \<br>  HELPDESK_API_KEY=$ANTHROPIC_API_KEY \<br>  go run ./testing/cmd/faulttest run \<br>    --external --via-gateway \<br>    --gateway $HELPDESK_GATEWAY_URL \<br>    --repeat 5 \<br>    --approval-mode force \<br>    --judge \<br>    --judge-vendor $HELPDESK_JUDGE_VENDOR \<br>    --judge-model $HELPDESK_JUDGE_MODEL \<br>    --judge-api-key $HELPDESK_JUDGE_API_KEY</pre><p>… and get the receipts:</p><pre>  Triage consistency<br>    Fault         : db-lock-contention  (Transaction lock chain / deadlock)<br>    Verdict       : STABLE<br>    Runs          : 5<br>    Pass rate     : 100%<br>    Conf range    : 4pp  (primary hypothesis, passing runs only)<br>    Clean         : yes<br>    Playbook      : pbs_lock_chain_triage<br>    Diagnosis model: claude-fable-5-1<br>    Judge model   : claude-opus-5-5<br>    Tested at     : 2026-10-04 09:15 EDT  (0 days ago)</pre><p>And this is a good receipt! STABLE, 100% pass rate, 4pp confidence spread against Gemini’s 8pp, meaning that the confidence spread is narrow and so the incoming model (Anthropic’s) is more consistent in its diagnosis, averaged across 5 sample runs.</p><p>Same playbook. Same fault. Different model, independently scored by a third model (again, ideally, with the judge that was never swapped). That side-by-side is the whole argument <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">the old post</a> was making, just with the receipt of specific steps instead of the mere assertion.</p><p>Run this across your real fault set, not just one cherry-picked fault. That is, kick off <em>make recertify</em> with no <em>FAULT_IDS</em> filter that runs every <em>external-compatible</em> fault in the catalog [<a href="https://github.com/borisdali/helpdesk/blob/main/testing/catalog/failures.yaml">code link</a>].</p><p>Watch out for any regressions compared to the outgoing Gemini model. Now, the ones that come back <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md#4-stable-vs-unstable-the-criteria">UNSTABLE</a> aren’t a reason to panic and to abandon the swap. They’re your worklist. “This specific playbook is unreliable under this specific new model” is a tuning task. “We think the new model might be worse” is a guess. Don’t guess. Guessing is what leads to questionable or botched model swap projects. Get the numbers instead. And if the worklist happened to be long with many diagnoses worse than your outgoing/Gemini model, consider staying with Gemini (although we are yet to encounter that situation 😉).</p><h4>Step 5: What you’re still not allowed to conclude</h4><p>Here’s the part <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">the original post</a> under-specified and worth being exact about now: a STABLE cert tells you the new model’s reasoning is consistent. And indeed, in our experience of what we see in a field, ditching Gemini often leads to better, more consistent triage results, but it tells you nothing about whether the new model is safe to run <a href="https://medium.com/google-cloud/your-ai-just-diagnosed-the-outage-should-it-fix-it-too-ff6a43ec475f#8176">the remediation</a> and in particular, the destructive operations, be it SQL <em>drop</em> statements, a <em>restart_container</em> or a <em>set_archive_command</em>.</p><p>This is because that was never the model’s call to begin with, on Gemini or on Anthropic. Every write and destructive action still goes through</p><ul><li>the same <a href="https://github.com/borisdali/helpdesk/blob/main/docs/AIGOVERNANCE.md#3-policy-engine">Policy Engine</a> check</li><li>the same <a href="https://github.com/borisdali/helpdesk/blob/main/docs/INFORMED_CONSENT.md">Informed Consent</a> gate</li><li>the same post-action <a href="https://github.com/borisdali/helpdesk/blob/main/docs/OBJECTIVE_EVIDENCE.md">Objective Evidence</a> verification it went through under the old model</li></ul><p>None of that machinery cares which vendor issued the token that proposed the action, because none of it was ever built to trust the model that far. And that’s one of aiHelpDesk <a href="https://github.com/borisdali/helpdesk/blob/main/docs/PRINCIPLES.md#5-the-llm-is-a-reasoning-layer-not-an-execution-layer">core design principles</a>, not an afterthought.</p><p>The one-liner TL;DR: of this whole recipe:</p><ul><li>You proved that for triage purposes the model is replaceable</li><li>You proved that the thing that actually executes, which is a the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/TOOL_REGISTRY.md">Tool Registry</a>, doesn’t care about models and never needs model replacing in the first place 😉</li><li>This is because the model is <em>never</em> the executor</li><li>The model is the <strong>runtime</strong> the playbook runs on. Swap it, and the parts of the system responsible for <em>actually fixing</em> anything in your infrastructure don’t even notice</li></ul><p>And that’s the breakup. Total elapsed time for a model swap, per <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">the original post</a>’s own math: an afternoon, non-engineering affair, not a quarter worth of effort (where you still may feel uncomfortable with no numbers to prove it either way).</p><h3>Mental model: the three layers</h3><p>This section may feel almost orthogonal to the main topic of this post, so if you are here for the Gemini breakup recipe, feel free to skip it altogether, but it may be worth elaborating on the last point that the model in aiHelpDesk is strictly the <strong>runtime layer</strong>, never an executor.</p><p>I failed to make this point clear in <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">the original post</a>, but it’s important to realize that the LLM just reads the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/TOOL_REGISTRY.md">Tool Registry</a>’s <em>tool output</em> (e.g. <em>pg_stat_archiver numbers </em>or <em>pgbackrest info</em> JSON using the examples from <a href="https://itnext.io/when-the-watchman-cant-see-how-a-silent-backup-failure-almost-stayed-silent-forever-98ccc9597043">the backup post</a>), forms a hypothesis and decides to call <em>set_archive_command</em> with a specific value. Everything <strong>after</strong> that decision, i.e. the actual `ALTER SYSTEM SET archive_command = $1; SELECT pg_reload_conf()`, the <a href="http://Policy Engine">Policy Engine</a> check against resource/tag/purpose, the Informed Consent gate that can block the call pending a human’s explicit approval, the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/OBJECTIVE_EVIDENCE.md">Objective Evidence</a> check afterward confirming the claimed effect actually happened… <strong>none of that is the LLM “executing” anything</strong>.</p><p>The actual execution is exclusively the deterministic Go code in the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/TOOL_REGISTRY.md">Tool Registry</a>. The LLM’s output at that point is <a href="https://medium.com/google-cloud/llms-are-functions-not-brains-aihelpdesk-perspective-e12e5432a9ed">a function call</a> it <em>proposes</em>. It never touches the database, the kubectl API or the SSH session directly.</p><p>The reason we built all that AI harness is specifically because something sits between the LLM’s decision and the real-world changes. And that something is where execution actually lives. That something is what makes the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CUSTOMER_RIGHTS.md">Bill of Rights</a> credible: the thing that acts on your infrastructure is auditable, deterministic, policy-gated code, not a stochastic model’s whim.</p><p>So my mental model of aiHelpDesk is three layers:</p><ul><li>🧠 <strong>Knowledge</strong>. The <a href="https://github.com/borisdali/helpdesk/blob/main/docs/PLAYBOOKS.md">Playbook</a> (versioned, stability-certified, stored in the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md">Vault</a>). Static. Doesn’t change per-<a href="https://github.com/borisdali/helpdesk/blob/main/docs/INCIDENTS.md">incident</a></li><li>💡 <strong>Reasoning</strong>. That’s the LLM. Interprets that static knowledge against live, never-identical evidence, forms a hypothesis, picks a playbook and which of the playbook’s pre-approved paths applies (or escalates because none do). This is real, non-trivial work a static playbook can’t do on its own, but it’s <em>deciding</em>, not <em>doing</em></li><li>⚡ <strong>Execution</strong>. The <a href="https://github.com/borisdali/helpdesk/blob/main/docs/TOOL_REGISTRY.md">Tool Registry</a>. Fully deterministic. The <em>only</em> layer that ever touches real infrastructure and the <em>only</em> layer that the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/AIGOVERNANCE.md#3-policy-engine">Policy Engine</a> and the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/OBJECTIVE_EVIDENCE.md">Objective Evidence</a> framework trust</li></ul><p>Collapsing “reasoning” and “execution” into one role and calling it “the LLM is the executor” is simpler, but very coarse and it leads to believe that a model actually has the power and ability to do things. It doesn’t. Whichever word you use for that middle layer (orchestrator, reasoner, interpreter), “executor” is the one label that’s actively misleading and it’s the one claim this project’s entire <a href="https://github.com/borisdali/helpdesk/blob/main/docs/AIGOVERNANCE.md">governance</a> design exists to contradict.</p><p>Try it yourself, take aiHelpDesk for a spin with a <a href="https://github.com/borisdali/helpdesk/blob/main/deploy/docker-compose/DEMO.md">10-minute demo</a>.</p><p>aiHelpDesk is open source. We invented and pioneered the concepts of <strong><em>Operational SRE/DBA Flywheel </em></strong><em>(</em><a href="https://medium.com/google-cloud/your-sre-on-call-runbook-is-already-obsolete-heres-why-that-s-not-your-fault-0a82b3b0183c#7fe7"><em>blog post</em></a><em>, </em><a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#the-operational-sredba-flywheel"><em>doc</em></a><em>), </em>Triage <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md">Consistency Certification</a>, <a href="https://github.com/borisdali/helpdesk/blob/main/docs/ATTRIBUTION_CERTS.md">3D Certs</a>, <a href="https://github.com/borisdali/helpdesk/blob/main/docs/INFORMED_CONSENT.md">Informed Consent</a>, <a href="https://github.com/borisdali/helpdesk/blob/main/docs/SECOND_OPINION.md">Second Opinion</a>, <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CUSTOMER_RIGHTS.md">Bill of Rights</a>, etc. See <a href="https://github.com/borisdali/helpdesk/blob/main/docs/RIGHTS_AND_THE_FLYWHEEL.md">here</a> how the rights mentioned above map to our Flywheel.</p><p>The <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#vault-commands">vault commands</a>, the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/LLM_AS_JUDGE.md">judge</a>, the <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#vault-diff">playbook diff</a>, the full <a href="https://github.com/borisdali/helpdesk/blob/main/docs/AUDIT.md">audit trail</a>, the calibration <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#vault-calibration"><em>data quality banner</em></a>, the model-scoped <a href="https://github.com/borisdali/helpdesk/blob/main/docs/CONSISTENCY.md">stability certs</a> and <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#vault-cert-compare"><em>vault cert-compare</em></a>… are not add-ons. They are the product. <strong>Trust is the product.</strong> The <a href="https://github.com/borisdali/helpdesk/blob/main/docs/JUDGMENT_LAYER.md">judgment layer</a> covers what to do when the AI’s own improvement proposals fail. And why that case is where the most durable operational knowledge gets encoded.</p><h3>Why aiHelpDesk Playbooks are trustworthy?</h3><p>Because we give you, the customer, the ability to vet, verify and improve them through the methodology that we refer to as <strong>Operational SRE/DBA Flywheel</strong>, see <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#the-operational-sredba-flywheel">here</a> and <a href="https://medium.com/google-cloud/your-sre-on-call-runbook-is-already-obsolete-heres-why-that-s-not-your-fault-0a82b3b0183c#7fe7">here</a> for details.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*snCV_27uE6nt34-a.png" /></figure><p>And yes, as a customer, you can not only confirm that the playbooks that you get with aiHelpDesk out of the box work for your environment, but you can easily bring your own. Both: BYO playbooks (by either importing your existing runbooks or cloning and customizing one of our’s or by creating one from scratch) + BYO faults as well.</p><blockquote>Because nobody knows your specific databases, your environment and your workload with your upstream/downstream apps better than you do. You know how your database fails. Vendors don’t. At aiHelpDesk, we give you an option to create your own faults and add your own playbooks to triage and rectify them (in addition to the system playbooks we ship, of course).</blockquote><p>And yes, we don’t depend on a particular model or a model provider. aiHelpDesk is <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">model-neutral</a>. From our standpoint, the LLMs are a <a href="https://medium.com/google-cloud/the-llm-is-the-dumbest-part-of-your-ai-operations-platform-1ac95039cacd">disposable commodity</a>. Flip from Gemini to Anthropic and aiHelpDesk should continue to give you exactly the same diagnosis and remediation. Anything shorter than that is a P0 bug.</p><h3>Related Reading</h3><ul><li>aiHelpDesk Flywheel <a href="https://github.com/borisdali/helpdesk/blob/main/docs/VAULT.md#the-operational-sredba-flywheel">official documentation</a></li><li><a href="https://itnext.io/when-the-watchman-cant-see-how-a-silent-backup-failure-almost-stayed-silent-forever-98ccc9597043">When the Watchman Can’t See: How a Silent Backup Failure Almost Stayed Silent Forever</a>: Your dashboard was green and yet your backups had been dead for two weeks. Nobody lied to you, but nobody asked the right question either</li><li><a href="https://itnext.io/aws-says-its-wrong-not-broken-but-who-does-the-grading-c832d5fbaf8d">AWS Says It’s Wrong, Not Broken. But Who Does the Grading?</a><br>Naming the problem is progress. Grading it with another language model is the same problem wearing a lab coat</li><li><a href="https://levelup.gitconnected.com/your-ai-agent-has-no-alibi-and-it-just-lied-to-you-stop-grading-it-on-whether-it-finished-the-task-7efe31b5ba7a">Your AI Agent Has No Alibi and It Just Lied to You. Stop Grading It on Whether It Finished the Task</a>: A model that fabricates a tool call and still fixes your database isn’t a success story. It’s a governance failure you haven’t found yet. This is a story of a DB agent that narrated a config check it never ran. And a system built to distrust its own AI</li></ul><p>As of this writing, aiHelpDesk is available in Beta. If you run PostgreSQL in production and would like to get help in preparing for <a href="https://medium.com/google-cloud/your-sre-on-call-runbook-is-already-obsolete-heres-why-that-s-not-your-fault-0a82b3b0183c#5634">the avalanche</a>, consider aiHelpDesk. Reach out to us at <a href="mailto: info@aiHelpDesk.biz">info@aiHelpDesk.biz</a> and we’ll be happy to show you what it looks like in practice.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=85b37ad9c669" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/how-to-ditch-gemini-a-step-by-step-breakup-recipe-85b37ad9c669">How to Ditch Gemini: A Step-by-Step Breakup Recipe</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>