<?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: Basavaraj SH</title>
    <description>The latest articles on DEV Community by Basavaraj SH (@basavaraj_sh_1ea7d95f0f2e).</description>
    <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e</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%2F3972738%2F6b40a4fd-25b3-402e-a9db-2dd77e574036.jpg</url>
      <title>DEV Community: Basavaraj SH</title>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/basavaraj_sh_1ea7d95f0f2e"/>
    <language>en</language>
    <item>
      <title>How to Give AI Agents a Safe Sandbox Using Docker</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:13:26 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-to-give-ai-agents-a-safe-sandbox-using-docker-5300</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-to-give-ai-agents-a-safe-sandbox-using-docker-5300</guid>
      <description>&lt;p&gt;AI agents that can execute code, browse files, or run shell commands are powerful - and risky. Docker sandboxes let you hand an agent real execution capability without letting it touch anything it shouldn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disposable Containers as Agent Workspaces
&lt;/h2&gt;

&lt;p&gt;When an AI agent needs to run code or interact with a filesystem, the naive approach is to let it run directly on the host. That works until it doesn't - a runaway loop, an unintended file deletion, or a dependency conflict can wreck your environment.&lt;/p&gt;

&lt;p&gt;The better pattern is to spin up a fresh Docker container per agent task, give it only what it needs, and throw it away when the task is done. Each container provides an isolated workspace: it has its own filesystem, its own process namespace, and no access to host resources unless you explicitly grant them. The agent runs inside it, does its work, and the container is removed. If something goes wrong, the blast radius is one disposable container, not your machine or your production environment.&lt;/p&gt;

&lt;p&gt;This pattern is especially useful for agents that use tool-calling (where the LLM triggers actual function execution) or code interpreter steps - any workflow where the model's output becomes a live command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example: Spin Up and Tear Down an Agent Sandbox
&lt;/h2&gt;

&lt;p&gt;Here's a minimal pattern using the Docker SDK for Python to create a sandboxed execution environment for an agent task:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_env&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_in_sandbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python:3.12-slim&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="n"&gt;mem_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128m&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;network_disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# auto-delete after exit
&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_in_sandbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;print(sum(range(100)))&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 4950
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few details worth noting: &lt;code&gt;network_disabled=True&lt;/code&gt; cuts off outbound calls from inside the container - critical if the agent-generated code might try to exfiltrate data or call external APIs unexpectedly. &lt;code&gt;mem_limit&lt;/code&gt; prevents a runaway process from consuming host memory. &lt;code&gt;remove=True&lt;/code&gt; means the container is deleted the moment it exits, so you're not accumulating stale containers.&lt;/p&gt;

&lt;p&gt;For more complex agent setups (multi-step tasks, file I/O between steps), you can mount a temporary volume for the duration of the task and unmount it afterward, keeping the isolation intact while still allowing artifact passing between agent turns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Giving AI agents a throwaway Docker container per task limits damage from unexpected or malicious code execution.&lt;/li&gt;
&lt;li&gt;Disabling networking and capping memory are the two most important constraints to set from the start - not as an afterthought.&lt;/li&gt;
&lt;li&gt;This pattern works with most agent frameworks (LangChain, LlamaIndex, custom tool-calling loops) since it wraps execution at the infrastructure layer, not inside the framework itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are you currently running agent-generated code directly on the host, or do you already have an isolation layer in place - and if so, what does it look like?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews - Docker Sandboxes discussion (403 points, 258 comments)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>agents</category>
      <category>llm</category>
      <category>python</category>
    </item>
    <item>
      <title>How OpenAI's Tiered Model Strategy Actually Works Under the Hood</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 07 Aug 2026 00:32:53 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-openais-tiered-model-strategy-actually-works-under-the-hood-3gbg</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-openais-tiered-model-strategy-actually-works-under-the-hood-3gbg</guid>
      <description>&lt;p&gt;OpenAI is rolling out GPT-4o "Sol" improvements while expanding "Luna" access to free users - and the split reveals something worth understanding about how AI providers are structuring model tiers in 2025.&lt;/p&gt;

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

&lt;p&gt;Modern AI providers don't ship one model - they ship a spectrum. A "Sol"-style tier typically targets reasoning-heavy tasks: long-context analysis, complex coding, multi-step planning. A "Luna"-style tier is a distilled or capacity-constrained variant optimized for speed and cost at scale.&lt;/p&gt;

