<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Basavaraj SH</title>
    <description>The latest articles on DEV Community by Basavaraj SH (@basavaraj_sh_1ea7d95f0f2e).</description>
    <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3972738%2F6b40a4fd-25b3-402e-a9db-2dd77e574036.jpg</url>
      <title>DEV Community: Basavaraj SH</title>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/basavaraj_sh_1ea7d95f0f2e"/>
    <language>en</language>
    <item>
      <title>The Safety Check That Runs on the Conversation, Not the Turn</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Wed, 07 Oct 2026 12:38:48 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-safety-check-that-runs-on-the-conversation-not-the-turn-4573</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-safety-check-that-runs-on-the-conversation-not-the-turn-4573</guid>
      <description>&lt;p&gt;Common Sense Media just called OpenAI's teen-oriented ChatGPT an unacceptable risk for young users - months after it launched with guardrails specifically for that group. A product built to be safe can fail review while every individual response looks fine. That's the key tension for anyone shipping AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-Turn Filtering vs. Session-Level Evaluation
&lt;/h2&gt;

&lt;p&gt;Almost every moderation setup starts the same way: classify each incoming message and each outgoing response against a policy, block or rewrite what fails. It's cheap, fast, stateless, and easy to audit - one input, one verdict, one log line.&lt;/p&gt;

&lt;p&gt;It also can't see drift. A conversation that gets gradually more personal, more dependent, or more role-play-committed over thirty turns produces thirty individually clean messages. The harm emerges in the trajectory, not the turn. That's the mismatch: some platforms evaluate sessions, while most teams evaluate messages.&lt;/p&gt;

&lt;p&gt;So the decision is whether to add a &lt;strong&gt;session-level evaluator&lt;/strong&gt; - a second check that reads the conversation so far and judges the arc, not the line. The cost is real: more tokens, added latency, a new false-positive surface where a legitimate long tutoring session gets flagged. The usual rejected alternative - just make the per-turn classifier stricter - is cheaper but trades directly against usefulness, because the only way a stateless filter catches drift is by over-blocking turns that are fine in isolation.&lt;/p&gt;

&lt;p&gt;Look at your eval suite to determine which one you need. If every test case is one prompt and one expected response, you have no visibility into the failure mode reviewers will actually report.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Drift Test Case Looks Like
&lt;/h2&gt;

&lt;p&gt;Multi-turn evals aren't exotic. They're a fixture file:&lt;br&gt;
&lt;/p&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;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;escalation-dependency-01&lt;/span&gt;
 &lt;span class="na"&gt;persona&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15yo, late night, repeat user&lt;/span&gt;
 &lt;span class="na"&gt;turns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt; &lt;span class="c1"&gt;# scripted, gradually more personal&lt;/span&gt;
 &lt;span class="na"&gt;assert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;per_turn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no_policy_violation&lt;/span&gt;
 &lt;span class="na"&gt;per_session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;support_resource_offered_by_turn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;persona_roleplay_persists&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;encourages_offline_contact&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two assertion layers, one fixture. The per-turn checks are what you already have. The per-session checks are the new thing, and they're the ones that fail.&lt;/p&gt;

&lt;p&gt;On the runtime side, you don't need the session evaluator on every turn. Trigger it: run it every N turns, or when a cheap risk score crosses a threshold, or when conversation length passes the point where your per-turn data stopped being representative. That keeps the added latency off the median request and on the small slice of sessions where it matters.&lt;/p&gt;

&lt;p&gt;For a PM, this is a scoping conversation, not an architecture one: "our safety testing covers single exchanges, and the reviews that will hurt us test long ones" is a fundable gap with a clear boundary.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Per-turn moderation is cheap and auditable but structurally blind to conversations that drift over many turns.&lt;/li&gt;
&lt;li&gt;Tightening the per-turn classifier to compensate buys safety by making the product worse at normal long tasks - it's the wrong lever.&lt;/li&gt;
&lt;li&gt;Trigger session-level checks on length or risk score rather than every turn, so the cost lands only where the risk does.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's the longest conversation any test case in your eval suite actually runs - and is it longer than your median real session?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: The Verge, Common Sense Media&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>evals</category>
      <category>trustandsafety</category>
    </item>
    <item>
      <title>Subscription Seats vs API Keys: Running the Break-Even Math</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Tue, 06 Oct 2026 12:47:41 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/subscription-seats-vs-api-keys-running-the-break-even-math-520g</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/subscription-seats-vs-api-keys-running-the-break-even-math-520g</guid>
      <description>&lt;p&gt;A Hacker News thread comparing the value of Anthropic and OpenAI subscriptions turned into something more useful than a vendor scoreboard: people posting their actual usage and realizing they were paying the wrong way for it. Flat-rate seats and metered API keys are the same capability priced on two different axes, and most teams pick one by habit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Decision Is Billing Shape, Not Vendor
&lt;/h2&gt;

&lt;p&gt;A subscription is a flat monthly fee per person with soft usage caps. An API key is pay-per-token with no ceiling. Does your usage pattern reward a fixed price or a variable one? That's the distinction that matters before you compare vendors—who gives more value per dollar is secondary.&lt;/p&gt;

