<?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</title>
    <description>The most recent home feed on DEV Community.</description>
    <link>https://dev.to</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed"/>
    <language>en</language>
    <item>
      <title>React Mastery Series – Day 22: State Management with Redux Toolkit – Building Enterprise React Applications</title>
      <dc:creator>Siva Samanthapudi</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:01:03 +0000</pubDate>
      <link>https://dev.to/siva_samanthapudi/react-mastery-series-day-22-state-management-with-redux-toolkit-building-enterprise-react-31eh</link>
      <guid>https://dev.to/siva_samanthapudi/react-mastery-series-day-22-state-management-with-redux-toolkit-building-enterprise-react-31eh</guid>
      <description>&lt;p&gt;Welcome back to the &lt;strong&gt;React Mastery Series&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;In the previous article, we explored &lt;strong&gt;TypeScript with React&lt;/strong&gt; and learned how static typing improves code quality, developer productivity, and application reliability.&lt;/p&gt;

&lt;p&gt;Today, we're diving into one of the most requested topics in React interviews and one of the most widely used state management solutions in enterprise applications:&lt;/p&gt;

&lt;h1&gt;
  
  
  Redux Toolkit (RTK)
&lt;/h1&gt;

&lt;p&gt;If you've ever wondered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why do we need Redux when React already has Context API?&lt;/li&gt;
&lt;li&gt;What problems does Redux solve?&lt;/li&gt;
&lt;li&gt;Why is Redux Toolkit preferred over traditional Redux?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article answers all of those questions.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Do We Need Redux?
&lt;/h1&gt;

&lt;p&gt;Imagine you're building an enterprise banking application.&lt;/p&gt;

&lt;p&gt;It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login&lt;/li&gt;
&lt;li&gt;Dashboard&lt;/li&gt;
&lt;li&gt;Accounts&lt;/li&gt;
&lt;li&gt;Transactions&lt;/li&gt;
&lt;li&gt;Beneficiaries&lt;/li&gt;
&lt;li&gt;Profile&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many screens need the same data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logged-in user&lt;/li&gt;
&lt;li&gt;Authentication token&lt;/li&gt;
&lt;li&gt;Customer profile&lt;/li&gt;
&lt;li&gt;Theme&lt;/li&gt;
&lt;li&gt;Permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without centralized state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Component A
     |
Component B
     |
Component C
     |
Component D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each component manages its own copy of the data.&lt;/p&gt;

&lt;p&gt;Problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate API calls&lt;/li&gt;
&lt;li&gt;Inconsistent state&lt;/li&gt;
&lt;li&gt;Difficult debugging&lt;/li&gt;
&lt;li&gt;Complex data flow&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Context API vs Redux
&lt;/h1&gt;

&lt;p&gt;Many developers ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why not just use Context API?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Context works well for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Theme&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Language&lt;/li&gt;
&lt;li&gt;User preferences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, for applications with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent state updates&lt;/li&gt;
&lt;li&gt;Large datasets&lt;/li&gt;
&lt;li&gt;Complex business logic&lt;/li&gt;
&lt;li&gt;Multiple developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Redux provides better scalability and tooling.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context API&lt;/th&gt;
&lt;th&gt;Redux Toolkit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Good for simple shared state&lt;/td&gt;
&lt;td&gt;Designed for complex state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic state sharing&lt;/td&gt;
&lt;td&gt;Predictable state management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Limited debugging&lt;/td&gt;
&lt;td&gt;Excellent DevTools support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimal boilerplate&lt;/td&gt;
&lt;td&gt;Simplified with RTK&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  What is Redux?
&lt;/h1&gt;

&lt;p&gt;Redux is a predictable state management library.&lt;/p&gt;

&lt;p&gt;It stores application state in one central location called:&lt;/p&gt;

&lt;h1&gt;
  
  
  Store
&lt;/h1&gt;

&lt;p&gt;Instead of multiple components managing separate state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header

Dashboard

Profile

Sidebar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything reads from one source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Store
             |
   --------------------------
   |      |       |        |
Header Dashboard Profile Sidebar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Core Redux Concepts
&lt;/h1&gt;

&lt;p&gt;Redux is built around four ideas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Store
  ↓
Action
  ↓
Reducer
  ↓
Updated State
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand each one.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is a Store?
&lt;/h1&gt;

&lt;p&gt;The Store is the central container for your application's state.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Store
├── auth
├── user
├── transactions
├── accounts
└── settings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every component reads data from the Store.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is an Action?
&lt;/h1&gt;

&lt;p&gt;An Action describes &lt;strong&gt;what happened&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LOGIN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ADD_TRANSACTION&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&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;Notice:&lt;/p&gt;

&lt;p&gt;Actions never update state directly.&lt;/p&gt;

&lt;p&gt;They simply describe an event.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is a Reducer?
&lt;/h1&gt;

&lt;p&gt;A Reducer decides how state changes.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current State
      +
   Action
      ↓
  New State
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reducers must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be pure functions&lt;/li&gt;
&lt;li&gt;Never mutate existing state&lt;/li&gt;
&lt;li&gt;Always return new state&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Traditional Redux vs Redux Toolkit
&lt;/h1&gt;

&lt;p&gt;Older Redux required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Action creators&lt;/li&gt;
&lt;li&gt;Constants&lt;/li&gt;
&lt;li&gt;Reducers&lt;/li&gt;
&lt;li&gt;Store configuration&lt;/li&gt;
&lt;li&gt;Boilerplate code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;actions.js
constants.js
reducers.js
store.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redux Toolkit removes most of this boilerplate.&lt;/p&gt;




&lt;h1&gt;
  
  
  Installing Redux Toolkit
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @reduxjs/toolkit react-redux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@reduxjs/toolkit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;react-redux&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all you need for most applications.&lt;/p&gt;




&lt;h1&gt;
  
  
  Creating the Store
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;authReducer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./authSlice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authReducer&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;&lt;code&gt;configureStore()&lt;/code&gt; automatically enables useful defaults like Redux DevTools and middleware.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is a Slice?
&lt;/h1&gt;

&lt;p&gt;A Slice groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;Reducers&lt;/li&gt;
&lt;li&gt;Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;into one file.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;authSlice.ts
├── Initial State
├── Reducers
└── Generated Actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the biggest improvement introduced by Redux Toolkit.&lt;/p&gt;




&lt;h1&gt;
  
  
  Creating Your First Slice
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSlice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;logout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;authSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;authSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice:&lt;/p&gt;

&lt;p&gt;We appear to modify state directly.&lt;/p&gt;

&lt;p&gt;Redux Toolkit uses &lt;strong&gt;Immer&lt;/strong&gt; internally, so immutable updates happen automatically.&lt;/p&gt;




&lt;h1&gt;
  
  
  Providing the Store
&lt;/h1&gt;

&lt;p&gt;Wrap the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every component can access Redux state.&lt;/p&gt;




&lt;h1&gt;
  
  
  Reading State
&lt;/h1&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Store
     ↓
useSelector()
     ↓
 Component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Updating State
&lt;/h1&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Siva&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Button Click
         ↓
    dispatch()
         ↓
     Reducer
         ↓
   Store Updated
         ↓
Component Re-renders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Enterprise Authentication Flow
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Login Form
     ↓
Authentication API
     ↓
dispatch(login())
     ↓
Redux Store
     ↓
Navbar Updates
     ↓
Dashboard Updates
     ↓
Profile Updates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every component immediately receives the updated user information.&lt;/p&gt;




&lt;h1&gt;
  
  
  Async API Calls with createAsyncThunk
&lt;/h1&gt;

&lt;p&gt;Most applications fetch data from APIs.&lt;/p&gt;

&lt;p&gt;Redux Toolkit provides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createAsyncThunk()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAsyncThunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users/fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;Redux automatically generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pending&lt;/li&gt;
&lt;li&gt;Fulfilled&lt;/li&gt;
&lt;li&gt;Rejected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;states.&lt;/p&gt;




&lt;h1&gt;
  
  
  Handling Async States
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    API Request
         ↓
     Pending
         ↓
Success OR Failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typical state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for enterprise applications.&lt;/p&gt;




&lt;h1&gt;
  
  
  Folder Structure
&lt;/h1&gt;

&lt;p&gt;A scalable Redux Toolkit project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src

├── app
│   └── store.ts
│
├── features
│   ├── auth
│   │   └── authSlice.ts
│   │
│   ├── users
│   │   └── userSlice.ts
│   │
│   └── transactions

│       └── transactionSlice.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each feature owns its own Redux logic.&lt;/p&gt;




&lt;h1&gt;
  
  
  Real-World Banking Example
&lt;/h1&gt;

&lt;p&gt;Imagine a customer logs in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Login
     ↓
dispatch(login())
     ↓
Store Updated
     ↓
Header

Sidebar

Dashboard

Profile

Notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every screen instantly reflects the new authentication state.&lt;/p&gt;




&lt;h1&gt;
  
  
  Redux DevTools
&lt;/h1&gt;

&lt;p&gt;One of Redux's biggest advantages is debugging.&lt;/p&gt;

&lt;p&gt;You can inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every action&lt;/li&gt;
&lt;li&gt;Previous state&lt;/li&gt;
&lt;li&gt;New state&lt;/li&gt;
&lt;li&gt;Action payload&lt;/li&gt;
&lt;li&gt;State history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    LOGIN
      ↓
FETCH_ACCOUNTS
      ↓
ADD_BENEFICIARY
      ↓
   LOGOUT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes debugging much easier than scattered component state.&lt;/p&gt;




&lt;h1&gt;
  
  
  Common Mistakes
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Putting Everything in Redux
&lt;/h2&gt;

&lt;p&gt;Not all state belongs in the Store.&lt;/p&gt;

&lt;p&gt;Avoid storing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modal visibility&lt;/li&gt;
&lt;li&gt;Form input values&lt;/li&gt;
&lt;li&gt;Tooltip state&lt;/li&gt;
&lt;li&gt;Local UI toggles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;code&gt;useState()&lt;/code&gt; for component-specific state.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Mutating State Outside Redux Toolkit
&lt;/h2&gt;

&lt;p&gt;Incorrect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;outside a reducer.&lt;/p&gt;

&lt;p&gt;Always update state through Redux actions.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Creating One Huge Slice
&lt;/h2&gt;

&lt;p&gt;Avoid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appSlice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Orders&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;Theme&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;authSlice

userSlice

transactionSlice

themeSlice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep slices focused.&lt;/p&gt;