&lt;p&gt;The mechanism behind this involves a combination of model distillation (training a smaller model on outputs from a larger one), quantization (reducing numerical precision to shrink compute requirements), and sometimes speculative decoding (using the smaller model to draft tokens the larger one then validates). The result is a family of models that share a lineage but optimize for different latency and cost budgets. The Sol/Luna framing makes the tier explicit to users rather than hiding it behind vague "standard" vs. "advanced" labels - which creates clearer expectations and surfaces a real trade-off decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;If you're building on the API and need to decide which tier fits your use case, a simple benchmark loop can surface the difference quickly:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;prompts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize this 3000-word doc: ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a regex for nested JSON keys&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
 &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;prompts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_tokens&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this against your actual workload - not synthetic benchmarks - before committing to a tier in production. Latency differences often matter more than quality differences for high-throughput pipelines, while quality gaps show up most on reasoning-dense tasks.&lt;/p&gt;

&lt;p&gt;For non-API users: the practical signal is that if Luna is now free, it's worth testing it against whatever you were doing with the paid tier before assuming you need to upgrade. For many content-generation and summarization tasks, the delta is smaller than the pricing difference implies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tiered model families (Sol/Luna style) reflect real architectural differences - distillation, quantization, and compute budgets - not arbitrary feature locks.&lt;/li&gt;
&lt;li&gt;For builders, the right tier decision depends on your task type: reasoning-heavy tasks favor the larger tier, throughput-heavy tasks often don't.&lt;/li&gt;
&lt;li&gt;Explicit tier naming benefits users by making trade-offs visible - watch for this pattern to spread as providers compete on transparency, not just capability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you found a task category where the mini/free tier consistently outperforms expectations - or one where it reliably falls apart?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion - "Improving GPT-4o Sol in ChatGPT, expanding GPT-4o Luna access for free users"&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openai</category>
      <category>python</category>
      <category>api</category>
    </item>
    <item>
      <title>Building a Kubernetes Troubleshooting Agent With LangGraph</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 07 Aug 2026 00:25:18 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/building-a-kubernetes-troubleshooting-agent-with-langgraph-jn9</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/building-a-kubernetes-troubleshooting-agent-with-langgraph-jn9</guid>
      <description>&lt;p&gt;Kubernetes incidents move fast - a pod crash loop at 2am doesn't wait for a human to read five dashboards. An autonomous SRE agent can triage, diagnose, and propose fixes while keeping a human in the approval loop for anything destructive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Pattern: Investigate First, Act With Permission
&lt;/h2&gt;

&lt;p&gt;The safe design uses a two-phase loop. The agent gets read-only tools for observation - &lt;code&gt;kubectl describe&lt;/code&gt;, log fetching, metrics queries - and a separate, gated set of write tools for remediation like scaling deployments or restarting pods. Every write action pauses and waits for explicit human approval before execution.&lt;/p&gt;

&lt;p&gt;This maps cleanly onto LangGraph's &lt;code&gt;interrupt&lt;/code&gt; mechanism, which lets a node in the agent graph pause execution, surface a structured decision to a human reviewer, and resume only on confirmation. The agent can reason over what it finds and generate a targeted fix rather than simply running a fixed runbook - but the blast radius is controlled by that approval gate.&lt;/p&gt;

&lt;p&gt;Tracing is strongly recommended for this kind of agent. Without full visibility into which tool calls the agent made and what it decided at each step, debugging a bad remediation in production is nearly impossible. LangSmith (LangChain's observability layer) or any equivalent tracing setup captures the full execution trace so you can replay what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a simplified LangGraph node that fetches pod status and flags for human review before restarting:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.checkpoint.memory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MemorySaver&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;investigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;pod_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;kubectl_describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pod_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# read-only
&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;diagnosis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_crash_reason&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pod_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;request_approval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="c1"&gt;# interrupt() pauses here; human sees diagnosis + proposed action
&lt;/span&gt; &lt;span class="n"&gt;human_decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;interrupt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;diagnosis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;diagnosis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proposed_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Restart pod &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pod_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;})&lt;/span&gt;
 &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_decision&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remediate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
 &lt;span class="nf"&gt;kubectl_rollout_restart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pod_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# write action
&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;investigate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;investigate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_approval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_approval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remediate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remediate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;investigate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;investigate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_approval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_approval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remediate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;interrupt()&lt;/code&gt; call is what separates an autonomous agent from a fully automated one - it lets the agent do the cognitive heavy lifting while keeping a human accountable for state changes in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Separate read tools from write tools in your agent's toolkit - investigation should never require destructive permissions&lt;/li&gt;
&lt;li&gt;Use an interrupt/approval gate before any action that modifies cluster state, not just the riskiest ones&lt;/li&gt;
&lt;li&gt;Full execution tracing isn't optional for production agents; you need to reconstruct exactly what the agent reasoned and did&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you found a reliable way to set the right granularity for approval gates - per action, per incident, or based on severity thresholds?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: LangChain Blog - "How we built an autonomous SRE agent for Kubernetes"&lt;/em&gt;&lt;/p&gt;