&lt;p&gt;Heavy, steady, interactive use favors seats. Someone coding against a model for six hours a day will blow past any flat fee's token-equivalent value, and the vendor pays for that. Bursty, automated, or embedded use favors the API: a feature that calls a model twice per user session doesn't need a seat, and more importantly, a seat can't be called from your backend anyway.&lt;/p&gt;

&lt;p&gt;Teams buy seats for people who use the model twice a week, or run batch jobs on API keys that would have been free under a plan someone already pays for. Both are quiet, recurring waste that nobody's dashboard flags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Your Logs and Compute It
&lt;/h2&gt;

&lt;p&gt;You don't need a model to decide this. You need last month's token counts per person, which every provider console exports.&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="n"&gt;seat_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;100.00&lt;/span&gt; &lt;span class="c1"&gt;# flat monthly plan, per person
&lt;/span&gt;&lt;span class="n"&gt;blended_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.00&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="c1"&gt;# your $ per token, input+output mixed
&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18_000_000&lt;/span&gt; &lt;span class="c1"&gt;# last month, one person, from your logs
&lt;/span&gt;
&lt;span class="n"&gt;api_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;blended_rate&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_cost&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; metered vs $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;seat_price&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buy the seat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;api_cost&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;seat_price&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stay on the API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it per person, not as a team average. Averages hide the shape of the distribution - in my experience a few people generate the majority of tokens, and those are the only ones where a seat clearly wins.&lt;/p&gt;

&lt;p&gt;Then apply two adjustments the math misses. First, subscription plans have usage limits that reset on a schedule; if your heaviest user hits them and stalls mid-task, the lost hours cost more than the metered overage would have. Second, anything that runs without a human present - evals, pipelines, product features - belongs on an API key regardless of price, because seat terms generally cover personal interactive use. That's a terms question, not a cost question, and it isn't negotiable with a spreadsheet.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Decide billing shape before vendor: flat seats suit heavy interactive users, metered keys suit bursty or automated workloads.&lt;/li&gt;
&lt;li&gt;Compute break-even per person from real token logs, not team averages - usage is almost always skewed toward a few people.&lt;/li&gt;
&lt;li&gt;Automated and product-embedded calls go on API keys regardless of the math, because subscription terms assume a human in the loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What does your per-person token distribution actually look like - is it two heavy users carrying the team, or spread evenly?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: Hacker News discussion comparing Anthropic and OpenAI subscription value&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>api</category>
      <category>anthropic</category>
      <category>openai</category>
    </item>
    <item>
      <title>Log Safety Events, Not Full Transcripts: One Audit Trade-Off</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:10:48 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/log-safety-events-not-full-transcripts-one-audit-trade-off-2lpo</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/log-safety-events-not-full-transcripts-one-audit-trade-off-2lpo</guid>
      <description>&lt;p&gt;The FTC's inquiry into consumer AI products has turned a question most teams deferred into a launch requirement: &lt;em&gt;can you show what your product actually did?&lt;/em&gt; That answer depends on a logging decision you make before launch - and can't retroactively fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content vs. Event
&lt;/h2&gt;

&lt;p&gt;Teams face two extremes. Keep every conversation, or keep nothing.&lt;/p&gt;

&lt;p&gt;Full transcripts answer any future question, which is exactly why they're expensive. Every retained message is breach surface, subpoena surface, and a trust cost you pay in your privacy policy. Teams that choose this path often discover their retention window was set by whoever wrote the database schema, not by anyone who thought about risk.&lt;/p&gt;

&lt;p&gt;Keeping nothing is cheap and genuinely privacy-protective - until someone asks how often your assistant encountered a user in distress and what it said back. You can't answer. Not "we'd rather not" - you structurally cannot, and neither can your own safety team, which means you also can't tell whether last month's guardrail change helped.&lt;/p&gt;

&lt;p&gt;The third option is to log the &lt;em&gt;decision&lt;/em&gt; rather than the content. For each turn, write a structured event: which classifier fired (a classifier here is just a small model or rule that labels input, e.g. "self-harm mention" or "minor-related"), what action the system took, which policy and model version were live, a session hash. No raw user text.&lt;/p&gt;

&lt;p&gt;How do you tell which you need? Ask what question you'll be asked. Aggregate questions - &lt;em&gt;how often, what did the system do, did the rate drop after the fix&lt;/em&gt; - are fully answered by event logs. Forensic questions - &lt;em&gt;why did this specific conversation go wrong&lt;/em&gt; - need content. Most teams need the first continuously and the second rarely, which argues for event logs by default plus a small consented, access-controlled transcript sample.&lt;/p&gt;

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

&lt;p&gt;A minimal safety event, emitted alongside your normal request logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"session"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:9f2c..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"ts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-18T14:03:22Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"flags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"self_harm_mention"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"crisis_resource_shown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"policy_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"safety-2025.11.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chat-v4.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"transcript_retained"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six fields, no user content. From a month of these you can report: how many sessions triggered the flag, what percentage received the intended response, and whether that percentage improved after &lt;code&gt;safety-2025.11.1&lt;/code&gt; shipped. That is the shape of a regulatory question.&lt;/p&gt;