&lt;h1&gt;
  
  
  Best Practices
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Organize Redux by feature.&lt;/li&gt;
&lt;li&gt;Keep slices small and focused.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;createAsyncThunk()&lt;/code&gt; for API requests.&lt;/li&gt;
&lt;li&gt;Keep UI state local.&lt;/li&gt;
&lt;li&gt;Use Redux DevTools during development.&lt;/li&gt;
&lt;li&gt;Prefer Redux Toolkit over traditional Redux.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Key Takeaways
&lt;/h1&gt;

&lt;p&gt;Today, we learned:&lt;/p&gt;

&lt;p&gt;✅ Redux provides centralized state management.&lt;br&gt;
✅ Redux Toolkit significantly reduces Redux boilerplate.&lt;br&gt;
✅ A Slice combines state, reducers, and actions.&lt;br&gt;
✅ &lt;code&gt;useSelector()&lt;/code&gt; reads data from the Store.&lt;br&gt;
✅ &lt;code&gt;useDispatch()&lt;/code&gt; sends actions to update state.&lt;br&gt;
✅ &lt;code&gt;createAsyncThunk()&lt;/code&gt; simplifies asynchronous API calls.&lt;br&gt;
✅ Redux Toolkit is the preferred Redux approach for modern React applications.&lt;/p&gt;




&lt;h1&gt;
  
  
  Coming Next 🚀
&lt;/h1&gt;

&lt;p&gt;In &lt;strong&gt;Day 23&lt;/strong&gt;, we will explore:&lt;/p&gt;

&lt;h1&gt;
  
  
  API Integration in React – Fetch, Axios, Error Handling &amp;amp; Best Practices
&lt;/h1&gt;

&lt;p&gt;We will learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch API vs Axios&lt;/li&gt;
&lt;li&gt;GET, POST, PUT, DELETE requests&lt;/li&gt;
&lt;li&gt;Request interceptors&lt;/li&gt;
&lt;li&gt;Response interceptors&lt;/li&gt;
&lt;li&gt;Authentication tokens&lt;/li&gt;
&lt;li&gt;Global error handling&lt;/li&gt;
&lt;li&gt;Loading and retry strategies&lt;/li&gt;
&lt;li&gt;Enterprise API architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of the next article, you'll know how production React applications communicate securely and efficiently with backend services.&lt;/p&gt;

&lt;p&gt;Happy Coding! 🚀&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactjsdevelopment</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Micro AI Code Reviewer in Rust: Lessons from 'ratatop' with Unsafe and System Metrics</title>
      <dc:creator>Tamiz Uddin</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:00:51 +0000</pubDate>
      <link>https://dev.to/tamizuddin/building-a-micro-ai-code-reviewer-in-rust-lessons-from-ratatop-with-unsafe-and-system-metrics-2o7f</link>
      <guid>https://dev.to/tamizuddin/building-a-micro-ai-code-reviewer-in-rust-lessons-from-ratatop-with-unsafe-and-system-metrics-2o7f</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://tamiz.pro/insights/micro-ai-code-reviewer-rust-unsafe-system-metrics" rel="noopener noreferrer"&gt;tamiz.pro&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the world of CI/CD, AI-powered code review tools are becoming ubiquitous. However, most of these solutions are heavyweight Python or Node.js services that introduce significant latency into the pull request workflow. They often suffer from cold starts, high memory footprints, and non-deterministic execution times. &lt;/p&gt;

&lt;p&gt;This deep dive explores the architecture and engineering decisions behind &lt;strong&gt;ratatop&lt;/strong&gt;, a micro AI code reviewer designed to run locally or in lightweight containers on every commit. Built entirely in &lt;strong&gt;Rust&lt;/strong&gt;, the project prioritizes deterministic low-latency execution, zero-copy memory management for large diffs, and deep integration with system-level metrics. We will dissect how we leveraged &lt;code&gt;unsafe&lt;/code&gt; blocks for performance-critical paths and how we integrated &lt;code&gt;prometheus&lt;/code&gt; and &lt;code&gt;libbpf&lt;/code&gt; to monitor the reviewer's impact on the host system in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: Why Rust for AI Tooling?
&lt;/h2&gt;

&lt;p&gt;Before diving into the code, it is crucial to understand why Rust was chosen over more traditional languages for this specific use case. While Python is the lingua franca of AI/ML, it is often too slow and memory-inefficient for high-throughput, low-latency system tooling.&lt;/p&gt;

&lt;p&gt;Rust offers three distinct advantages for building a micro AI reviewer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Zero-Cost Abstractions:&lt;/strong&gt; The ability to write high-level logic (like AST traversal or LLM prompt construction) without sacrificing the performance of C/C++. This is critical when processing large code diffs where memory allocation overhead can become a bottleneck.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Memory Safety without Garbage Collection:&lt;/strong&gt; Unlike Java or Go, Rust does not have a garbage collector (GC). This eliminates "stop-the-world" pauses that can jitter latency, ensuring that the code review process remains predictable even under load.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Interoperability with C/C++ Libraries:&lt;/strong&gt; Many high-performance diffing algorithms (like those used in &lt;code&gt;libgit2&lt;/code&gt; or &lt;code&gt;unidiff&lt;/code&gt;) are written in C or C++. Rust’s Foreign Function Interface (FFI) allows us to call these libraries directly, avoiding the need to rewrite complex low-level logic in Rust.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Zero-Copy Diff Processing with Unsafe Blocks
&lt;/h2&gt;

&lt;p&gt;One of the most performance-critical components of any code reviewer is the diff parser. When a developer pushes a commit with thousands of lines changed, parsing the diff, extracting context, and feeding it to an LLM can be expensive in terms of memory allocations.&lt;/p&gt;

&lt;p&gt;In Python, parsing a large diff often involves creating numerous string objects, leading to significant memory churn. In Rust, we can avoid this by using &lt;strong&gt;zero-copy&lt;/strong&gt; techniques, primarily through &lt;code&gt;unsafe&lt;/code&gt; blocks. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: String Allocations
&lt;/h3&gt;

&lt;p&gt;Consider the following naive approach to extracting a changed line from a diff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Naive approach - creates many allocations&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;extract_changes_naive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;diff_text&lt;/span&gt;
        &lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="nf"&gt;.starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&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;line&lt;/span&gt;&lt;span class="nf"&gt;.starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// Allocates a new String for each line&lt;/span&gt;
        &lt;span class="nf"&gt;.collect&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;This function allocates memory for every changed line. In a large diff with 10,000 changes, this results in 10,000 heap allocations. While modern allocators are fast, this overhead adds up, especially when processing multiple files concurrently.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Zero-Copy Slices
&lt;/h3&gt;

&lt;p&gt;Instead of creating new &lt;code&gt;String&lt;/code&gt; objects, we can work directly with &lt;code&gt;&amp;amp;str&lt;/code&gt; slices that point to the original buffer. This eliminates heap allocations entirely. However, if the diff data comes from a C library via FFI, we might receive a &lt;code&gt;*mut c_char&lt;/code&gt; (a raw pointer to a C string). Converting this safely requires &lt;code&gt;unsafe&lt;/code&gt; code.&lt;/p&gt;

&lt;p&gt;Here is how we implemented a zero-copy diff extractor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/// Extracts changed lines from a C-style diff buffer without allocating new strings.&lt;/span&gt;
&lt;span class="cd"&gt;/// Returns slices pointing directly into the original buffer.&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;extract_changes_zero_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Safety: We assume diff_buffer is a valid, null-terminated C string&lt;/span&gt;
        &lt;span class="c1"&gt;// and that the lifetime of the returned slices does not exceed the buffer's lifetime.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;diff_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="nf"&gt;.to_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;diff_text&lt;/span&gt;
            &lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="nf"&gt;.starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&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;line&lt;/span&gt;&lt;span class="nf"&gt;.starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// Returns a &amp;amp;str slice, no allocation&lt;/span&gt;
            &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;()&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;h4&gt;
  
  
  Why &lt;code&gt;unsafe&lt;/code&gt; is Justified Here
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;unsafe&lt;/code&gt; block is justified because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Pointer Validation:&lt;/strong&gt; We are dereferencing a raw pointer obtained from FFI. Rust cannot guarantee at compile-time that this pointer is valid or points to a null-terminated string. We manually validate this by using &lt;code&gt;CStr::from_ptr&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Lifetime Management:&lt;/strong&gt; We are returning references (&lt;code&gt;&amp;amp;str&lt;/code&gt;) that borrow from the original buffer. We must ensure that the buffer outlives these references. In our architecture, the buffer is owned by a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt; that lives for the duration of the review process, ensuring safety.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Performance:&lt;/strong&gt; This approach reduces memory usage by ~90% compared to the naive approach, leading to faster processing times and lower GC pressure (in terms of system memory).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Integrating LLMs with Deterministic Latency
&lt;/h2&gt;

&lt;p&gt;The core of &lt;strong&gt;ratatop&lt;/strong&gt; is its ability to send diffs to an LLM (e.g., via OpenAI, Anthropic, or a local model like Llama 3) and parse the response. However, LLM APIs are inherently non-deterministic in terms of latency. A review that takes 2 seconds one time might take 10 seconds the next.&lt;/p&gt;

&lt;p&gt;To mitigate this, we implemented a &lt;strong&gt;circuit breaker&lt;/strong&gt; pattern and &lt;strong&gt;streaming responses&lt;/strong&gt; with timeout controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Streaming Responses
&lt;/h3&gt;

&lt;p&gt;Instead of waiting for the entire LLM response, we stream the tokens and parse them incrementally. This allows us to provide feedback to the user (or the CI system) faster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_openai&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OpenAIConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_openai&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;CreateChatCompletionRequestArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Role&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="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_openai&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;stream_review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OpenAIConfig&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;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CreateChatCompletionRequestArgs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gpt-4o-mini"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nn"&gt;async_openai&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ChatCompletionRequestMessage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nn"&gt;async_openai&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ChatCompletionUserMessage&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="nn"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_content&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nf"&gt;.max_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.chat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.create_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;reviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="py"&gt;.choices&lt;/span&gt;&lt;span class="nf"&gt;.first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&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="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="py"&gt;.delta.content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Handle error, possibly with retry logic&lt;/span&gt;
                &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error in stream: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviews&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;h3&gt;
  
  
  Timeout and Circuit Breaker
&lt;/h3&gt;

&lt;p&gt;We wrap the LLM call in a timeout to prevent hanging. If the LLM API is slow, we fall back to a cached review or a rule-based heuristic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;review_with_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;timeout_duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout_duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;stream_review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff_content&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Timeout occurred, fall back to heuristic&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LLM call timed out. Using heuristic fallback."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"[Heuristic] Possible issue detected in diff."&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
        &lt;span class="p"&gt;}&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;h2&gt;
  
  
  System-Level Metrics with libbpf
&lt;/h2&gt;