</description>
      <category>langgraph</category>
      <category>kubernetes</category>
      <category>agents</category>
      <category>python</category>
    </item>
    <item>
      <title>Qwen3 235B Tops the Agentic Benchmark - What That Test Actually Measures</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 07 Aug 2026 00:12:48 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/qwen3-235b-tops-the-agentic-benchmark-what-that-test-actually-measures-2hgo</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/qwen3-235b-tops-the-agentic-benchmark-what-that-test-actually-measures-2hgo</guid>
      <description>&lt;p&gt;Agentic benchmarks rank models differently than chat benchmarks do, and the gap between the two scores is now wide enough to matter for real deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agentic Index and Why It Diverges From Chat Leaderboards
&lt;/h2&gt;

&lt;p&gt;Most familiar leaderboards (MMLU, HumanEval, MT-Bench) measure a model's single-turn reasoning or code correctness. The Agentic Index scores something harder: multi-step task completion, where the model must call tools, handle intermediate results, recover from errors, and reach a final goal across many turns - the same loop that runs inside frameworks like LangGraph, AutoGen, or CrewAI.&lt;/p&gt;

&lt;p&gt;Qwen3 235B (a Mixture-of-Experts model, meaning only a fraction of its 235 billion parameters activate per token, keeping inference costs lower than the raw number suggests) recently topped this index. That's notable because the models that score highest on chat benchmarks don't consistently win on agentic tasks. In production workflows, models often excel at single-turn reasoning but struggle when required to plan, call a search tool, interpret results, and loop back across multiple steps.&lt;/p&gt;

&lt;p&gt;The practical implication: if you're building an agent - a pipeline where the model drives tool use rather than just answering questions - benchmark selection should match your actual use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal LangGraph agent setup that lets you swap the underlying model and observe how completion rate changes across a multi-step task:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.prebuilt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_react_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt; &lt;span class="c1"&gt;# swap for any compatible endpoint
&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://your-qwen-endpoint/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen3-235b-a22b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calculator_tool&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Research Q3 revenue trends and summarize top 3 drivers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swap &lt;code&gt;base_url&lt;/code&gt; and &lt;code&gt;model&lt;/code&gt; to point at any OpenAI-compatible endpoint - Ollama, Together AI, Fireworks - and run the same multi-step task. Agentic benchmark gaps become visible fast: a model that writes great prose may stall on tool chaining or repeat a failed call indefinitely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Agentic benchmarks measure multi-turn, tool-using task completion - a fundamentally different capability than single-turn chat or code quality scores.&lt;/li&gt;
&lt;li&gt;Qwen3 235B's MoE architecture keeps per-token compute lower than its parameter count implies, making it more viable for high-throughput agent loops.&lt;/li&gt;
&lt;li&gt;If your workflow involves tool calls, planning steps, or autonomous loops, run your own task-specific eval rather than defaulting to the leaderboard most people quote.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benchmark context shapes build decisions more than most teams realize - which agentic tasks are you actually running in production that a standard eval wouldn't cover?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion thread, Agentic Index leaderboard (referenced in discussion)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>agents</category>
      <category>langgraph</category>
      <category>qwen</category>
    </item>
    <item>
      <title>Choosing Between LangChain, LangGraph, and Deep Agents</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Thu, 06 Aug 2026 23:13:01 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/choosing-between-langchain-langgraph-and-deep-agents-2g29</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/choosing-between-langchain-langgraph-and-deep-agents-2g29</guid>
      <description>&lt;p&gt;Picking the wrong agent framework early can mean a painful rewrite later. Here's how to read the decision fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Distinction
&lt;/h2&gt;

&lt;p&gt;These three frameworks operate at different levels of abstraction, and that's the real axis to choose on - not popularity or GitHub stars.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain&lt;/strong&gt; is a toolkit of composable components: chains, retrievers, prompt templates, memory, tool integrations. It's best for linear or lightly branching workflows - think a RAG pipeline (retrieve relevant documents, then generate an answer) where the steps are mostly predictable. You wire components together, it runs them in sequence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangGraph&lt;/strong&gt; is built on top of LangChain but shifts the mental model from a chain to a stateful graph, where nodes are actions and edges are conditional transitions. You define explicit control flow: if the model requests a tool call, go to node B; if it hits a retry limit, go to node C. This matters the moment your agent needs to loop, branch on its own output, or recover from errors in a structured way. The state is persisted across steps, so you can inspect or interrupt mid-run - critical for human-in-the-loop workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deep Agents&lt;/strong&gt; is a higher-abstraction layer designed for agents that run longer, more autonomous tasks without you hand-coding every state transition. If LangGraph gives you the graph, Deep Agents gives you sensible defaults on top of it - built-in memory, task decomposition, and persistence - so you spend less time on plumbing.&lt;/p&gt;