&lt;p&gt;The honest limitation: if a journalist surfaces one bad conversation, these logs tell you the system &lt;em&gt;classified&lt;/em&gt; it and what it &lt;em&gt;did&lt;/em&gt; - not what the user typed. That gap is the price. Decide consciously whether you pay it, and whether a 1% sampled transcript set with clear user disclosure closes it well enough.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Event-level safety logging answers aggregate accountability questions at a fraction of the privacy exposure of full transcript retention - the two are not equally risky.&lt;/li&gt;
&lt;li&gt;Pick based on the question you expect: rates and trends need events; single-conversation forensics needs sampled content, with disclosure and tight access control.&lt;/li&gt;
&lt;li&gt;Logging is not backfillable. Whatever you don't capture before launch is gone from your first safety review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a regulator asked tomorrow how your product handled distressed users last quarter, which fields in your current logs would actually answer it?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion on the FTC inquiry into OpenAI, Anthropic and other AI companies&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>observability</category>
      <category>privacy</category>
      <category>ai</category>
    </item>
    <item>
      <title>Pro Seats vs Metered API: Where the Break-Even Actually Falls</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Tue, 29 Sep 2026 12:11:43 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/pro-seats-vs-metered-api-where-the-break-even-actually-falls-pbe</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/pro-seats-vs-metered-api-where-the-break-even-actually-falls-pbe</guid>
      <description>&lt;p&gt;OpenAI reopening its $200/month Pro tier put a familiar budgeting question back on the table for teams: do you buy people flat-rate seats, or do you wire the same models in through the metered API and pay per token? Most teams pick by vibes. There's a two-minute calculation that settles it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You're Actually Buying at $200 a Seat
&lt;/h2&gt;

&lt;p&gt;A flat seat and an API key give you access to similar models, but they're different products. The seat is an unmetered interactive surface for one human - chat, file uploads, the newest reasoning models, no per-request accounting. The API is programmatic access with logging, routing, prompt control, and a bill that moves with usage.&lt;/p&gt;

&lt;p&gt;No cost-attribution overhead, no finance conversation about whose experiment spiked the bill, and a hard ceiling on what one user can spend - these are the things the seat quietly includes. At typical per-token rates, a single person doing heavy chat work all month rarely approaches $200 in raw inference cost. The API looks cheaper until you count these things. The seat's real product is predictability. The API's real product is control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the Numbers Before You Argue About Them
&lt;/h2&gt;

&lt;p&gt;Plug your own provider's current rates and your team's actual usage into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;seat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="c1"&gt;# flat monthly subscription
&lt;/span&gt;&lt;span class="n"&gt;in_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="c1"&gt;# $ per 1M tokens (check live pricing)
&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_tok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_tok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt; &lt;span class="c1"&gt;# per user, per month
&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_tok&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1e6&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;in_rate&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;out_tok&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1e6&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 22.95 vs 200
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At that usage - roughly 45 substantial requests a workday - metered access costs about a ninth of a seat. Break-even lands near 7,800 calls per user per month, or about 390 a day. No human types that much. An agent loop hits it before lunch.&lt;/p&gt;

&lt;p&gt;The decision line is: &lt;strong&gt;who or what is generating the requests.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A person in a chat window&lt;/strong&gt; → seat. You'd need to 8x a heavy user's volume to justify the switch, and you'd pay for that in engineering time building the interface they already have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An automated pipeline or agent&lt;/strong&gt; → API. Volume scales past break-even fast, and you need the logging and retry control anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The messy middle&lt;/strong&gt; - a human clicking a button that fans out into 300 model calls - → API, with a per-user spend cap. This is where teams get surprise invoices, because the usage &lt;em&gt;feels&lt;/em&gt; human-scale and isn't.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One more thing the math hides: variance. A seat caps your downside at $200. A runaway retry loop on the API does not cap anything. If your team is early and your guardrails are thin, paying a premium for a known number is a defensible call - just make it on purpose.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Compare flat seats and metered API on request volume per user, not headline price - break-even often sits near 8,000 calls a month.&lt;/li&gt;
&lt;li&gt;Seats buy predictability and a ready-made interface; the API buys control, logging, and the ability to scale past a single human's output.&lt;/li&gt;
&lt;li&gt;Human-driven work that silently fans out into hundreds of calls is where budgets break. Cap per-user spend before you ship it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's your team's actual monthly call volume per user - and have you ever measured it, or are you estimating?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: Hacker News discussion on OpenAI re-opening Pro subscriptions&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>llm</category>
      <category>api</category>
      <category>python</category>
    </item>
    <item>
      <title>Test Your Agent Config With Telemetry Off, Not On</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Thu, 24 Sep 2026 11:11:53 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/test-your-agent-config-with-telemetry-off-not-on-4dgp</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/test-your-agent-config-with-telemetry-off-not-on-4dgp</guid>
      <description>&lt;p&gt;A bug report made the rounds recently: a coding agent only picked up its instructions file when telemetry was enabled. Whatever the root cause, it exposes a decision most teams make badly - how you verify that an AI agent actually read the config you gave it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea: Verify Behavior, Not Presence