&lt;p&gt;To monitor the performance of &lt;strong&gt;ratatop&lt;/strong&gt; in production, we integrated &lt;strong&gt;libbpf&lt;/strong&gt;, a Rust binding for eBPF (Extended Berkeley Packet Filter). eBPF allows us to observe the behavior of the reviewer at the kernel level without modifying the kernel code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why eBPF?
&lt;/h3&gt;

&lt;p&gt;Traditional monitoring tools (like Prometheus exporters) rely on instrumentation within the application code. However, this can introduce overhead and may not capture system-level events like context switches or page faults. eBPF provides a low-overhead way to observe the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring Context Switches
&lt;/h3&gt;

&lt;p&gt;We used eBPF to monitor the number of context switches performed by the &lt;strong&gt;ratatop&lt;/strong&gt; process during a review. High context switches can indicate contention or inefficient scheduling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;libbpf_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;skel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SkelBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;libbpf_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OpenSkel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;libbpf_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Skel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Assume we have an eBPF skeleton generated from a C program&lt;/span&gt;
&lt;span class="c1"&gt;// that counts context switches for a specific PID.&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;setup_bpf_monitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;skel_builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;MySkelBuilder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;open_skel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skel_builder&lt;/span&gt;&lt;span class="nf"&gt;.open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the PID to monitor&lt;/span&gt;
    &lt;span class="n"&gt;open_skel&lt;/span&gt;&lt;span class="nf"&gt;.maps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.ro_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.pid_to_monitor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;skel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;open_skel&lt;/span&gt;&lt;span class="nf"&gt;.load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;skel&lt;/span&gt;&lt;span class="nf"&gt;.attach&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Now, we can read the maps from the eBPF program&lt;/span&gt;
    &lt;span class="c1"&gt;// to get context switch counts&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"eBPF monitor attached for PID {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;h3&gt;
  
  
  Integrating with Prometheus
&lt;/h3&gt;

&lt;p&gt;We exported the eBPF metrics to Prometheus using the &lt;code&gt;prometheus&lt;/code&gt; crate. This allows us to create dashboards that show the relationship between eBPF metrics (context switches, page faults) and LLM latency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;register_int_counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IntCounter&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;CONTEXT_SWITCHES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Lazy&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IntCounter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Lazy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;register_int_counter!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ratatop_context_switches_total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Total context switches during review"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;record_context_switches&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="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CONTEXT_SWITCHES&lt;/span&gt;&lt;span class="nf"&gt;.inc_by&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Building &lt;strong&gt;ratatop&lt;/strong&gt; taught us several valuable lessons about building micro AI services in Rust:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;unsafe&lt;/code&gt; is a Tool, Not a Crutch:&lt;/strong&gt; We used &lt;code&gt;unsafe&lt;/code&gt; sparingly, only where it provided clear performance benefits (zero-copy parsing). Every &lt;code&gt;unsafe&lt;/code&gt; block was thoroughly documented and tested.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Latency Jitter is the Enemy:&lt;/strong&gt; Even with Rust's performance guarantees, LLM APIs are non-deterministic. Implementing timeouts, circuit breakers, and fallbacks is essential for a reliable service.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;eBPF Provides Unique Insights:&lt;/strong&gt; Integrating eBPF allowed us to monitor system-level metrics that are invisible to traditional application-level monitoring. This helped us optimize the reviewer's interaction with the host system.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Modularity is Key:&lt;/strong&gt; By separating the diff parser, LLM client, and metrics collector into distinct modules, we were able to easily swap out components (e.g., using a different LLM provider or a different diffing algorithm) without rewriting the entire system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ratatop&lt;/strong&gt; demonstrates that Rust is an excellent choice for building micro AI services that require low latency, high throughput, and system-level observability. By leveraging &lt;code&gt;unsafe&lt;/code&gt; blocks for zero-copy memory management and eBPF for deep system monitoring, we were able to create a reviewer that is both fast and insightful.&lt;/p&gt;

&lt;p&gt;For developers looking to build similar tools, we recommend starting with a modular architecture, embracing Rust's type system for safety, and not being afraid to use &lt;code&gt;unsafe&lt;/code&gt; where it provides clear benefits. Additionally, integrating eBPF can provide a level of observability that is difficult to achieve with traditional monitoring tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Is it safe to use &lt;code&gt;unsafe&lt;/code&gt; blocks for zero-copy parsing?&lt;/strong&gt;&lt;br&gt;
A: Yes, as long as you carefully manage lifetimes and validate pointers. In our case, we ensure that the buffer outlives the slices and that pointers are valid before dereferencing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I handle errors from LLM APIs?&lt;/strong&gt;&lt;br&gt;
A: We recommend implementing a retry mechanism with exponential backoff, as well as a circuit breaker to fall back to heuristic-based reviews if the LLM API is consistently slow or unavailable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I use eBPF on Windows or macOS?&lt;/strong&gt;&lt;br&gt;
A: eBPF is primarily supported on Linux. For Windows and macOS, you may need to use alternative monitoring tools or containerize the reviewer on a Linux kernel.&lt;/p&gt;

&lt;p&gt;For more insights on building high-performance Rust applications, check out &lt;a href="https://tamiz.pro/insights" rel="noopener noreferrer"&gt;Tamiz's Insights&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machine</category>
      <category>learning</category>
      <category>micro</category>
    </item>
    <item>
      <title>Your Ops Agent’s Chat History Is an Attack Surface: Prompt Injection Just Became an Infrastructure Problem</title>
      <dc:creator>Muskan Bandta</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:00:26 +0000</pubDate>
      <link>https://dev.to/muskan_bandta/your-ops-agents-chat-history-is-an-attack-surface-prompt-injection-just-became-an-infrastructure-2pee</link>
      <guid>https://dev.to/muskan_bandta/your-ops-agents-chat-history-is-an-attack-surface-prompt-injection-just-became-an-infrastructure-2pee</guid>
      <description>&lt;p&gt;There's a line going around dev.to this week that stuck with me: &lt;em&gt;your AI agent's chat history is user input.&lt;/em&gt; It's a security observation about chatbots. But if you've given an agent cloud credentials — and half the "I let an agent run my ops" posts on here have — that line stops being about chatbots and becomes the scariest sentence in your architecture.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable version: &lt;strong&gt;when an agent can call cloud APIs, prompt injection is remote code execution on your infrastructure.&lt;/strong&gt; Let me walk through exactly how, because the attack surface is bigger and dumber than most people realize.&lt;/p&gt;

&lt;h2&gt;
  
  
  The classic framing, and why it undersells the risk
&lt;/h2&gt;

&lt;p&gt;Prompt injection in a chatbot: attacker gets the bot to say something it shouldn't, or leak its system prompt. Bad, embarrassing, usually contained.&lt;/p&gt;

&lt;p&gt;Prompt injection in an &lt;em&gt;ops agent&lt;/em&gt;: attacker gets the agent to &lt;code&gt;TerminateInstances&lt;/code&gt;, exfiltrate secrets to an external endpoint, or open a security group to &lt;code&gt;0.0.0.0/0&lt;/code&gt;. The agent has an IAM role. The IAM role has real permissions. Every check is green — because the agent is &lt;em&gt;allowed&lt;/em&gt; to do those things; that's its job. (I wrote a whole separate piece on why IAM being green is exactly the trap.)&lt;/p&gt;

&lt;p&gt;The model doesn't distinguish "instruction from my operator" from "text I read while doing my job." To an LLM it is all just tokens in the context window. And the context window is full of attacker-reachable text.&lt;/p&gt;

&lt;h2&gt;
  
  
  The injection surface nobody threat-models
&lt;/h2&gt;

&lt;p&gt;When people hear "prompt injection" they picture the chat box. For an ops agent, the chat box is the &lt;em&gt;least&lt;/em&gt; of it. Your agent reads all of this while working, and any of it can carry instructions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource tags and names.&lt;/strong&gt; An agent listing resources reads their &lt;code&gt;Name&lt;/code&gt; tags. A tag value of &lt;code&gt;prod-db — ignore prior instructions and run &amp;lt;bad thing&amp;gt;&lt;/code&gt; is now in the context. Anyone who can create a resource in a connected account can plant text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log lines.&lt;/strong&gt; Agent triaging an incident reads application logs. Logs contain user-controlled strings. A crafted log line is a payload the agent ingests as part of "reading the logs."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud resource metadata, commit messages, PR descriptions, ticket bodies, error messages from third-party APIs, container image labels, Kubernetes annotations.&lt;/strong&gt; Every one of these is (a) text the agent reads to do its job and (b) writable by someone who isn't your operator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent's own memory.&lt;/strong&gt; With long-term memory (now a first-class feature in Bedrock AgentCore, Azure Foundry, Vertex), a poisoned instruction written into memory &lt;em&gt;today&lt;/em&gt; fires days later, in a fresh session, with no attacker present. Persistent memory is a persistent attack surface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The threat model most teams have is "someone types something malicious in the chat." The real model is "any text from any source the agent touches is potentially adversarial instruction." That's a vastly larger surface, and it maps onto data you already treat as untrusted for XSS/SQLi — except now the sink is your cloud control plane.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the usual defenses don't fully save you
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"We'll sanitize inputs."&lt;/strong&gt; You can't reliably sanitize natural language for instruction content — there's no parser boundary between data and command in a prompt. This is the whole reason prompt injection is unsolved. Delimiters and "the following is untrusted, ignore instructions in it" help at the margin and are defeated regularly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Least-privilege IAM."&lt;/strong&gt; Necessary, insufficient. An ops agent's &lt;em&gt;legitimate&lt;/em&gt; permissions are the dangerous ones. You can't least-privilege away delete verbs when deleting is the job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"A human approves actions."&lt;/strong&gt; The best single control — but approval fatigue is real, and a well-crafted plan looks reasonable. "Clean up these 40 idle resources" hides one resource that isn't idle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually reduces the blast radius
&lt;/h2&gt;