&lt;p&gt;For fixed sequences of steps, use LangChain. For explicit branching logic and state management, use LangGraph. For long-horizon autonomy with less custom wiring, use Deep Agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal LangGraph state graph in Python showing the branching pattern that LangChain alone can't express cleanly:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
 &lt;span class="n"&gt;needs_tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_node&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;needs_tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llm_node&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call_llm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_node&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call_tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llm_node&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llm_node&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;add_conditional_edges&lt;/code&gt; call is what separates this from a plain LangChain chain - the agent decides its own next step based on state, not a fixed sequence you hard-coded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Choose LangChain for predictable, linear pipelines where the steps don't need to loop back on themselves&lt;/li&gt;
&lt;li&gt;Choose LangGraph when your agent needs conditional branching, retries, or human checkpoints - and you want explicit control over that logic&lt;/li&gt;
&lt;li&gt;Choose Deep Agents when you want longer autonomous runs without writing the full state machine yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are you currently managing branching logic in LangChain with workarounds, or have you already moved that work into LangGraph?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: LangChain Blog - Deep Agents vs LangChain vs LangGraph&lt;/em&gt;&lt;/p&gt;

</description>
      <category>langgraph</category>
      <category>langchain</category>
      <category>agents</category>
      <category>python</category>
    </item>
    <item>
      <title>Human Oversight of AI Agents Failed 33% of the Time in Testing</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Thu, 06 Aug 2026 22:11:45 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/human-oversight-of-ai-agents-failed-33-of-the-time-in-testing-45</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/human-oversight-of-ai-agents-failed-33-of-the-time-in-testing-45</guid>
      <description>&lt;p&gt;When AI agents ask for permission to act, how often do humans actually catch the dangerous ones? A study on AI agent command approval accuracy across 40,000 simulated runs found the answer is: not nearly enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Approval Gap in Agentic AI
&lt;/h2&gt;

&lt;p&gt;Modern AI agents - systems that don't just answer questions but take sequences of actions (browsing, writing files, calling APIs, executing code) - typically include a "human-in-the-loop" checkpoint where a person approves or rejects a proposed command before it runs. The assumption baked into most agent frameworks is that this approval step catches harmful or unintended actions. The study broke that assumption: humans missed roughly one in three genuinely threatening commands when acting as approvers.&lt;/p&gt;

&lt;p&gt;The failure mode isn't carelessness. It's cognitive load and interface design. Approval queues move fast. Commands often look benign in isolation - &lt;code&gt;delete_temp_files()&lt;/code&gt; sounds harmless until you realize "temp" was redefined upstream in the agent's chain. The threat only makes sense in context, and reviewers rarely have that context surfaced to them at the moment of decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a simplified pattern from agentic pipelines where this goes wrong. An agent orchestrating a data cleanup task might generate a tool call like:&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="c1"&gt;# Agent-generated action, presented to human approver
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file_manager&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;processed/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# looks safe
&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recursive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To a reviewer approving dozens of these per session, &lt;code&gt;processed/&lt;/code&gt; sounds like scratch data. What's not shown inline: three steps earlier, the agent symlinked &lt;code&gt;processed/&lt;/code&gt; to a production directory. The approval UI showed the command. It didn't show the chain.&lt;/p&gt;