&lt;/h2&gt;

&lt;p&gt;When you hand an agent a config file - an &lt;code&gt;AGENTS.md&lt;/code&gt;, a system prompt, a tool allowlist - there are two ways to confirm it landed.&lt;/p&gt;

&lt;p&gt;The first is to check that the file was loaded. You look at logs, traces, or a debug flag that prints the resolved config. This is fast and it feels rigorous. You are inspecting a code path that only exists because you turned instrumentation on. If loading is coupled to the observability layer - an initialization order problem, a lazy load behind a flag, a plugin that registers the file reader - your check passes in exactly the conditions where the bug can't happen.&lt;/p&gt;

&lt;p&gt;The second is to test for a behavior the config uniquely causes. Write one rule into the file that changes an observable output. Then run the agent the way a normal user would with all instrumentation off and see if the output changes. Slower to set up, but it tests the path your users actually run.&lt;/p&gt;

&lt;p&gt;Most teams pick the first, because the second requires designing a rule whose absence is obvious. That design work is the actual cost, and it's worth paying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example: A Canary Rule
&lt;/h2&gt;

&lt;p&gt;Add a line to the config that does nothing useful except prove it was read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Output convention&lt;/span&gt;
Prefix every commit message with [cfg-ok].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run a check that never touches your debug tooling:&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;# no --verbose, no DEBUG=1, no OTEL exporter&lt;/span&gt;
claude &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"commit the staged changes"&lt;/span&gt; 
git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%s | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s1"&gt;'^\[cfg-ok\]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FAIL: config not applied in default mode"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this in CI on every agent-version bump. It costs one model call. When it fails, you learn something a trace-based check structurally cannot tell you: the config is being ignored in the default configuration, which is the one every user is in.&lt;/p&gt;

&lt;p&gt;For a PM, this is a one-line acceptance criterion: &lt;em&gt;our config test runs with logging disabled.&lt;/em&gt; You don't need to read the agent's source to ask whether the verification path and the production path are the same path. If the answer is no, the test is measuring something other than what you shipped.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Checking that a config file &lt;em&gt;loaded&lt;/em&gt; and checking that it &lt;em&gt;changed behavior&lt;/em&gt; are different tests, and only the second survives instrumentation bugs.&lt;/li&gt;
&lt;li&gt;Put a canary rule in every agent config - a small, observable output change whose absence is unambiguous.&lt;/li&gt;
&lt;li&gt;Run the canary in default mode with logging off, in CI, on every version bump. One model call, real coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's the one instruction in your agent's config whose absence you'd notice within a single run?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: Hacker News discussion on Claude Code and AGENTS.md telemetry behavior&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>claudecode</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>Give the Risk Agent a Veto, Not a Vote</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Tue, 08 Sep 2026 11:59:44 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/give-the-risk-agent-a-veto-not-a-vote-34jk</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/give-the-risk-agent-a-veto-not-a-vote-34jk</guid>
      <description>&lt;p&gt;Multi-agent LLM trading frameworks keep surfacing on Hacker News, and the discussion usually fixates on the roster: a news analyst, a fundamentals analyst, a technician, a debate round. The design choice that matters most is how you combine what those agents say.&lt;/p&gt;

&lt;h2&gt;
  
  
  Averaging Hides the One Agent Who Was Right
&lt;/h2&gt;

&lt;p&gt;There are two ways to turn several agent opinions into one action: weighted voting, where every agent returns a direction and a confidence score and you average them into a signal, or a gate, where analysts vote on direction but a separate risk agent holds binary authority to block the trade outright.&lt;/p&gt;

&lt;p&gt;Voting feels fairer and it's easier to tune. It also quietly buries asymmetric information. If three agents are mildly bullish and one has read a footnote about a restated quarter, averaging reduces that objection into a small discount on position size. In domains where the loss distribution is fat-tailed - a handful of outcomes that dwarf all the others - you don't want the rare correct objection smoothed into the mean.&lt;/p&gt;

&lt;p&gt;The trade-off is real. A veto costs you trades that would have worked, and it hands one model the ability to freeze the system on a hallucination. So you constrain it: the risk agent can only fire on enumerated conditions, and every block must name the rule it triggered and cite the document it relied on. An unexplained block is logged as a system failure, not as a block.&lt;/p&gt;

&lt;p&gt;The way to choose is by examining the shape of the error, not average accuracy. Symmetric, small, noisy errors favor voting, because averaging genuinely cancels noise. Rare and large errors favor a gate.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# analysts vote on direction; risk holds a separate switch
&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;weighted_vote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fundamentals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;technicals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;veto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;risk_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position_limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_blackout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity_floor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;veto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blocked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;veto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;veto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# must name a rule AND cite a source doc
&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;veto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_notional&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details do the work. The rules list is closed, so the risk agent can't invent a reason to sit out. And &lt;code&gt;veto.evidence&lt;/code&gt; is required - if the agent blocks without pointing at a filing, a price feed, or a position record, the pipeline treats that as a broken component and escalates instead of silently doing nothing.&lt;/p&gt;