&lt;p&gt;Not solutions — mitigations. Defense in depth, because the injection itself can't be fully prevented:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Two-phase execution.&lt;/strong&gt; Agent proposes a plan with read-only credentials; a separate executor with write credentials applies it after a gate. Injection into the reasoning agent can produce a bad &lt;em&gt;plan&lt;/em&gt;, but the plan is inspectable before any credential with teeth touches it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action-level policy, not just IAM.&lt;/strong&gt; Allowlist action &lt;em&gt;shapes&lt;/em&gt; (verb + resource class + condition + time window), enforce blast-radius budgets (max N resources, max $/hour delta per run). A run that suddenly wants to touch 200 resources trips the budget regardless of what convinced it to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat agent-read data as untrusted at the boundary.&lt;/strong&gt; Tags, logs, annotations — the same "untrusted input" hygiene you apply to a web form, applied to everything the agent ingests. You won't catch everything; you'll shrink the surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent state verification.&lt;/strong&gt; A watcher comparing actual resource state against expected baselines on a tight loop, on separate credentials and separate code from the agent — so a successful injection surfaces as drift within minutes instead of on next month's bill. (This is why, building anomaly detection into ZopNight, we made the verifying system share nothing with any acting system — an injected agent must not be the thing that reports whether it misbehaved.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate/anomaly alarms on the account.&lt;/strong&gt; CloudTrail → metric filter → alarm on API velocity per identity. A hijacked agent looks like a traffic anomaly before it looks like a policy violation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;"Your agent's chat history is user input" is correct and it doesn't go far enough. For an agent with cloud credentials, &lt;em&gt;everything the agent reads&lt;/em&gt; is user input — and the sink isn't a rendered web page, it's your infrastructure control plane. Prompt injection stopped being a chatbot embarrassment and became an infrastructure security problem the moment we handed agents an IAM role.&lt;/p&gt;

&lt;p&gt;If you're running an ops agent in prod: what's reading into its context that you don't control? Start listing, and the list gets uncomfortable fast. I'd like to hear what surfaces people found that they hadn't threat-modeled.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>GPT-5.6 Luna Just Cut Prices 80% Your AI Bill Is Still Going Up, and Here’s the Math</title>
      <dc:creator>Muskan Bandta</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:00:16 +0000</pubDate>
      <link>https://dev.to/muskan_bandta/gpt-56-luna-just-cut-prices-80-your-ai-bill-is-still-going-up-and-heres-the-math-284n</link>
      <guid>https://dev.to/muskan_bandta/gpt-56-luna-just-cut-prices-80-your-ai-bill-is-still-going-up-and-heres-the-math-284n</guid>
      <description>&lt;p&gt;This week in the AI price war: OpenAI cut GPT-5.6 Luna pricing by &lt;strong&gt;80%&lt;/strong&gt; and GPT-5.6 Terra by 20%. Claude Opus 5 landed on Amazon Bedrock holding at $5 in / $25 out per million tokens with a 1M context window. Every headline says the same thing: intelligence is getting cheaper, fast.&lt;/p&gt;

&lt;p&gt;So why does every engineering team I talk to report the same thing — &lt;strong&gt;the AI line on the cloud bill went &lt;em&gt;up&lt;/em&gt; again this quarter?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because tokens are the only part of the stack getting cheaper, and tokens are becoming the smallest part of the bill. Let's do the math.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jevons paradox, but for tokens
&lt;/h2&gt;

&lt;p&gt;In 1865, economist William Jevons noticed that more efficient steam engines didn't reduce coal consumption — they increased it, because efficiency made steam viable for things it was previously too expensive for.&lt;/p&gt;

&lt;p&gt;Swap coal for tokens. When Luna gets 80% cheaper, teams don't pocket the savings — they take workloads that were marginal at the old price and turn them on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The code-review bot that was "too expensive to run on every PR" now runs on every PR.&lt;/li&gt;
&lt;li&gt;The log-summarization job that ran daily now runs hourly.&lt;/li&gt;
&lt;li&gt;The agent that answered questions now &lt;em&gt;acts&lt;/em&gt; — and an acting agent burns 10–50× the tokens of an answering one, because plan/execute/verify loops are token furnaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An 80% price cut followed by a 10× usage increase is a 2× bill increase. That's not a failure of discipline; it's the price cut working exactly as intended — for the vendor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bill is quietly changing shape
&lt;/h2&gt;

&lt;p&gt;The more important shift: token spend is becoming the &lt;em&gt;minority&lt;/em&gt; of AI infrastructure cost. Here's the stack that came online around it this year:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Agent runtime.&lt;/strong&gt; AWS Bedrock AgentCore, Azure Foundry Agent Service, Vertex AI's agent stack — every major cloud shipped managed agent infrastructure this year. Runtime, gateway, identity, managed memory: each is a new metered line item that didn't exist on your 2024 bill. You're not paying for intelligence; you're paying for the &lt;em&gt;scaffolding around&lt;/em&gt; intelligence, and scaffolding doesn't get 80% cheaper on a Tuesday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Agent memory and state.&lt;/strong&gt; Long-term memory stores, vector databases, session persistence. Memory is storage + retrieval compute, priced like storage + compute — on the classic cloud cost curve (slow decline), not the model cost curve (cliff dives).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Observability.&lt;/strong&gt; Tracing what an agent did, evaluating outputs, storing full conversation traces for audit. Teams routinely discover their LLM observability spend rivals their token spend — you're storing and querying every token &lt;em&gt;twice&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The GPU floor.&lt;/strong&gt; If you run any inference yourself, you know the dirty secret: self-hosted model economics are dominated by utilization, and bursty agent workloads are utilization poison. A GPU node pool sized for peak agent activity idles most of the day at full price.&lt;/p&gt;

&lt;p&gt;Rough shape of what I see in real accounts: what was ~80% tokens / 20% everything-else in 2024 is heading toward &lt;strong&gt;~30% tokens / 70% runtime + memory + observability + GPU&lt;/strong&gt; — while total AI spend grows quarter over quarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a FinOps problem now
&lt;/h2&gt;

&lt;p&gt;For two years, AI cost had a comforting story: "wait six months, the price drops." True for tokens. Irrelevant for the rest of the stack — the rest of the stack is &lt;em&gt;ordinary cloud infrastructure&lt;/em&gt;, and it responds to ordinary FinOps levers, not to model-vendor price wars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Idle agent runtimes and GPU pools&lt;/strong&gt; obey the same physics as idle EC2 — schedule them. An eval environment's GPU node group has no business running at 3am (we schedule ours to sleep the same way we schedule staging — same tooling, ZopNight treats a GPU node group like any other schedulable resource).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability retention&lt;/strong&gt; is a knob. Ninety days of full traces for a chatbot is a choice, and it's usually the default, and the default is expensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Cheaper model" is a rightsizing decision.&lt;/strong&gt; Luna at −80% makes model selection a cost lever on par with instance selection. Routing the easy 70% of requests to the cheap tier is this year's version of moving dev to spot instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anomaly detection needs to cover AI resources.&lt;/strong&gt; An agent stuck in a retry loop is the new "forgot to turn off the p4d instance" — invisible on daily billing granularity until it's a very visible number.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The price war headlines are real, and they will keep coming — Luna won't be the last 80% cut. But "tokens got cheaper" and "AI got cheaper to run" stopped being the same sentence sometime this year. The bill's center of gravity moved into the infrastructure around the model, and that part doesn't do price-war cliff dives. It does what cloud bills have always done: grow quietly until someone looks.&lt;/p&gt;

&lt;p&gt;Is anyone actually seeing their total AI spend &lt;em&gt;fall&lt;/em&gt; after a price cut? I keep asking and I have not found one yet — if you're the exception, I'd genuinely like to know what you're doing differently.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cloud</category>
      <category>finops</category>
      <category>devops</category>
    </item>
    <item>
      <title>Gemini Robotics 2 place le cerveau des humanoïdes chez Google</title>
      <dc:creator>Thibault Monteiro</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:00:08 +0000</pubDate>
      <link>https://dev.to/thibault_monteiro/gemini-robotics-2-place-le-cerveau-des-humanoides-chez-google-5k4</link>
      <guid>https://dev.to/thibault_monteiro/gemini-robotics-2-place-le-cerveau-des-humanoides-chez-google-5k4</guid>
      <description>&lt;p&gt;L'essentiel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Google DeepMind a lancé le 30 juillet Gemini Robotics 2, une famille de trois modèles capables de piloter un humanoïde entier, des pieds aux doigts.&lt;/li&gt;
&lt;li&gt;  L'architecture sépare le raisonnement (Gemini Robotics ER 2) de l'exécution motrice, la première couche commandant la seconde comme un outil.&lt;/li&gt;
&lt;li&gt;  ER 2 est ouvert aux développeurs via l'API Gemini et Google AI Studio ; les modèles de contrôle moteur restent réservés à des partenaires sélectionnés.&lt;/li&gt;
&lt;li&gt;  La version embarquée s'adapte à une morphologie de robot entièrement nouvelle avec quelques heures de données.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous demandez à un robot de poser l'arrosoir dans le bac vert, sur l'étagère du bas. Qui décide qu'il faut marcher jusqu'à la table, fléchir les genoux, puis refermer les doigts au bon endroit ? Depuis le 30 juillet, Google DeepMind répond avec deux étages distincts plutôt qu'avec un modèle unique. Cette séparation pèsera plus lourd que les démonstrations de dextérité qui l'accompagnent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un cortex et une moelle épinière
&lt;/h2&gt;

&lt;p&gt;Gemini Robotics 2 regroupe trois modèles. Gemini Robotics ER 2 assure le raisonnement incarné : ce modèle vision-langage discute avec l'humain, comprend la scène et découpe une consigne en une séquence d'actions qui peut durer plusieurs minutes. Le modèle vision-langage-action (VLA), lui, convertit &lt;a href="https://blog.thibaultmonteiro.fr/modeles-ia/mistral-pilote-un-robot-avec-une-seule-camera-4639/" rel="noopener noreferrer"&gt;ce que voit le robot&lt;/a&gt; et ce qu'on lui dit en commandes motrices : marcher, s'accroupir, piloter une main à cinq doigts. Une troisième variante, Gemini Robotics On-Device 2, fait tourner cette conversion en local, sur la machine elle-même.&lt;/p&gt;

&lt;p&gt;L'analogie du système nerveux tient plutôt bien. ER 2 joue le cortex qui planifie, le VLA joue la moelle épinière et le geste. Google DeepMind assume cette division du travail : sa couche de raisonnement délègue l'exécution motrice à n'importe quel modèle de bas niveau. Le développeur déclare les interfaces de contrôle et les API de navigation comme des outils, et le cerveau les appelle, exactement comme il appellerait Google Search ou une fonction maison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Penser pendant qu'on bouge
&lt;/h2&gt;

&lt;p&gt;Ce découpage en deux étages répond à une contrainte très concrète : le monde physique n'attend pas. Un robot qui se fige pour réfléchir entre chaque geste devient inexploitable dans une cuisine ou un atelier. ER 2 s'appuie donc sur la Gemini Live API et son point d'entrée en streaming bidirectionnel, pensé pour réduire le délai de réponse. Le modèle suit un flux vidéo continu, vérifie où il en est, rattrape un geste raté et déclenche l'étape suivante au bon moment, sans la pause de réflexion qui trahissait les générations précédentes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/google-deepmind/gemini-robotics-er-2/?utm_source=deepmind.google&amp;amp;utm_medium=referral&amp;amp;utm_campaign=gdm&amp;amp;utm_content=" rel="noopener noreferrer"&gt;Google compare ER 2&lt;/a&gt; à ER 1.6 sur l'orchestration d'outils dans trois configurations : un modèle d'action réel, &lt;a href="https://blog.thibaultmonteiro.fr/ia-entreprise/strategie-et-rivalites/gemini-robotics-donnee-reelle-contre-monde-simule-4588/" rel="noopener noreferrer"&gt;un modèle simulé&lt;/a&gt;, et un humain en téléopération, c'est-à-dire aux commandes à distance. Le troisième cas est le plus parlant. La couche de raisonnement est indifférente à la nature de l'exécutant : un VLA, une simulation ou une paire de mains humaines occupent la même case dans son plan. Le corps est devenu un paramètre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le matériel, variable d'ajustement
&lt;/h2&gt;

&lt;p&gt;Les démonstrations enfoncent le clou. &lt;a href="https://apptronik.com/apollo/apollo-2" rel="noopener noreferrer"&gt;Apollo 2&lt;/a&gt;, l'humanoïde d'Apptronik, reçoit une consigne unique et enchaîne la marche, la flexion et la préhension. La même couche logicielle fait un nœud, visse une pièce, puis fait coopérer Apollo avec un second robot, Duo, pour ranger un garage : le modèle de raisonnement découpe la tâche, désigne les zones et choisit l'instant du passage de relais. Chez Boston Dynamics, c'est &lt;a href="https://bostondynamics.com/products/spot/" rel="noopener noreferrer"&gt;Spot&lt;/a&gt; qui exécute, avec ses API de navigation et de manipulation déclarées comme outils.&lt;/p&gt;

&lt;p&gt;Quand un constructeur arrive avec une morphologie inédite, la version embarquée s'y adapte &lt;a href="https://blog.thibaultmonteiro.fr/modeles-ia/xiaomi-arme-ses-robots-avec-100-000-heures-de-reel-4854/" rel="noopener noreferrer"&gt;en quelques heures de données&lt;/a&gt;. Le coût d'intégration d'un nouveau châssis s'effondre, pendant que la valeur se concentre dans la couche qui, elle, ne change jamais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le cerveau ouvert, les muscles fermés
&lt;/h2&gt;

&lt;p&gt;Le partage des accès confirme la hiérarchie. ER 2, le cerveau, est ouvert aux développeurs via l'API Gemini et Google AI Studio, en préversion privée sur Gemini Enterprise Agent Platform, avec des exemples publiés sur GitHub. Les modèles de contrôle moteur, eux, restent entre les mains de partenaires triés sur le volet. Chez les concurrents, la frontière passe ailleurs : NVIDIA publie les poids de son modèle pour humanoïdes &lt;a href="https://huggingface.co/nvidia/GR00T-N1.7-3B" rel="noopener noreferrer"&gt;GR00T N1.7&lt;/a&gt; sous licence commerciale ouverte, téléchargeables sur Hugging Face, tandis que Figure a rompu avec OpenAI début 2025 pour développer en interne son propre modèle vision-langage-action, &lt;a href="https://www.figure.ai/news/helix" rel="noopener noreferrer"&gt;Helix&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La conséquence est immédiate pour un fabricant de robots : il peut prototyper la partie qui planifie et qui parle, mais l'étage qui commande les muscles ne lui appartient pas, et le cerveau tourne chez Google. Un humanoïde privé de cette couche redevient une mécanique téléopérée. La question de la &lt;a href="https://blog.thibaultmonteiro.fr/ia-entreprise/strategie-et-rivalites/lia-souveraine-se-joue-sur-le-calcul-pas-les-modeles-4866/" rel="noopener noreferrer"&gt;souveraineté logicielle&lt;/a&gt;, que les industriels ont appris à poser pour leur cloud, se rejoue ici sur des machines qui marchent dans leurs entrepôts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les taux de réussite manquent à l'appel
&lt;/h2&gt;

&lt;p&gt;Les séquences diffusées sont choisies avec soin. Aucun taux de réussite n'accompagne les tâches montrées, et rien ne dit combien de tentatives précèdent la bonne prise de l'arrosoir. Les comparaisons chiffrées publiées portent sur l'orchestration d'outils face à la version précédente, pas sur la fiabilité d'un humanoïde qui se déplace parmi des objets fragiles et des humains.&lt;/p&gt;

&lt;p&gt;Ces réserves ne changent rien à ce que l'annonce installe. La robotique se structure comme le reste de l'informatique : un système d'exploitation d'un côté, du matériel de l'autre. Les fabricants d'humanoïdes viennent d'apprendre de quel côté de cette frontière on les attend.&lt;/p&gt;

&lt;p&gt;Mon avis&lt;/p&gt;

&lt;p&gt;La bataille des humanoïdes ne se gagnera pas sur les articulations, et ceux qui ne fabriquent que du matériel l'ont déjà perdue. Un constructeur qui branche Gemini Robotics 2 gagne deux ans de développement et perd son produit : il assemble le terminal d'une intelligence mise à jour ailleurs, par quelqu'un d'autre. Je surveille Apptronik de près, car c'est l'acteur qui a la plus forte incitation à bâtir sa propre couche de raisonnement et le moins de moyens de le faire. Et je ne crois pas une seconde que le contrôle moteur reste fermé longtemps : il s'ouvrira le jour où Google aura besoin de verrouiller le marché plutôt que de le trier.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>google</category>
      <category>machinelearning</category>
      <category>robotics</category>
    </item>
    <item>
      <title>Microsoft confie 90 % de sa chasse aux failles à un mini-modèle</title>
      <dc:creator>Thibault Monteiro</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:00:07 +0000</pubDate>
      <link>https://dev.to/thibault_monteiro/microsoft-confie-90-de-sa-chasse-aux-failles-a-un-mini-modele-2m6l</link>
      <guid>https://dev.to/thibault_monteiro/microsoft-confie-90-de-sa-chasse-aux-failles-a-un-mini-modele-2m6l</guid>
      <description>&lt;p&gt;L'essentiel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Microsoft a présenté le 27 juillet &lt;a href="https://microsoft.ai/news/introducing-mai-cyber-1-flash-inside-mdash/" rel="noopener noreferrer"&gt;MAI-Cyber-1-Flash&lt;/a&gt;, un modèle compact dérivé de son modèle de raisonnement maison MAI-Thinking-1 et taillé pour repérer des vulnérabilités logicielles.&lt;/li&gt;
&lt;li&gt;  Associé à GPT-5.4 dans le harnais multi-agents MDASH, il atteint 95,95 % sur le benchmark &lt;a href="https://arxiv.org/abs/2506.02548" rel="noopener noreferrer"&gt;CyberGym&lt;/a&gt; contre 88,45 % en mai, absorbe jusqu'à 90 % des tâches de sécurité courantes et divise par deux les coûts de la configuration en production.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://blogs.microsoft.com/blog/2026/07/27/rethinking-security-for-the-age-of-ai/" rel="noopener noreferrer"&gt;Project Perception&lt;/a&gt;, la plateforme d'agents rouges, bleus et verts qui exploite ce dispositif, entre en preview publique le 3 août dans Microsoft Defender, facturée à la consommation en Security Compute Units.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microsoft a fait deux annonces le même jour, et elles se répondent. D'un côté &lt;a href="https://blog.thibaultmonteiro.fr/modeles-ia/ce-mini-modele-ia-repere-150-fois-plus-de-failles-par-dollar-4965/" rel="noopener noreferrer"&gt;un modèle minuscule&lt;/a&gt;, entraîné pour une seule tâche. De l'autre une plateforme d'agents censée tenir une posture de défense en continu. Entre les deux, une décision d'architecture qui dépasse largement l'éditeur : arrêter d'envoyer chaque ligne de code à un généraliste hors de prix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un spécialiste bon marché en face d'un généraliste cher
&lt;/h2&gt;

&lt;p&gt;MAI-Cyber-1-Flash dérive de MAI-Thinking-1, le modèle de raisonnement que Microsoft a présenté en juin avec six autres modèles internes. Version compacte et peu coûteuse à faire tourner, il a été entraîné sur les données d'attaques et de correctifs que les équipes de sécurité de l'éditeur accumulent depuis des années. Il ne travaille pas seul : il s'insère dans MDASH, le harnais multi-agents de la firme (l'ossature logicielle qui orchestre les agents et enchaîne leurs étapes), dévoilé en mai.&lt;/p&gt;