&lt;p&gt;The fix isn't slower humans - it's better tooling. Agent frameworks like LangGraph and AutoGen support step-level trace logging; show the last N actions &lt;em&gt;alongside&lt;/em&gt; the approval prompt, not buried in a separate log view, to give reviewers the context they need to actually evaluate risk. Some teams are also adding a lightweight secondary model (a "critic" or "red-teamer") that flags high-risk tool calls before they reach human review, so humans spend attention on the ones that actually need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Human-in-the-loop approval is not a reliable safety net by itself - 33% miss rate at scale is a significant risk surface&lt;/li&gt;
&lt;li&gt;The core problem is missing context at decision time, not reviewer intent or effort&lt;/li&gt;
&lt;li&gt;Pairing trace context surfacing with an automated pre-filter (critic model) makes human review meaningfully more effective&lt;/li&gt;
&lt;li&gt;Agent frameworks already have the logging infrastructure to support this - it's largely a UI/UX and workflow design problem, not a new research challenge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tooling to fix this exists today inside most major agent frameworks. The question is whether teams building production agents are actually wiring it up - are you surfacing full action traces to your human approvers, or just the single command?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion, 226 points, 178 comments - study referenced in thread on AI agent command approval accuracy across 40,000 simulated runs&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>llm</category>
      <category>aisafety</category>
      <category>langchain</category>
    </item>
    <item>
      <title>How Open Embedding Models Can Match GPT-Class Retrieval Quality</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Thu, 06 Aug 2026 08:48:53 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-open-embedding-models-can-match-gpt-class-retrieval-quality-45nc</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-open-embedding-models-can-match-gpt-class-retrieval-quality-45nc</guid>
      <description>&lt;p&gt;RAG (Retrieval-Augmented Generation - a pattern where you fetch relevant documents before generating an answer) lives or dies on retrieval quality. A cheaper retrieval stack isn't always a compromise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Retrieval Quality Gap Is Often in the Chunking, Not the Model
&lt;/h2&gt;

&lt;p&gt;Most teams assume the embedding model is the bottleneck when retrieval underperforms. The real culprit is usually upstream: how documents are split before they're embedded. Overlapping chunks with a recursive character splitter, combined with a well-tuned open embedding model like &lt;code&gt;bge-large-en-v1.5&lt;/code&gt; or &lt;code&gt;nomic-embed-text&lt;/code&gt;, can close a surprising amount of the gap against expensive proprietary embeddings - often without touching the LLM layer at all.&lt;/p&gt;

&lt;p&gt;The pattern that tends to work: chunk at a meaningful boundary (paragraph or sentence, not fixed character count), add a small overlap window (10 - 15% of chunk size), then embed with a model that scores well on the MTEB benchmark (Massive Text Embedding Benchmark - a standardized leaderboard for comparing retrieval and semantic similarity models). Many open models in the 1B parameter range sit competitively on MTEB against models costing 100x more per token to call via API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal retrieval setup using LangChain with a local open embedding model via Ollama:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.embeddings&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OllamaEmbeddings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Chroma&lt;/span&gt;

&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;separators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_documents&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;your_text&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaEmbeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nomic-embed-text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;vectorstore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Chroma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vectorstore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;similarity_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your query here&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swapping &lt;code&gt;nomic-embed-text&lt;/code&gt; for &lt;code&gt;bge-large-en-v1.5&lt;/code&gt; (via HuggingFace) takes one line change. Running both against your actual dataset on a held-out set of queries - not a synthetic benchmark - is the fastest way to know which one fits your domain.&lt;/p&gt;

&lt;p&gt;The cost difference is real: embedding a million tokens locally via Ollama is effectively free after the initial model pull, versus measurable per-call costs at API scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Chunking strategy (boundary type + overlap) affects retrieval quality at least as much as the embedding model choice - fix this before swapping models.&lt;/li&gt;
&lt;li&gt;Open embedding models in the 1B range score competitively on MTEB and run locally or on modest GPU instances.&lt;/li&gt;
&lt;li&gt;Evaluate retrieval quality on your own queries, not just published benchmarks - domain-specific retrieval patterns differ from general benchmarks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've swapped embedding models in a production RAG pipeline, which metric did you actually use to confirm the quality change - cosine similarity threshold, end-task accuracy, or something else?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion - "Beating GPT-5.6 Sol on retrieval with 100x cheaper open models", MTEB Leaderboard (Hugging Face)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rag</category>
      <category>embeddings</category>
      <category>llm</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Audit AI-Generated Content Before It Shapes Your Opinion</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Mon, 03 Aug 2026 10:01:47 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-to-audit-ai-generated-content-before-it-shapes-your-opinion-55d6</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-to-audit-ai-generated-content-before-it-shapes-your-opinion-55d6</guid>
      <description>&lt;h2&gt;
  
  
  The Detection Problem
&lt;/h2&gt;

&lt;p&gt;AI-written articles, especially those produced at scale to push a particular narrative, can pass casual reading tests with ease. What gives them away is pattern, not grammar: suspiciously uniform sentence rhythm, missing primary sources, no named journalists with a searchable byline, and publication dates that cluster around news events in ways that suggest reactive content farming rather than original reporting.&lt;/p&gt;