&lt;p&gt;This pattern generalizes well beyond trading. Any workflow where one agent handles irreversible or expensive actions - refunds, outbound messages, contract terms, publishing - has the same choice to make.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Choose your aggregation rule based on the shape of your losses, not average accuracy: averaging suits small symmetric errors, a gate suits rare large ones.&lt;/li&gt;
&lt;li&gt;A veto only stays trustworthy if it's limited to a closed list of conditions and must cite evidence for each block.&lt;/li&gt;
&lt;li&gt;Treat an unexplained block as a failure to investigate, not as a safe default - otherwise you've built an invisible kill switch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you gave one component in your pipeline the power to stop everything, which specific conditions would you put on its list - and how would you notice it was blocking too often?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: Hacker News discussion on a multi-agent LLM financial trading framework&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>agents</category>
      <category>python</category>
      <category>fintech</category>
    </item>
    <item>
      <title>The KV Cache Formula That Should Set Your Context Limit</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Mon, 07 Sep 2026 16:18:07 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-kv-cache-formula-that-should-set-your-context-limit-8nh</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-kv-cache-formula-that-should-set-your-context-limit-8nh</guid>
      <description>&lt;p&gt;Phone prices are climbing this year largely because memory is scarce - AI data centers are buying DRAM faster than fabs can make it. That same squeeze shows up in your cloud bill, and it changes which knob you turn first when inference gets expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Is the Binding Constraint, Not Compute
&lt;/h2&gt;

&lt;p&gt;When teams hit capacity limits serving a language model, the reflex is to ask for more GPUs. But on most serving setups the shortage isn't raw compute - it's the memory those chips carry. Model weights take a fixed slice. Everything left over goes to the KV cache: the running store of intermediate values for every token the model has already seen in a conversation. That cache grows linearly with context length and with the number of requests you serve at once.&lt;/p&gt;

&lt;p&gt;So the real decision isn't "buy more GPUs or not." It's: &lt;strong&gt;do we cap context length and retrieve the relevant parts, or do we pay for the memory to keep stuffing everything in the prompt?&lt;/strong&gt; Long-context models made the second option easy to reach for. Chipflation is making it expensive to keep reaching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Numbers Before You Ask for Budget
&lt;/h2&gt;

&lt;p&gt;The formula is simple enough to put in a planning doc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_value

# 7B-class model, GQA: 2 * 32 * 8 * 128 * 2 (fp16) = 131,072 bytes
# = 128 KB per token, per request
# 8k context -&amp;gt; 1.0 GB per request
# 32k context -&amp;gt; 4.0 GB per request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On an 80 GB accelerator with roughly 15 GB going to weights, you have ~65 GB for cache. At 32k context that's about 16 concurrent requests. At 8k, about 65. Same hardware, four times the throughput - purely from a context decision, no new chips required.&lt;/p&gt;

&lt;p&gt;That's the trade-off stated honestly: you're spending retrieval quality to buy concurrency. The way to tell whether it's worth it is not vibes. Build a held-out set of 100 - 200 real user questions, answer each one twice - once with the full long context, once with an 8k window plus retrieval - and score them. If the quality gap is inside your tolerance, cap the window. If your users routinely need reasoning across a whole document, it isn't, and the extra memory is a legitimate line item.&lt;/p&gt;

&lt;p&gt;There's a middle lever too: quantizing the KV cache to 8-bit halves the per-token cost with a smaller quality hit than truncation. Worth testing before you commit to either extreme.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Memory, not compute, usually sets your inference ceiling - and memory prices are rising for reasons outside your control.&lt;/li&gt;
&lt;li&gt;Context length and batch size drive KV cache size linearly; a 4x context cut is roughly a 4x concurrency gain on the same hardware.&lt;/li&gt;
&lt;li&gt;Decide with a scored comparison on real questions, not intuition - long context is a cost you should be able to justify.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you ran that comparison on your own traffic, how much of your current context window is actually load-bearing?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: The Verge&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>rag</category>
      <category>inference</category>
      <category>gpu</category>
    </item>
    <item>
      <title>The Handoff Check That Catches Schema-Valid Nonsense</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Mon, 07 Sep 2026 12:10:08 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-handoff-check-that-catches-schema-valid-nonsense-28jc</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-handoff-check-that-catches-schema-valid-nonsense-28jc</guid>
      <description>&lt;p&gt;Multi-agent systems tend to fail quietly. Every agent returns well-formed JSON, every eval suite goes green, and the final output is still wrong - because the failure happened in a handoff nobody inspected. The fix isn't a better model; it's a cheap invariant check between steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Schema Validation Isn't Correctness
&lt;/h2&gt;

&lt;p&gt;Most agent pipelines validate structure: does the payload have the right keys, are the types correct, does it parse. That catches malformed output, which is the easy failure. The expensive failure is a payload that passes every structural check and is still semantically false - a summarizer agent that cites a document ID the retriever never returned, a pricing agent whose &lt;code&gt;total&lt;/code&gt; doesn't equal the sum of its line items, a planner that outputs three steps when the task requires four.&lt;/p&gt;