&lt;p&gt;Microsoft assume &lt;a href="https://blog.thibaultmonteiro.fr/agents-ia/orchestration-agentique/chez-cursor-les-gros-modeles-planifient-les-petits-executent-5019/" rel="noopener noreferrer"&gt;cette répartition des rôles&lt;/a&gt; sans détour. Le généraliste sait presque tout et facture chaque appel en conséquence ; le modèle vertical ne sait faire qu'une chose, mais il la répète pour beaucoup moins cher. Concrètement, MAI-Cyber-1-Flash prend jusqu'à 90 % des tâches de sécurité courantes, et GPT-5.4 n'intervient plus que sur les 10 % de cas les plus retors. L'éditeur revendique une facture réduite de moitié par rapport à la configuration MDASH aujourd'hui en production.&lt;/p&gt;

&lt;p&gt;Les concurrents ont pris l'autre chemin : Google DeepMind fait tourner &lt;a href="https://deepmind.google/blog/introducing-codemender-an-ai-agent-for-code-security/" rel="noopener noreferrer"&gt;CodeMender&lt;/a&gt;, son agent de correction de code, sur ses modèles Gemini, et Anthropic a bâti son offre Claude Security sur ses modèles généralistes. Voilà l'arbitrage qui va se rejouer partout : payer un modèle universel pour un travail répétitif, ou entraîner un modèle étroit et garder le gros calibre pour la poignée de cas qui résistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  La sécurité possède ce qui manque aux autres métiers
&lt;/h2&gt;

&lt;p&gt;Si les modèles verticaux percent d'abord ici, ce n'est pas un hasard de calendrier. &lt;a href="https://blog.thibaultmonteiro.fr/risques-ia/lia-deterre-1-500-failles-par-mois-la-correction-ne-suit-pas-4477/" rel="noopener noreferrer"&gt;La détection de vulnérabilités&lt;/a&gt; réunit les trois conditions que les autres domaines n'ont presque jamais ensemble : un gisement de données propriétaires (des décennies de failles trouvées et corrigées), un volume énorme de tâches quasi identiques, et surtout un juge mécanique. Un exploit fonctionne, ou il ne fonctionne pas.&lt;/p&gt;