&lt;p&gt;The deeper issue is &lt;em&gt;provenance opacity&lt;/em&gt; - you often can't tell who funded the content, what incentive sits behind it, or whether the "news site" has any editorial independence from the organization it covers (or attacks). This matters especially when the content targets specific individuals or companies in a competitive or regulatory space, where financial incentives to shape public perception are high.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;You don't need a specialized tool to run a basic credibility audit. A structured prompt against any article - fed into an LLM you trust - can surface red flags fast:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a media literacy analyst. Review the following article and output:
1. Named authors with verifiable professional history (yes/no + details)
2. Primary sources cited vs. secondary or no sources
3. Emotional or loaded language count (flag phrases)
4. Publication date relative to the news event it covers
5. Ownership/funding disclosure present (yes/no)

Article: [paste article text here]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this as a system prompt with the article as user input in any chat-based LLM interface or via API. The output won't be perfect, but it creates a forcing function - you're making the audit explicit rather than relying on gut feel. For teams processing a lot of external content (market research, competitive intelligence, policy tracking), this kind of lightweight pipeline can be automated or coded into a simple script that batches articles and logs flag counts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Provenance and funding disclosure are the clearest signals of editorial independence; their absence is a flag worth taking seriously.&lt;/li&gt;
&lt;li&gt;A structured LLM-based audit prompt is a practical, low-effort way to make credibility checks systematic rather than intuitive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you're doing competitive research or tracking industry commentary, how are you currently verifying whether a source has an undisclosed stake in the narrative it's publishing?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion thread, 179 points&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>medialiteracy</category>
      <category>aitools</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>How MCP Reconnected a Developer's Broken AI Workflow</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Sun, 02 Aug 2026 09:26:24 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-mcp-reconnected-a-developers-broken-ai-workflow-3del</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-mcp-reconnected-a-developers-broken-ai-workflow-3del</guid>
      <description>&lt;p&gt;Model Context Protocol (MCP) - the open standard for letting AI models talk to external tools and data sources - has gone from "interesting spec" to "actually useful" faster than most people expected. The shift is visible in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Shift: From One-Shot Prompts to Connected Context
&lt;/h2&gt;

&lt;p&gt;AI workflows often operate with manual handoffs: you paste text in, get text out, carry results from one tool to the next. MCP offers an alternative - a structured way for a model to call tools, read files, query APIs, and pass context across steps. The protocol defines a client-server model where your AI host (Claude Desktop, a custom agent, a VS Code extension) connects to MCP servers that expose specific capabilities. Each server declares what tools it offers, and the model decides when to invoke them. A workflow where "go check the database, then update the doc, then file the ticket" can happen in one session rather than three copy-paste cycles becomes possible.&lt;/p&gt;

&lt;p&gt;The practical growth in MCP adoption has been enabled by the growing ecosystem of pre-built servers for common tools (GitHub, Postgres, Slack, filesystem access) that make the setup fast enough to actually reach for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal MCP server in Python using the official SDK that exposes one tool - a word count check a content editor or PM might actually want during a review workflow:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.server.fastmcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastMCP&lt;/span&gt;

&lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastMCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content-tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@mcp.tool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;word_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Count words and flag if over 500.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
 &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;over_limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it with &lt;code&gt;python server.py&lt;/code&gt;, point your MCP-compatible client at it, and the model can now call &lt;code&gt;word_count&lt;/code&gt; mid-conversation - no plugin store, no custom API wrapper, no manual copy-paste. Add a second &lt;code&gt;@mcp.tool()&lt;/code&gt; for a readability score, a Postgres query, or a Jira ticket creator, and the same pattern scales.&lt;/p&gt;

&lt;p&gt;The key insight: you're not building an agent framework from scratch. You're writing small, testable functions and letting the protocol handle when and how the model calls them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MCP standardizes tool-calling so AI models can pull live context and take actions without manual handoffs between steps&lt;/li&gt;
&lt;li&gt;Pre-built MCP servers for GitHub, databases, and file systems mean you can connect an existing workflow in minutes rather than days&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;FastMCP&lt;/code&gt; Python SDK reduces server setup to decorated functions - accessible for data scientists and engineers alike, not just AI infra teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern is simple enough that a solo freelancer and a five-person product team can both reach for it - what matters is knowing which tool connection would actually save you the most friction.&lt;/p&gt;