&lt;p&gt;End-to-end evaluation misses these because it scores the final answer, usually against a small golden set. If the bad handoff happens in an edge case your eval set doesn't cover, the score stays high while production quietly degrades. A watchdog - a small function that runs between agents and asserts relationships the schema can't express - catches the error at the step where it started, not three hops later when it's untraceable.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Watchdog Between Two Agents
&lt;/h2&gt;

&lt;p&gt;The pattern is unglamorous: pure Python, no model call, runs in microseconds.&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;class&lt;/span&gt; &lt;span class="nc"&gt;HandoffError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
 &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HandoffError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: total != sum(line items)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cited_ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieved_ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
 &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HandoffError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: cited a doc that was never retrieved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then wrap each transition:&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="n"&gt;draft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;writer_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;draft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;writer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;retrieval_output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reviewer_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;guard&lt;/code&gt; raises, you have three sane options: retry the step with the error text appended to the prompt, fall back to a deterministic path, or route to a human. Log every raise with the step name - after a week you'll know exactly which agent is your weak link, which is information no aggregate eval score gives you.&lt;/p&gt;

&lt;p&gt;The design work is deciding what to assert. Good invariants are relationships between a step's input and its output: nothing cited that wasn't retrieved, no field invented that wasn't in the source, counts and sums that must reconcile. If you're a PM scoping this, that list is a spec question, not an engineering one - you likely already know the three things that must never be true in your product's output.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Structural validation and end-to-end evals both miss payloads that are well-formed but semantically wrong; those are the failures that reach users.&lt;/li&gt;
&lt;li&gt;A watchdog is a plain function between agent steps that asserts input - output relationships a JSON schema can't express - no extra model call needed.&lt;/li&gt;
&lt;li&gt;Log every guard failure by step name. That log tells you which agent is unreliable, which an aggregate score never will.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>productmanagement</category>
      <category>technology</category>
    </item>
    <item>
      <title>The Skill That Gets More Valuable When Agents Write the Draft</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 21 Aug 2026 09:00:28 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-skill-that-gets-more-valuable-when-agents-write-the-draft-520n</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/the-skill-that-gets-more-valuable-when-agents-write-the-draft-520n</guid>
      <description>&lt;p&gt;AI agents are getting good at producing the first version of almost anything - code, specs, campaign copy, analysis. The scarce skill is knowing, quickly and confidently, whether the output in front of you is right, and no longer just producing output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Idea: Specification Beats Production&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Addy Osmani, who spent 14 years at Google working on Chrome DevTools and developer experience, discussed this shift in "From Chrome DevTools to AI Engineering, with Addy Osmani" on The Pragmatic Engineer. The pattern generalizes well beyond code.&lt;/p&gt;

&lt;p&gt;Most professional work has two halves: deciding what should exist, and making it exist. Agents are reducing the cost of the second half. What they don't do is tell you the constraint you forgot, the edge case that matters to your specific customers, or that the request you made was the wrong request.&lt;/p&gt;

&lt;p&gt;So the capabilities shifting toward value are the ones that sit on either side of generation: &lt;strong&gt;specification&lt;/strong&gt; (being precise about intent, constraints, and success criteria before anything is produced) and &lt;strong&gt;evaluation&lt;/strong&gt; (judging quality against those criteria fast). The capabilities losing relative value are the ones purely about throughput - writing boilerplate, assembling a standard doc, producing a first draft from a blank page.&lt;/p&gt;

&lt;p&gt;This isn't "engineers become managers" or "PMs stop needing depth." It's the opposite. Judging an agent's output requires &lt;em&gt;more&lt;/em&gt; domain depth than producing it did, because you're reviewing without the context you'd have built by doing the work yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real Example: Rewriting Your Growth Plan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Take a data scientist whose team now uses an agent for exploratory analysis. Here's the concrete shift, step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Before:&lt;/strong&gt; 60% of the week writing pandas transforms, 20% interpreting, 20% communicating results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After:&lt;/strong&gt; 15% prompting and reviewing transforms, 45% interpreting, 40% communicating and defending conclusions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The trap:&lt;/strong&gt; the agent produced a clean-looking cohort analysis that silently dropped users with null signup dates - 8% of the sample, skewed toward one acquisition channel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Catching that required knowing the data's history, not knowing pandas. The person who spent the last two years only writing transforms wouldn't spot it. The person who spent that time arguing with stakeholders about what a "cohort" actually means would.&lt;/p&gt;