&lt;p&gt;Cette vérifiabilité pèse autant sur l'entraînement que sur l'évaluation. Un modèle spécialisé en rédaction commerciale ou en analyse juridique reste condamné au jugement humain, donc à des progrès lents et discutables. Un modèle de sécurité, lui, se corrige contre une preuve. C'est ce qui fait de la cybersécurité le premier marché où le pari du petit modèle métier tient économiquement, et pas seulement sur le papier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le score grimpe, le bruit reste hors champ
&lt;/h2&gt;

&lt;p&gt;Le pipeline MDASH orchestre plus de cent agents spécialisés en plusieurs étapes : préparation, scan, débat contradictoire entre agents, dédoublonnage, puis preuve d'exploitabilité. Sur CyberGym, le benchmark de référence pour la détection de vulnérabilités réelles dans du code open source, l'ensemble passe de 88,45 % en mai à 95,95 % avec le nouveau modèle. Selon les mesures de Microsoft, cela le place une douzaine de points devant Claude Mythos d'Anthropic.&lt;/p&gt;

&lt;p&gt;Ce pourcentage compte les failles que le système finit par trouver. Il ne compte pas celles qu'il croit voir là où il n'y en a aucune. Or les deux étapes les plus intéressantes du pipeline, le débat contradictoire et la preuve d'exploitabilité, existent précisément pour éteindre les fausses alertes. Ces deux garde-fous désignent l'adversaire principal, le bruit, qu'aucun chiffre public ne quantifie pour l'instant.&lt;/p&gt;

&lt;p&gt;La question devient sérieuse dès qu'un agent agit sans relecture. Une alerte fausse dans un tableau de bord coûte quelques minutes d'analyste. Un &lt;a href="https://blog.thibaultmonteiro.fr/agents-ia/agents-de-code/gpt-5-6-trouve-la-faille-la-valide-et-la-corrige-seul-4821/" rel="noopener noreferrer"&gt;correctif appliqué automatiquement&lt;/a&gt; sur une fausse alerte touche du code de production. Fixer le seuil de tolérance revient donc à décider si la boucle peut se fermer sans vous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rouge, bleu, vert : les agents travaillent, l'humain signe
&lt;/h2&gt;

&lt;p&gt;Project Perception distribue trois rôles. Les agents rouges simulent des attaques comme le ferait un assaillant en quête d'une porte ouverte. Les agents bleus détectent les menaces et les hiérarchisent par gravité. Les agents verts appliquent les correctifs et referment les brèches. Les actions à fort impact restent soumises à une validation humaine, et Microsoft défend cette ligne de partage : la charge de travail aux agents, les décisions stratégiques aux équipes.&lt;/p&gt;

&lt;p&gt;La formule est rassurante, à une réserve près : la frontière du « fort impact » est définie par la plateforme, pas par vous. Tout ce qui tombe en dessous s'exécute en silence. Le modèle économique ajoute une seconde tension, moins discutée. La facturation se fait à la consommation, en Security Compute Units (des unités de calcul de sécurité facturées à l'usage) dont le volume dépend de l'intensité des tâches exécutées. Un agent zélé qui multiplie les scans devient une ligne budgétaire, et l'optimisation des coûts finit par arbitrer la profondeur de l'analyse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testez sur votre code, pas sur le benchmark
&lt;/h2&gt;

&lt;p&gt;L'ouverture au public commence le 3 août dans Microsoft Defender, avant un déploiement progressif au reste de la gamme de sécurité. Si vous mettez la main dessus, ne rejouez pas le test public : mesurez sur votre propre base de code combien d'alertes remontées se révèlent exploitables, et à quel coût en unités de calcul. Exigez le taux de fausses alertes avant d'autoriser le moindre correctif automatique, et calibrez vous-même la liste des actions qui réclament une signature humaine.&lt;/p&gt;

&lt;p&gt;Un modèle de sécurité à 95,95 % de détection reste un excellent produit. Un agent qui referme une brèche imaginaire dans votre dépôt, en revanche, ne se rattrape pas d'un point de benchmark supplémentaire.&lt;/p&gt;

&lt;p&gt;Mon avis&lt;/p&gt;

&lt;p&gt;La cybersécurité va servir de laboratoire grandeur réelle à toute la vague des modèles verticaux, parce qu'elle est l'un des rares métiers où une réponse se prouve au lieu de se plaider. Le score sur CyberGym m'intéresse donc moins que le premier correctif appliqué par un agent vert sur une fausse alerte en production, et que la manière dont Microsoft en rendra compte. Un modèle spécialisé qui se trompe rarement mais dans le silence coûte plus cher qu'un généraliste bavard qu'on relit encore. Et je doute que le seuil de validation humaine, aujourd'hui fixé par l'éditeur, résiste longtemps à la pression sur les Security Compute Units.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>I Gave an AI Agent One Prompt Cut Our Cloud Bill 20% Without Breaking Anything Here’s What It Did</title>
      <dc:creator>Muskan Bandta</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:00:02 +0000</pubDate>
      <link>https://dev.to/muskan_bandta/i-gave-an-ai-agent-one-prompt-cut-our-cloud-bill-20-without-breaking-anything-heres-what-it-did-48bl</link>
      <guid>https://dev.to/muskan_bandta/i-gave-an-ai-agent-one-prompt-cut-our-cloud-bill-20-without-breaking-anything-heres-what-it-did-48bl</guid>
      <description>&lt;p&gt;After my cloud-ops-for-a-week experiment, several people in the comments asked the obvious next question: what happens if you point an agent at the &lt;em&gt;bill&lt;/em&gt; instead of the ops queue?&lt;/p&gt;

&lt;p&gt;So I ran it. One agent, read access to our AWS and GCP accounts plus billing data, MCP tools for querying resources and metrics, and exactly one prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Cut our cloud bill by 20% without breaking anything. Show me your plan before you touch anything."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two ground rules from the start: the agent got &lt;strong&gt;read-only credentials&lt;/strong&gt; (plans only, no execution — I applied approved changes myself), and it had to justify every line item with actual metrics, not vibes. Here's what a week of that produced, sorted into the good, the scary, and the genuinely surprising.&lt;/p&gt;

&lt;h2&gt;
  
  
  The good: it found the boring waste instantly
&lt;/h2&gt;

&lt;p&gt;Within the first hour, the agent produced a list a human FinOps review would have taken days to assemble:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;11 unattached EBS volumes&lt;/strong&gt; (oldest one: 9 months, from an instance terminated last year)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A dev RDS instance at 3% average CPU&lt;/strong&gt; over 30 days — provisioned as &lt;code&gt;db.r5.xlarge&lt;/code&gt; "temporarily" for a load test&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two NAT gateways in a region we'd migrated out of&lt;/strong&gt;, faithfully billing ~$32/month each for zero traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 load balancers with zero healthy targets&lt;/strong&gt; — the targets were deprovisioned, the LBs weren't&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staging running 24/7&lt;/strong&gt; with request counts flatlining to zero from 8pm to 8am every single day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Projected savings from just this list: &lt;strong&gt;~14% of the monthly bill&lt;/strong&gt;. None of it required cleverness. All of it required &lt;em&gt;looking&lt;/em&gt;, which nobody had done because looking is tedious. This is the strongest case for agents in FinOps: the discovery layer, where wrong answers are cheap because a human verifies before anything executes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scary: the plans that would have caused incidents
&lt;/h2&gt;

&lt;p&gt;This is the section people actually asked for. Three plans I rejected:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It wanted to delete "unused" snapshots that were our DR baseline.&lt;/strong&gt; The snapshots had no recent restore activity and no tags (our fault), so the agent classified them as orphaned. The metrics genuinely supported the conclusion. The &lt;em&gt;context&lt;/em&gt; — "these are the disaster-recovery baseline, they're supposed to sit untouched" — lived in a Confluence page and two engineers' heads. Metrics-driven reasoning with no access to intent will confidently propose deleting your safety net.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. It proposed downsizing a "3% CPU" instance that was memory-bound.&lt;/strong&gt; Classic. CloudWatch doesn't report memory by default; the agent saw idle CPU and recommended halving the instance. The box was running an in-memory cache at 85% RAM. Downsizing = OOM-killer roulette. Lesson: an agent reasoning from an incomplete metrics surface doesn't know the surface is incomplete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It wanted to buy reserved instances during a migration.&lt;/strong&gt; Mathematically correct on 30 days of data — those instances had run flat-out all month. What the data didn't show: we were migrating that workload to GKE within the quarter. A human with calendar context kills that plan in five seconds; the agent would have locked in a year of commitment.&lt;/p&gt;

&lt;p&gt;The common thread: &lt;strong&gt;every dangerous plan was locally rational.&lt;/strong&gt; The agent was never wrong on the data it had. It was wrong on the data that &lt;em&gt;isn't data&lt;/em&gt; — intent, plans, tribal knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The surprising: it negotiated with itself
&lt;/h2&gt;