&lt;p&gt;If you've tried wiring MCP into an existing workflow, which server or tool integration turned out to be genuinely useful versus more trouble than it was worth?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: Simon Willison's July 2026 Newsletter, MCP Python SDK documentation (modelcontextprotocol.io)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>python</category>
      <category>llm</category>
      <category>agents</category>
    </item>
    <item>
      <title>How the EU AI Act's Risk Tiers Actually Classify Your AI System</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 31 Jul 2026 13:55:24 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-the-eu-ai-acts-risk-tiers-actually-classify-your-ai-system-56l8</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-the-eu-ai-acts-risk-tiers-actually-classify-your-ai-system-56l8</guid>
      <description>&lt;p&gt;The EU AI Act isn't just incoming regulation - it classifies AI systems by risk and sorts what you're required to build, document, and prove before you ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Risk Tier System and What It Requires
&lt;/h2&gt;

&lt;p&gt;The Act sorts AI systems into four risk tiers: unacceptable risk (banned outright), high risk, limited risk, and minimal risk. Most teams building internal tools, chatbots, or recommendation features land in the &lt;strong&gt;limited or minimal risk&lt;/strong&gt; buckets - which carry light obligations, mostly around transparency (telling users they're interacting with AI).&lt;/p&gt;

&lt;p&gt;The tier that demands real engineering attention is &lt;strong&gt;high risk&lt;/strong&gt;. Systems in this category include AI used in hiring, credit scoring, education assessment, critical infrastructure, and healthcare triage. If your product touches any of those domains, you're looking at mandatory conformity assessments, human oversight mechanisms, detailed technical documentation, logging of system outputs, and data governance requirements before you can legally deploy in the EU.&lt;/p&gt;

&lt;p&gt;High-risk systems must be built to support auditability from the start - not retrofitted. That means logging inputs and outputs with enough context to reconstruct decisions, building in a kill switch or human override, and maintaining a risk register that maps each failure mode to a mitigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal logging pattern for a high-risk AI decision endpoint - the kind of audit trail the Act expects to exist:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_ai_decision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;decision_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_hash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;model_output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;human_reviewed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="c1"&gt;# Write to append-only store (e.g., S3, BigQuery, audit DB)
&lt;/span&gt; &lt;span class="n"&gt;audit_log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't compliance theatre - it's the minimum scaffold you need to answer "what did your system decide, and why, on date X?" - a question regulators can ask. The &lt;code&gt;human_reviewed&lt;/code&gt; flag signals where oversight happened and where it didn't.&lt;/p&gt;

&lt;p&gt;For non-technical roles: think of this as a receipt system for every AI decision your product makes. Without it, you can't demonstrate accountability after the fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The EU AI Act's impact on your team depends almost entirely on which risk tier your use case falls into - mapping that early saves rework later.&lt;/li&gt;
&lt;li&gt;High-risk AI systems require audit logging, human override mechanisms, and pre-deployment conformity assessments - these aren't add-ons, they're architectural requirements.&lt;/li&gt;
&lt;li&gt;Products in limited or minimal risk tiers mostly just need to disclose that they're AI-powered - a much lower bar, but still a legal one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're currently building an AI feature for a regulated domain, what's your team's current approach to logging model decisions in a way that could survive a compliance review?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: OpenAI Blog - Advancing responsible AI across Europe; EU AI Act official text summary (European Parliament)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>euaiact</category>
      <category>llm</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>LangSmith LLM Gateway Adds Spend Limits and PII Redaction at Runtime</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 31 Jul 2026 10:49:48 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/langsmith-llm-gateway-adds-spend-limits-and-pii-redaction-at-runtime-3f10</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/langsmith-llm-gateway-adds-spend-limits-and-pii-redaction-at-runtime-3f10</guid>
      <description>&lt;p&gt;AI agents that can call LLMs freely are a budget and compliance risk waiting to happen. LangSmith's new LLM Gateway addresses both without forcing you to rewrite your agent logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea: Governance as Infrastructure, Not Afterthought
&lt;/h2&gt;

&lt;p&gt;Most teams bolt on cost controls and data-privacy rules after something goes wrong - a runaway agent burns $400 in a weekend, or a support bot logs a customer's social security number into a trace. The LangSmith LLM Gateway moves those guardrails into the request path itself, sitting between your agent and the underlying model provider.&lt;/p&gt;

&lt;p&gt;Spend limits are blocked at runtime - meaning an agent that exceeds its token budget stops before the API call goes out, not after you audit last month's invoice. PII redaction works the same way: sensitive patterns are stripped from the request and from the stored trace, so the compliance problem never reaches the model or the log in the first place. Crucially, trace continuity is preserved, so you still get full observability - you can see what the agent tried to do, just with the sensitive fields masked rather than missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example: Wiring a Spend Limit Into Your Chain
&lt;/h2&gt;

&lt;p&gt;If you're already using LangChain + LangSmith, the gateway integrates at the client initialization level. A minimal setup looks roughly like this:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ls-...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;gateway_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spend_limit_usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# hard stop per session/agent run
&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pii_redaction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# strip emails, SSNs, phone numbers
&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fallback_on_limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# or "warn" to log and continue
&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the gateway is in place, every LLM call your agent makes flows through it. The spend counter increments per token usage; hitting the ceiling raises a controlled exception your agent can catch and handle gracefully - returning a partial result or escalating to a human - instead of silently running up charges. PII redaction runs on both the outbound prompt and the inbound completion before either touches the LangSmith trace store.&lt;/p&gt;

&lt;p&gt;This is particularly useful for Forward Deployed Engineers shipping agents to enterprise customers who have strict data-handling requirements baked into their contracts, and for product teams running multi-agent workflows where a single misconfigured node could drain a shared budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Runtime governance means the guardrail executes &lt;em&gt;during&lt;/em&gt; the agent's API call, not in a post-hoc audit - which is the only layer that actually prevents harm.&lt;/li&gt;
&lt;li&gt;PII redaction at the gateway level keeps sensitive data out of your trace store, which directly reduces compliance surface area without sacrificing observability.&lt;/li&gt;
&lt;li&gt;Spend limits paired with a configurable fallback give agents a graceful degradation path instead of an uncontrolled failure or an unlimited bill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're already tracking agent runs in LangSmith, what's your current approach to capping per-run LLM spend - token budget in the prompt, external middleware, or something else?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: LangChain Blog - LangSmith LLM Gateway announcement&lt;/em&gt;&lt;/p&gt;

</description>
      <category>langchain</category>
      <category>llm</category>
      <category>agents</category>
      <category>observability</category>
    </item>
    <item>
      <title>How to Detect and Handle API Outages Gracefully in AI-Powered Apps</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Thu, 30 Jul 2026 13:58:50 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-to-detect-and-handle-api-outages-gracefully-in-ai-powered-apps-4enf</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/how-to-detect-and-handle-api-outages-gracefully-in-ai-powered-apps-4enf</guid>
      <description>&lt;p&gt;When a major LLM provider goes down, your app shouldn't. Elevated error rates across model APIs are a when, not an if - so the resilience layer matters as much as the integration itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea: Circuit Breakers and Fallback Chains
&lt;/h2&gt;

&lt;p&gt;Most teams wire up an LLM API and handle errors with a basic try/except. That works fine until a real outage hits - then every request hangs or fails hard, and users see a broken product instead of a graceful degradation.&lt;/p&gt;

&lt;p&gt;The pattern worth building is a &lt;strong&gt;fallback chain with a circuit breaker&lt;/strong&gt;. Track consecutive failures, and once a threshold is crossed, stop hammering the primary provider and route to a backup - whether that's a different provider, a cached response, or a simplified deterministic answer. A circuit breaker (a pattern borrowed from distributed systems) sits in front of your API call and activates when failure rate spikes, protecting your app from compounding timeouts.&lt;/p&gt;

&lt;p&gt;The two pieces together - fallback routing and circuit breaking - let you serve something useful even during a full provider outage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal Python pattern using &lt;code&gt;tenacity&lt;/code&gt; for retries and a simple circuit breaker flag, with provider fallback:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tenacity&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop_after_attempt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait_exponential&lt;/span&gt;

&lt;span class="n"&gt;CIRCUIT_OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;FAILURE_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;THRESHOLD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_primary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
 &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;stop_after_attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;wait_exponential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_fallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
 &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;CIRCUIT_OPEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FAILURE_COUNT&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;CIRCUIT_OPEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call_primary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="n"&gt;FAILURE_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
 &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;FAILURE_COUNT&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;FAILURE_COUNT&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;THRESHOLD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;CIRCUIT_OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;call_fallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In production you'd replace the global flags with something like &lt;code&gt;pybreaker&lt;/code&gt; or a Redis-backed counter so the state persists across workers. The routing logic stays the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;API outages from any LLM provider are recurring events - building for them upfront is cheaper than scrambling during one.&lt;/li&gt;
&lt;li&gt;A circuit breaker prevents cascading timeouts by stopping requests to a failing endpoint once a failure threshold is hit.&lt;/li&gt;
&lt;li&gt;A fallback chain (primary provider → secondary provider → cached/static response) keeps your product functional at degraded quality rather than fully broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you actually tested your LLM integration with the primary endpoint completely unreachable - what happened?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion on Claude elevated errors incident, Anthropic status page&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>llm</category>
      <category>api</category>
      <category>resilience</category>
    </item>
  </channel>
</rss>