&lt;p&gt;Apply the same audit to your own week. Estimate the share of your time an agent could plausibly absorb in 18 months. Then ask what you'd have left - and whether that remainder is something you're deliberately getting better at, or something you've been coasting on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Value is shifting from producing output to specifying intent and evaluating results - both require deeper domain knowledge, not less.&lt;/li&gt;
&lt;li&gt;Reviewing AI output is harder than it looks, because you lack the context you'd have gained by doing the work manually.&lt;/li&gt;
&lt;li&gt;Audit your week: what percentage is throughput an agent could absorb, and what's the judgment layer you're actively strengthening?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's one task in your job where you can spot a wrong answer in under 30 seconds - and how did you build that instinct?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources referenced: The Pragmatic Engineer - "From Chrome DevTools to AI Engineering, with Addy Osmani"&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>agents</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>ChatGPT Search Is Firing site: Queries - Test Yours Today</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Fri, 21 Aug 2026 08:37:31 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/chatgpt-search-is-firing-site-queries-test-yours-today-1381</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/chatgpt-search-is-firing-site-queries-test-yours-today-1381</guid>
      <description>&lt;p&gt;ChatGPT's search step increasingly issues &lt;code&gt;site:&lt;/code&gt;-scoped queries rather than broad open-web searches. This single detail changes what "being findable" means for anyone with a site, docs, or a blog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What a site:-Scoped Search Actually Implies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a model decides to search, it writes the query itself. A broad query like &lt;code&gt;best invoicing tools for freelancers&lt;/code&gt; pulls from the whole index and the model picks whatever ranks. A scoped query like &lt;code&gt;site:yourdomain.com pricing&lt;/code&gt; means the model has &lt;em&gt;already&lt;/em&gt; decided your domain is the right source and now wants a specific fact from it.&lt;/p&gt;

&lt;p&gt;Broad search rewards general authority. Scoped search rewards whether the specific answer exists on a crawlable page on your domain, in text, at a URL a search index has actually seen. If your pricing lives inside a JavaScript-rendered widget, or your API rate limits are buried in a PDF, a scoped query returns nothing - and the model either guesses, hedges, or moves on to a competitor's docs page.&lt;/p&gt;

&lt;p&gt;For AI engineers building retrieval-augmented systems (RAG - feeding a model external documents at query time), this should feel familiar. It's the same failure mode as a chunk that never got indexed. The difference is the index isn't yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run the Test Yourself&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You don't need a GEO vendor to check this. Run the same scoped queries a model would generate:&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;# What a model asks when it already trusts your domain&lt;/span&gt;
site:yourdomain.com pricing
site:yourdomain.com &lt;span class="s2"&gt;"rate limit"&lt;/span&gt;
site:yourdomain.com refund policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste each into Google or Bing directly. Then check whether the answer is in the visible snippet - not three clicks deep.&lt;/p&gt;

&lt;p&gt;Then check crawlability from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://yourdomain.com/pricing | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"per month"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;curl&lt;/code&gt; returns your raw HTML but the price isn't in it, that fact is client-side rendered and invisible to most crawlers. Same test for docs pages, FAQ answers, and comparison tables.&lt;/p&gt;

&lt;p&gt;Three fixes, in order of payoff:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Put the literal answer in server-rendered HTML.&lt;/strong&gt; Prices, limits, versions, dates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give each discrete fact its own indexable URL.&lt;/strong&gt; One page answering "what are the rate limits" beats a mega-page with an anchor link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the phrasing a user would type.&lt;/strong&gt; Models generate queries from user language, not your internal product vocabulary.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is unglamorous work - closer to technical SEO hygiene than to prompt engineering. That's precisely why most teams skip it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scoped &lt;code&gt;site:&lt;/code&gt; queries mean the model already chose your domain; the only question is whether the fact is retrievable.&lt;/li&gt;
&lt;li&gt;Client-side-rendered facts are functionally invisible to the crawl step - &lt;code&gt;curl&lt;/code&gt; plus &lt;code&gt;grep&lt;/code&gt; tells you in seconds.&lt;/li&gt;
&lt;li&gt;One clear fact per indexable URL, written in user phrasing, outperforms a comprehensive page that buries it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run one scoped query for your own site right now - which specific fact came back empty that you assumed was public?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources referenced: Simon Willison's blog, Promptwatch reporting&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>search</category>
      <category>seo</category>
    </item>
    <item>
      <title>Zero Data Retention in the OpenAI API: What It Actually Controls</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Thu, 20 Aug 2026 08:33:39 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/zero-data-retention-in-the-openai-api-what-it-actually-controls-29ip</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/zero-data-retention-in-the-openai-api-what-it-actually-controls-29ip</guid>
      <description>&lt;p&gt;If you're building on top of any LLM API, knowing what happens to your request data after the response lands is not optional - it's a design decision with compliance implications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mechanism Behind Zero Data Retention
&lt;/h2&gt;

&lt;p&gt;Most API providers, by default, log your inputs and outputs for some window of time - for abuse monitoring, safety evaluation, or model improvement. Zero Data Retention (ZDR) is an opt-in policy available to eligible OpenAI API customers that instructs the platform to not persist request or response data to disk after serving the response. The data moves through memory to generate a reply, then gets discarded. No stored prompt, no stored completion.&lt;/p&gt;

&lt;p&gt;This matters most in three situations: you're passing personally identifiable information (PII) through prompts, your use case falls under a regulated industry (healthcare, finance, legal), or your enterprise contract explicitly prohibits third-party data storage. In all three, ZDR changes the answer to the question "does this vendor store our data?" from "yes, briefly" to "no, by policy."&lt;/p&gt;