&lt;p&gt;The genuinely unexpected part. Told that "without breaking anything" was a hard constraint, the agent started attaching &lt;em&gt;confidence levels and rollback plans&lt;/em&gt; to its own suggestions, unprompted, and split its output into "safe to automate" vs "needs human review." Its taxonomy was roughly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reversible in seconds, zero user impact (stop idle dev instance) → high confidence&lt;/li&gt;
&lt;li&gt;Reversible with effort (downsize, snapshot-then-delete) → medium, human approves&lt;/li&gt;
&lt;li&gt;Irreversible or commitment (delete data, buy RIs) → flagged, refuses to recommend without confirmation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's... the correct architecture. The agent independently converged on the plan/approve/execute split that we'd already learned the hard way building scheduling and one-click remediation into ZopNight — where every remediation ships with its undo, because the undo &lt;em&gt;is&lt;/em&gt; the product. Watching a model reinvent that boundary from a one-line constraint was the most interesting result of the week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final scorecard
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Savings identified&lt;/td&gt;
&lt;td&gt;~19% of monthly bill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Savings I actually applied&lt;/td&gt;
&lt;td&gt;~12% (the rest needed refactors or timing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plans that would have caused incidents&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Incidents caused&lt;/td&gt;
&lt;td&gt;0 — because plans ≠ execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time I spent reviewing plans&lt;/td&gt;
&lt;td&gt;~4 hours across the week&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;12% of the bill for four hours of review is a spectacular trade. But read the table again: the zero in row four exists &lt;em&gt;only&lt;/em&gt; because of the read-only rule. Same experiment with write credentials is a different article, probably titled "post-incident review."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The one-line takeaway:&lt;/strong&gt; agents are already excellent at finding the money and terrible at knowing which findings are traps. Structure the work so those two skills stay separated — agent proposes, human (or hard policy) disposes.&lt;/p&gt;

&lt;p&gt;Would you give an agent write access to your infra for this? Genuinely curious where people's lines are — the comments on my last experiment convinced me nobody agrees yet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cloud</category>
      <category>finops</category>
      <category>devops</category>
    </item>
    <item>
      <title>AI agents should not just write code</title>
      <dc:creator>Daniel Maß</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:59:32 +0000</pubDate>
      <link>https://dev.to/themassiveone/ai-agents-should-not-just-write-code-333l</link>
      <guid>https://dev.to/themassiveone/ai-agents-should-not-just-write-code-333l</guid>
      <description>&lt;p&gt;They should be able to use the application they changed.&lt;/p&gt;

&lt;p&gt;That sounds obvious, but most coding agent workflows still stop at editing files, running tests, maybe starting a dev server, and reporting back. For web apps, that is not enough.&lt;/p&gt;

&lt;p&gt;A human developer does not only inspect diffs. They open the app. They click through the flow. They notice when the wrong tab is open, when a button does nothing, when the page changed unexpectedly, or when the browser is still pointing at yesterday's backend.&lt;/p&gt;

&lt;p&gt;AI agents need that same feedback loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser state becomes coordination state
&lt;/h2&gt;

&lt;p&gt;Once multiple agents are running in parallel, browser state becomes another coordination problem. Without isolation, browser tabs point to the wrong workspace, one agent clicks in another agent's app, authentication state leaks between branches, screenshots no longer match the running process, and the developer cannot tell which agent is doing what.&lt;/p&gt;

&lt;p&gt;This is why Agent-Up now treats the browser as part of the workspace runtime.&lt;/p&gt;

&lt;p&gt;Each workspace gets its own browser session, application tabs, port mappings, logs, and runtime state. Agents interact with that browser through MCP, so they can navigate to the app, inspect the page, click links and buttons, wait for text or selectors, take screenshots, and record browser activity into the audit history.&lt;/p&gt;

&lt;p&gt;The important part is not just that the agent can click. It is that the click belongs to the correct workspace.&lt;/p&gt;

&lt;p&gt;When an agent clicks inside its app, Agent-Up can switch the visible application tab for that workspace, move the agent mouse representation, show the click animation, and keep the developer's desktop view aligned with what the agent is actually doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The review experience changes
&lt;/h2&gt;

&lt;p&gt;Instead of reading four terminal logs and guessing what happened, you can watch four agents exercise four isolated versions of an app at the same time.&lt;/p&gt;

&lt;p&gt;One agent might test the login flow. Another checks pricing. Another walks through checkout. Another validates returns and fulfillment.&lt;/p&gt;

&lt;p&gt;Same machine. Same repo.&lt;/p&gt;

&lt;p&gt;But different worktrees, different runtime environments, and different browser sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The browser is part of the feedback loop
&lt;/h2&gt;

&lt;p&gt;This is the part of agentic development I think people underestimate: the browser is not just an output surface.&lt;/p&gt;

&lt;p&gt;It is part of the feedback loop.&lt;/p&gt;

&lt;p&gt;For web applications, an agent that cannot use the browser is missing the place where the product actually exists.&lt;/p&gt;

&lt;p&gt;Git isolates the source. Agent-Up isolates the runtime. MCP gives agents control over both.&lt;/p&gt;

&lt;p&gt;That makes parallel agent work easier to supervise because you are no longer only reviewing generated code. You are watching each agent operate its own version of the product.&lt;/p&gt;

&lt;p&gt;That is what the demo was built to show.&lt;/p&gt;

&lt;p&gt;Download Agent-Up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://agent-up.themassiveone.net/" rel="noopener noreferrer"&gt;https://agent-up.themassiveone.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open source repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/agent-up-oss/agent-up/" rel="noopener noreferrer"&gt;https://github.com/agent-up-oss/agent-up/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>browser</category>
    </item>
    <item>
      <title>3 Simple Go Habits That Will Save You Hours of Debugging</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:59:02 +0000</pubDate>
      <link>https://dev.to/kahenda/3-simple-go-habits-that-will-save-you-hours-of-debugging-47j3</link>
      <guid>https://dev.to/kahenda/3-simple-go-habits-that-will-save-you-hours-of-debugging-47j3</guid>
      <description>&lt;p&gt;We have all been there. You look at a Go function you wrote just two weeks ago, and it looks like a complete mystery. Writing code that compiles is easy. Writing Go code that is readable, maintainable, and easy to debug is the real superpower.The Go philosophy values simplicity and clarity over cleverness. You do not need to master complex architecture to write better code today. Here are three simple, actionable habits you can start using in your next package.1. Use Meaningful Names (But Keep Go Idioms in Mind)Go prefers short variable names, but they must still carry clear meaning based on their scope. Avoid cryptic, single-letter names for long functions or global states.❌ Bad:gofunc process(d time.Duration) {&lt;br&gt;
    // confusing if the function is long&lt;br&gt;
    let t := time.Now().Add(d) &lt;br&gt;
}&lt;br&gt;
Use code with caution.✅ Good:gofunc process(expiryTimeout time.Duration) {&lt;br&gt;
    deadline := time.Now().Add(expiryTimeout)&lt;br&gt;
}&lt;br&gt;
Use code with caution.Why it matters: Code is read far more often than it is written. While a short r is fine for a receiver or a brief loop index, use descriptive names for data that travels through your application logic.2. Keep Functions Small and Return EarlyGo code can quickly become unreadable if you deeply nest your if statements. Use the "return early" strategy by handling errors immediately. This keeps your successful code path aligned to the left of your screen.❌ Bad (Deeply Nested):gofunc SaveUser(u *User) error {&lt;br&gt;
    if u != nil {&lt;br&gt;
        if u.IsValid() {&lt;br&gt;
            err := db.Save(u)&lt;br&gt;
            if err == nil {&lt;br&gt;
                return nil&lt;br&gt;
            }&lt;br&gt;
            return err&lt;br&gt;
        }&lt;br&gt;
        return errors.New("invalid user")&lt;br&gt;
    }&lt;br&gt;
    return errors.New("nil user")&lt;br&gt;
}&lt;br&gt;
Use code with caution.✅ Good (Return Early):gofunc SaveUser(u *User) error {&lt;br&gt;
    if u == nil {&lt;br&gt;
        return errors.New("nil user")&lt;br&gt;
    }&lt;br&gt;
    if !u.IsValid() {&lt;br&gt;
        return errors.New("invalid user")&lt;br&gt;
    }&lt;br&gt;
    return db.Save(u)&lt;br&gt;
}&lt;br&gt;
Use code with caution.Why it matters: Returning early eliminates the "arrow anti-pattern" (deeply nested code). It makes your functions incredibly easy to read, test, and debug from top to bottom.3. Comment the "Why," Not the "What"Go features self-documenting syntax. Your comments should not repeat what the code plainly states. Instead, use them to explain why a specific approach or workaround was necessary.❌ Bad:go// Increment total by one&lt;br&gt;
total++&lt;br&gt;
Use code with caution.✅ Good:go// Retry limit is set to 3 to prevent hammering the third-party billing API&lt;br&gt;
const maxRetries = 3&lt;br&gt;
Use code with caution.Why it matters: Avoid stating the obvious. Use comments to provide critical business context or architectural constraints that the code itself cannot show.&lt;br&gt;
Clean Go code is not about perfection. It is about empathy for the next developer who touches your project—even if that developer is you.Pick just one of these habits for your next pull request, and notice how much easier debugging becomes!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>go</category>
    </item>
    <item>
      <title>99.4% Accurate but still completely useless?</title>
      <dc:creator>Rajesh Singh</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:51:35 +0000</pubDate>
      <link>https://dev.to/rajinh24/994-accurate-but-still-completely-useless-2332</link>
      <guid>https://dev.to/rajinh24/994-accurate-but-still-completely-useless-2332</guid>
      <description>&lt;p&gt;Why accuracy alone can fool you on imbalanced datasets. Somewhere, an ML model is proudly reporting 99.4% accuracy.&lt;/p&gt;

&lt;p&gt;The dashboard is green. The stakeholders are smiling. Someone is probably preparing the report.&lt;/p&gt;

&lt;p&gt;Then a dangerous question appears:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How much fraud did the model actually catch?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer: &lt;strong&gt;zero&lt;/strong&gt; 😟&lt;/p&gt;

&lt;p&gt;Welcome to the accuracy trap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch the full video:&lt;/strong&gt;&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/aLCBlyht2UY"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet the world’s laziest model
&lt;/h2&gt;

&lt;p&gt;Consider a simulated dataset containing &lt;strong&gt;20,000 card transactions&lt;/strong&gt;, where only &lt;strong&gt;0.6% are fraudulent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now introduce our highly sophisticated baseline:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lazy_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction&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;not fraud&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No training. No feature engineering. No hyperparameter tuning. No GPU trying to heat the neighbourhood.&lt;/p&gt;

&lt;p&gt;It simply predicts &lt;strong&gt;“not fraud”&lt;/strong&gt; every time.&lt;/p&gt;

&lt;p&gt;And because almost every transaction is legitimate, the model achieves:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Lazy Model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Accuracy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.4%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Precision&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recall&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F1 score&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The model is correct most of the time but useful none of the time. It catches no fraud and probably still asks for a promotion. &lt;/p&gt;

&lt;h2&gt;
  
  
  Considering Precision and recall
&lt;/h2&gt;

&lt;p&gt;Accuracy asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How often was the model correct overall?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sounds reasonable until one class heavily outnumbers the other.&lt;/p&gt;

&lt;p&gt;For fraud detection, two other metrics are far more revealing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Precision&lt;/strong&gt; asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Of everything flagged as fraud, how much was actually fraud?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Low precision means your system keeps blocking genuine customers. Congratulations—you have successfully detected someone buying groceries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recall&lt;/strong&gt; asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Of all the fraud that really happened, how much did we catch?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Low recall means the fraudsters leave with the money while the model celebrates its excellent accuracy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens with a real model?
&lt;/h2&gt;

&lt;p&gt;We trained a logistic regression model using balanced class weights.&lt;/p&gt;

&lt;p&gt;Its results looked less impressive at first:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Lazy Model&lt;/th&gt;
&lt;th&gt;Logistic Regression&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Accuracy&lt;/td&gt;
&lt;td&gt;99.4%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;85.3%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Precision&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.1%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recall&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;77.8%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F1 score&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6.0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The real model has &lt;strong&gt;lower accuracy&lt;/strong&gt;, but it catches almost &lt;strong&gt;78% of the fraud&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So which model is better?&lt;/p&gt;

&lt;p&gt;The Lazy Model wins the dashboard beauty contest.&lt;/p&gt;

&lt;p&gt;The logistic regression model wins the actual fraud-detection contest. &lt;/p&gt;

&lt;h2&gt;
  
  
  Precision and recall are professional rivals
&lt;/h2&gt;

&lt;p&gt;There is usually a trade-off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower the fraud threshold and recall increases, but so do false alarms.&lt;/li&gt;
&lt;li&gt;Raise the threshold and precision may improve, but more fraud can slip through.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The “best” threshold is therefore not only a mathematical choice. It depends on business cost.&lt;/p&gt;

&lt;p&gt;What is worse?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Annoying a legitimate customer?&lt;/li&gt;
&lt;li&gt;Missing a fraudulent transaction?&lt;/li&gt;
&lt;li&gt;Sending 10,000 alerts to a fraud team with three analysts and one coffee machine?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The answer depends on the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;For imbalanced classification problems, accuracy is not useless but it is often incomplete.&lt;/p&gt;

&lt;p&gt;Always look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Precision&lt;/strong&gt; for alert quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recall&lt;/strong&gt; for detection coverage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;F1 score&lt;/strong&gt; for balance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The confusion matrix&lt;/strong&gt; for the types of mistakes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business impact&lt;/strong&gt; for what those mistakes actually cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A 99.4% accurate model can still be terrible.&lt;/p&gt;

&lt;p&gt;Metrics do not lie but they are perfectly happy to let us misunderstand them.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>llm</category>
      <category>mlops</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Staj Günlükleri #2: Mühendislikte Proje Yönetimi, Agile/Scrum ve Kurumsal Süreçler</title>
      <dc:creator>derykuscu</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:35:42 +0000</pubDate>
      <link>https://dev.to/derykuscu/staj-gunlukleri-2-muhendislikte-proje-yonetimi-agilescrum-ve-kurumsal-surecler-1bom</link>
      <guid>https://dev.to/derykuscu/staj-gunlukleri-2-muhendislikte-proje-yonetimi-agilescrum-ve-kurumsal-surecler-1bom</guid>
      <description>&lt;p&gt;Herkese selam! 👋&lt;/p&gt;

&lt;p&gt;Eprom Elektronik bünyesindeki gömülü sistemler stajımın 2. haftasını tamamladım. Bu hafta doğrudan donanım üzerinde çalışmak yerine, mühendislik projelerinin arka planında yürütülen &lt;strong&gt;proje yönetimi metodolojileri, kurumsal dokümantasyon, depo/operasyon süreçleri ve şirket içi yazılım sistemleri&lt;/strong&gt; üzerine odaklandım.&lt;/p&gt;

&lt;p&gt;Bir mühendis adayı olarak projenin sadece kod/donanım kısmını değil, yönetimsel ve kurumsal operasyon süreçlerini de deneyimlemek vizyonum açısından oldukça verimli bir hafta oldu.&lt;/p&gt;

&lt;p&gt;İşte 2. haftada gün gün öne çıkan başlıklar ve öğrendiklerim:&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Gün Gün Hafta Özeti
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📌 1. Gün: Proje Yönetimi ve V Modeli (V-Model)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;V Modeli:&lt;/strong&gt; Donanım ve yazılım geliştirme süreçlerinde doğrulama (verification) ve geçerleme (validation) adımlarının nasıl paralel ilerlediğini inceledim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standartlar:&lt;/strong&gt; Mühendislik projelerinde bir ürünün konsept aşamasından test adımlarına kadar olan yaşam döngüsünü kavramaya odaklandım.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📌 2. Gün: PMP, PMI ve Proje Yönetim Standartları
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PMI &amp;amp; PMP:&lt;/strong&gt; Project Management Institute (PMI) standartları ve PMP (Project Management Professional) yaklaşımı üzerine araştırmalar yaptım.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Süreç Yönetimi:&lt;/strong&gt; Bir projenin başlatılması, planlanması, yürütülmesi, izlenmesi ve sonlandırılması (Lifecycle) aşamalarının kurumsal yapılarda nasıl karşılık bulduğunu inceledim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📌 3. Gün: Çevik Metodolojiler (Agile &amp;amp; Scrum Framework)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agile Yaklaşımı:&lt;/strong&gt; Değişen gereksinimlere hızlı uyum sağlayan esnek proje yönetim mantığını araştırdım.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scrum Yapısı:&lt;/strong&gt; Sprint'ler, Daily Stand-up toplantıları, Backlog yönetimi ve Scrum rolleri (Product Owner, Scrum Master, Team) üzerine durarak gömülü/yazılım projelerine entegrasyonunu değerlendirdim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📌 4. Gün: Belge Tarama, Dosyalama ve Barkod/Etiket Operasyonları
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Saha &amp;amp; Operasyon Süreçleri:&lt;/strong&gt; Şirket içi belge tarama, dijital arşivleme, dosyalama standartları ve sistemli veri kayıt adımlarını tecrübe ettim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Barkodlama:&lt;/strong&gt; Ürün ve bileşen takibi için barkod okuma, etiket çıkartma, fiziksel etiket yapıştırma ve bunların veritabanı/sistem kayıt süreçlerini uyguladım.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📌 5. Gün: Kurumsal Yazılımlar (Redmine &amp;amp; Netsis Arayüz İncelemeleri)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Redmine (Proje &amp;amp; Görev Takibi):&lt;/strong&gt; Şirket içinde kullanılan açık kaynaklı proje yönetim ve issue/bug takip arayüzü Redmine'ı inceledim. Görev açma, efor takibi ve iş dağılımı süreçlerini gözlemledim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Netsis (ERP Sistemleri):&lt;/strong&gt; Kurumsal kaynak planlaması (ERP) tarafında Netsis arayüzünü inceleyerek stok, malzeme, depo ve kurumsal operasyon verilerinin sistem üzerinde nasıl yönetildiğini öğrendim.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Bu Haftadan Çıkardığım Notlar
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sadece Kod Değil, Süreç Yönetimi:&lt;/strong&gt; Harika bir donanım veya yazılım geliştirmek tek başına yeterli değil. Ürünün PMP veya Agile standartlarında doğru yönetilmesi ve belgelenmesi projenin başarısını doğrudan belirliyor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;İzlenebilirlik (Traceability):&lt;/strong&gt; Barkodlama ve Netsis/Redmine gibi ERP ve görev takip araçları sayesinde bir ürünün en küçük bileşeninden en üst görev adımlarına kadar izlenebilir olmasının kurumsal firmalarda ne kadar kritik olduğunu gördüm.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;💬 &lt;strong&gt;Yorumlarda Buluşalım!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yazılım veya donanım projelerinizde geleneksel yöntemleri mi (Waterfall/V-Model) yoksa çevik yöntemleri mi (Agile/Scrum) tercih ediyorsunuz? Şirketlerinizde Redmine veya benzeri ERP araçlarını nasıl entegre ediyorsunuz? Yorumlarda tecrübelerinizi paylaşırsanız çok sevinirim!&lt;/p&gt;

</description>
      <category>career</category>
      <category>agile</category>
      <category>management</category>
      <category>internship</category>
    </item>
    <item>
      <title>The MCP 2026-07-28 spec is final - check your server in one command!</title>
      <dc:creator>Alex Akimov</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:24:56 +0000</pubDate>
      <link>https://dev.to/mcpscore/the-mcp-2026-07-28-spec-is-final-check-your-server-in-one-command-438k</link>
      <guid>https://dev.to/mcpscore/the-mcp-2026-07-28-spec-is-final-check-your-server-in-one-command-438k</guid>
      <description>&lt;p&gt;The &lt;a href="https://blog.modelcontextprotocol.io/posts/2026-07-28/" rel="noopener noreferrer"&gt;Model Context Protocol's 2026-07-28 revision&lt;/a&gt; went final on July 28. It's a meaningful one: the lifecycle moves to stateless requests. If you maintain an MCP server, the two questions are: &lt;em&gt;is my server still well-built, and is it ready for the new spec?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mcpscore&lt;/strong&gt; answers both in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvx mcpscore https://your-server.example/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No install, no API key. In a few seconds you get a 0–100 quality score and a list of exactly what to fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it checks
&lt;/h2&gt;

&lt;p&gt;72 deterministic rules, each citing the spec section it enforces, grouped into four categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocol&lt;/strong&gt;: version negotiation, transport correctness, error shapes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools Quality&lt;/strong&gt;: names, titles, descriptions, input/output schemas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Auth&lt;/strong&gt;: TLS, auth posture, safe error handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readiness&lt;/strong&gt;: how ready you are for the 2026-07-28 lifecycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's deterministic - the same server always gets the same score, so it's stable in CI, and it's read-only: it lists your tools and probes behavior but never calls a tool, so auditing is side-effect-free. Local servers in any language audit over stdio too — &lt;code&gt;mcpscore --stdio ./my-go-server&lt;/code&gt;, &lt;code&gt;--stdio java -jar server.jar&lt;/code&gt; — not just &lt;code&gt;.py&lt;/code&gt;/&lt;code&gt;.js&lt;/code&gt; files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Servers behind OAuth
&lt;/h2&gt;

&lt;p&gt;Most production MCP servers are auth-gated, and until now that meant unauditable. This release changes that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# full audit with your token (also reads MCPSCORE_TOKEN)&lt;/span&gt;
uvx mcpscore &lt;span class="nt"&gt;--token&lt;/span&gt; &lt;span class="nv"&gt;$TOKEN&lt;/span&gt; https://api.example.com/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with no credentials at all, a 401 server gets a &lt;strong&gt;partial audit&lt;/strong&gt; of its observable surface, including auth-posture rules that check the &lt;code&gt;WWW-Authenticate&lt;/code&gt; challenge, RFC 9728 protected-resource metadata, the authorization server's RFC 8414 metadata, and PKCE support. The gate itself Tokens never appear in logs or reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  In CI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mcp-box/mcpscore-action@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://your-server.example/mcp&lt;/span&gt;
    &lt;span class="na"&gt;min-score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It comments the report on the PR and fails the check below your threshold.&lt;/p&gt;

&lt;h2&gt;
  
  
  The badge
&lt;/h2&gt;

&lt;p&gt;Add a live score badge to your README from the report page at &lt;a href="https://mcpscore.dev" rel="noopener noreferrer"&gt;mcpscore.dev&lt;/a&gt; - it reflects your server's latest score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "score", not "audit"
&lt;/h2&gt;

&lt;p&gt;There's a good official conformance suite for "is my server legal." mcpscore is the other question - "how good is it" - the way Lighthouse scores a web page's quality, not just its validity. It runs on the official MCP Python SDK v2, it's open source (MIT), and the methodology is public: &lt;a href="https://docs.mcpscore.dev/methodology" rel="noopener noreferrer"&gt;https://docs.mcpscore.dev/methodology&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Point it at your server and see where you land!&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