&lt;p&gt;The tradeoff is real: some safety and quality features - like certain content classifiers and abuse-detection pipelines - depend on stored logs. OpenAI is previewing a feature called Private Safety Processing to close this gap, running safety checks in a way that doesn't require retaining the underlying request content. The architecture isn't fully public yet, but the direction is toward keeping safety enforcement and data minimization from being mutually exclusive.&lt;/p&gt;

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

&lt;p&gt;If you're on an eligible plan, ZDR is configured at the organization level, not per-request. Here's a minimal API call - the ZDR guarantee applies to the entire session once enabled, so no extra header or flag is needed in the request itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize this contract clause: ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&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="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference from a standard call: zero. That's the point. Your org-level ZDR setting does the work. If you're unsure whether your account has ZDR enabled, it shows up under your organization's data controls in the API dashboard - not in code.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Zero Data Retention means request and response data isn't persisted after the API call completes - it's a policy control, not a cryptographic guarantee&lt;/li&gt;
&lt;li&gt;ZDR is org-level, not request-level - it applies across your account once enabled, requiring no per-call code changes&lt;/li&gt;
&lt;li&gt;Private Safety Processing aims to decouple safety monitoring from data retention, though its implementation details are still emerging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For PMs and builders using LLM APIs with sensitive user data: have you actually checked your org's data retention settings, or are you assuming the default is private?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: OpenAI Blog - Offering Zero Data Retention for frontier models&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>llm</category>
      <category>api</category>
      <category>privacy</category>
    </item>
    <item>
      <title>GPT-4o API Costs Dropped 50% - How to Recalculate Your AI Budget</title>
      <dc:creator>Basavaraj SH</dc:creator>
      <pubDate>Tue, 18 Aug 2026 12:55:03 +0000</pubDate>
      <link>https://dev.to/basavaraj_sh_1ea7d95f0f2e/gpt-4o-api-costs-dropped-50-how-to-recalculate-your-ai-budget-cj</link>
      <guid>https://dev.to/basavaraj_sh_1ea7d95f0f2e/gpt-4o-api-costs-dropped-50-how-to-recalculate-your-ai-budget-cj</guid>
      <description>&lt;p&gt;OpenAI has cut prices on its frontier models again. If you're running any production workload on the API, your cost assumptions from six months ago are probably stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Impact of a Pricing Halving
&lt;/h2&gt;

&lt;p&gt;A 50% price cut sounds like pure good news, but it changes the calculus on decisions you already made. Projects you shelved because the token costs didn't pencil out deserve a second look. Architectures you built around cheaper, less capable models to save money may now be false economies - the cost gap between "good enough" and "best available" just got smaller.&lt;/p&gt;

&lt;p&gt;The more interesting shift is for teams running retrieval-augmented generation (RAG) pipelines - systems that pull relevant documents from a database at query time and feed them into the model as context. RAG workflows tend to be token-heavy because every retrieved chunk counts against your input token bill. At the old pricing, teams were aggressively trimming context windows and limiting retrieved chunks to stay within budget. At half the cost, you can retrieve more, keep longer context, and let the model reason over richer information - without changing a line of retrieval logic.&lt;/p&gt;

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

&lt;p&gt;Here's a simplified cost check you can drop into any project that calls the OpenAI API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;

&lt;span class="c1"&gt;# Approximate pricing per 1M tokens (check platform.openai.com for current rates)
&lt;/span&gt;&lt;span class="n"&gt;INPUT_COST_PER_1M&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.50&lt;/span&gt; &lt;span class="c1"&gt;# update to current figure
&lt;/span&gt;&lt;span class="n"&gt;OUTPUT_COST_PER_1M&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.00&lt;/span&gt; &lt;span class="c1"&gt;# update to current figure
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;estimate_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;INPUT_COST_PER_1M&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
 &lt;span class="n"&gt;output_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;OUTPUT_COST_PER_1M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Example: a RAG call with 3,000 input tokens and 500 output tokens
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimated cost per call: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;estimate_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Run this across your monthly volume to see the real delta
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiply that per-call number by your actual monthly call volume and compare it against what you budgeted. For many teams, the difference will justify revisiting chunk size limits, context window caps, or the decision to use a smaller model.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;A 50% price cut isn't just savings - it's a reason to reopen architecture decisions made under tighter cost constraints.&lt;/li&gt;
&lt;li&gt;RAG pipelines benefit disproportionately because they're input-token-heavy; more retrieved context is now affordable without budget gymnastics.&lt;/li&gt;
&lt;li&gt;Always re-anchor cost estimates to current pricing before committing to a new model tier or retrieval design - rates shift faster than most project roadmaps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's the one workflow in your stack where you cut corners on context length to keep costs down - and would you rebuild it now that the math has changed?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources referenced: HackerNews discussion thread, OpenAI platform pricing page&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openai</category>
      <category>rag</category>
      <category>python</category>
    </item>
  </channel>
</rss>
