<?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: Mandar S</title>
    <description>The latest articles on DEV Community by Mandar S (@mavericksh).</description>
    <link>https://dev.to/mavericksh</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%2F1407450%2Fdf1b8a38-b5ba-4fef-bb53-010ba228a5b1.jpeg</url>
      <title>DEV Community: Mandar S</title>
      <link>https://dev.to/mavericksh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mavericksh"/>
    <language>en</language>
    <item>
      <title>Stopping a runaway AI agent before the provider bills you</title>
      <dc:creator>Mandar S</dc:creator>
      <pubDate>Sun, 01 Nov 2026 13:40:31 +0000</pubDate>
      <link>https://dev.to/mavericksh/stopping-a-runaway-ai-agent-before-the-provider-bills-you-29e9</link>
      <guid>https://dev.to/mavericksh/stopping-a-runaway-ai-agent-before-the-provider-bills-you-29e9</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclosure&lt;/strong&gt;: I build Cognocient AI, an LLM proxy that does this. The post is mostly about the approaches, which apply whatever you use.&lt;/p&gt;

&lt;p&gt;Most cost tools report spend after the provider has billed you. For agents that's too late, because a loop can spend hundreds of dollars in minutes. Checks that work &lt;em&gt;before&lt;/em&gt; the call goes out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Per-run budgets.&lt;/strong&gt; Each call in a loop looks cheap; only the run total is the problem. Tag every call in a run with one run ID and enforce the budget across all of them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop detection.&lt;/strong&gt; Stop a session after N identical tool calls in a row, or a streak of errors. (In our product: 3 identical calls, Growth plan.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity limits in dollars, not just requests.&lt;/strong&gt; Tokens per minute and dollars per minute catch a flood that request-count limits miss when calls get long.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reserve before calling.&lt;/strong&gt; Reserve the expected cost atomically before forwarding, then settle with the real cost afterwards. Otherwise 20 parallel calls all pass a budget check that only one of them should have passed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read/write-aware degrading.&lt;/strong&gt; When the budget runs out, hard-stop calls whose tools look like writes, and let read-only calls continue on a cheaper model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A kill switch.&lt;/strong&gt; One button that blocks everything, for when you're not sure what's happening.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Trade-off&lt;/strong&gt;: all of this means sitting in the request path. That's a code change (one base URL) and some latency. If you only need reports after the fact, a read-only billing integration is simpler.&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;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cognocient.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;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;&amp;lt;cognocient key&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[...],&lt;/span&gt;
    &lt;span class="n"&gt;extra_headers&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;X-Cost-Feature&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;support-agent&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;X-Cost-Run-ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# one budget across every call in this run
&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;



</description>
      <category>mcp</category>
      <category>devops</category>
      <category>ai</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Your Anthropic bill doesn't fit FOCUS. Here's how to convert it (and the cached-token trap)</title>
      <dc:creator>Mandar S</dc:creator>
      <pubDate>Sun, 01 Nov 2026 13:35:30 +0000</pubDate>
      <link>https://dev.to/mavericksh/your-anthropic-bill-doesnt-fit-focus-heres-how-to-convert-it-and-the-cached-token-trap-4ll0</link>
      <guid>https://dev.to/mavericksh/your-anthropic-bill-doesnt-fit-focus-heres-how-to-convert-it-and-the-cached-token-trap-4ll0</guid>
      <description>&lt;p&gt;FOCUS is the FinOps Foundation's open billing format. AWS, Azure and Google Cloud can export it, so cloud costs from different providers land in the same columns. AI providers don't export it yet, and their CSVs don't map cleanly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cached-token trap
&lt;/h3&gt;

&lt;p&gt;Anthropic's Console splits input tokens into four buckets, each at a different price:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Token type&lt;/th&gt;
&lt;th&gt;Price relative to base input&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Uncached input&lt;/td&gt;
&lt;td&gt;1x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache read&lt;/td&gt;
&lt;td&gt;0.1x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache write, 5 minutes&lt;/td&gt;
&lt;td&gt;1.25x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache write, 1 hour&lt;/td&gt;
&lt;td&gt;2x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenAI does it differently: cached tokens are counted &lt;em&gt;inside&lt;/em&gt; prompt tokens. If you treat both exports the same way, you either count cached input twice (OpenAI) or lose the cache writes (Anthropic). Cache writes are billed, not just reported, which surprises people.&lt;/p&gt;

&lt;h3&gt;
  
  
  One row per meter
&lt;/h3&gt;

&lt;p&gt;The fix is to give every token type its own row, its own SKU and its own unit price, like a cloud bill does for each meter. Here's one real day from my own October Anthropic export after conversion (a few of the 40 columns shown; prices are per million tokens):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ChargePeriodStart&lt;/th&gt;
&lt;th&gt;SkuId&lt;/th&gt;
&lt;th&gt;SkuMeter&lt;/th&gt;
&lt;th&gt;ConsumedQuantity&lt;/th&gt;
&lt;th&gt;ListUnitPrice&lt;/th&gt;
&lt;th&gt;BilledCost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2026-10-28&lt;/td&gt;
&lt;td&gt;anthropic/claude-sonnet-4-5/input&lt;/td&gt;
&lt;td&gt;Input Tokens&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;td&gt;0.000156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10-28&lt;/td&gt;
&lt;td&gt;anthropic/claude-sonnet-4-5/cache-read&lt;/td&gt;
&lt;td&gt;Cache Read Input Tokens&lt;/td&gt;
&lt;td&gt;5,775&lt;/td&gt;
&lt;td&gt;0.30&lt;/td&gt;
&lt;td&gt;0.0017325&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10-28&lt;/td&gt;
&lt;td&gt;anthropic/claude-sonnet-4-5/cache-write-5m&lt;/td&gt;
&lt;td&gt;Cache Write Input Tokens (5 min)&lt;/td&gt;
&lt;td&gt;1,925&lt;/td&gt;
&lt;td&gt;3.75&lt;/td&gt;
&lt;td&gt;0.00721875&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10-28&lt;/td&gt;
&lt;td&gt;anthropic/claude-sonnet-4-5/output&lt;/td&gt;
&lt;td&gt;Output Tokens&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;15.00&lt;/td&gt;
&lt;td&gt;0.00024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10-28&lt;/td&gt;
&lt;td&gt;anthropic/claude-haiku-4-5/cache-write-5m&lt;/td&gt;
&lt;td&gt;Cache Write Input Tokens (5 min)&lt;/td&gt;
&lt;td&gt;23,016&lt;/td&gt;
&lt;td&gt;1.25&lt;/td&gt;
&lt;td&gt;0.02877&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Look at the Sonnet rows: 52 uncached input tokens, but 7,700 tokens went through the cache. A converter that only reads "input tokens" reports 52 and misses most of that day's input cost. The 1-hour cache write gets its own &lt;code&gt;.../cache-write-1h&lt;/code&gt; row when it appears; this month's file didn't have any.&lt;/p&gt;

&lt;p&gt;The total of the rows has to match the provider's own figure. If the computed price doesn't round to the cost in the export, the converter trusts the provider's number and records that it did so.&lt;/p&gt;

&lt;p&gt;For the whole month: 41 rows, $1.06 in FOCUS BilledCost against $1.06 on Anthropic's own cost export.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;For Anthropic, pass both the Cost and the Usage exports from the Console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx ai-bill-to-focus convert cost.csv usage.csv &lt;span class="nt"&gt;-o&lt;/span&gt; focus.csv
npx ai-bill-to-focus check focus.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in the browser, where the file never leaves your machine: &lt;a href="https://www.cognocient.com/tools/focus-checker" rel="noopener noreferrer"&gt;https://www.cognocient.com/tools/focus-checker&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What isn't tested yet
&lt;/h3&gt;

&lt;p&gt;Anthropic is tested on real Console exports. OpenAI and Together AI are built from their published formats, and I haven't had a real file. If you have one, &lt;code&gt;npx ai-bill-to-focus report &amp;lt;your files&amp;gt;&lt;/code&gt; prints a summary with no dollars or account names that you can paste into an issue.&lt;/p&gt;

&lt;p&gt;Repo (MIT): &lt;a href="https://github.com/mandarvshinde/ai-bill-to-focus" rel="noopener noreferrer"&gt;https://github.com/mandarvshinde/ai-bill-to-focus&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I build Cognocient AI, which tracks AI spend per feature, team and customer. This tool is standalone and needs no account.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>finops</category>
      <category>ai</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I built an async wrapper for OpenAI/Anthropic SDKs because I didn't want a proxy in my request path</title>
      <dc:creator>Mandar S</dc:creator>
      <pubDate>Sat, 08 Aug 2026 12:46:54 +0000</pubDate>
      <link>https://dev.to/mavericksh/i-built-an-async-wrapper-for-openaianthropic-sdks-because-i-didnt-want-a-proxy-in-my-request-path-1h1p</link>
      <guid>https://dev.to/mavericksh/i-built-an-async-wrapper-for-openaianthropic-sdks-because-i-didnt-want-a-proxy-in-my-request-path-1h1p</guid>
      <description>&lt;p&gt;I kept running into the same tradeoff building cost tooling for teams shipping LLM features. Every attribution tool in this space works the same way: you point &lt;code&gt;base_url&lt;/code&gt; at a proxy, and it sees every call before it happens. That's genuinely useful if you want to block or downgrade a call before it fires. It also means the proxy's uptime is now your uptime, and you've added a network hop to every single request.&lt;/p&gt;

&lt;p&gt;I wanted the attribution without touching the request path at all. So I wrote a wrapper instead.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Cognocient&lt;/code&gt; wraps the OpenAI and Anthropic Python clients directly. You still call &lt;code&gt;client.chat.completions.create()&lt;/code&gt; exactly the way you always did. The wrapper times the call, then fires a cost report on a background thread after your real response has already returned to your code.&lt;/p&gt;

&lt;p&gt;The part I actually spent the most time on wasn't the happy path, it was making sure a dead reporting endpoint can never touch your application. If Cognocient's ingestion API is slow, down, or just does not exist, that failure has to stay invisible to whatever you're building. No exception bubbling up, no retry pile-up blocking your real call. There is a test, &lt;code&gt;test_reporter_failure_isolation.py&lt;/code&gt;, that specifically points the reporter at an unreachable host and asserts the actual API call still returns clean. Writing that test is what convinced me the design was sound, not the other way around.&lt;/p&gt;

&lt;p&gt;What you get: per-call cost, and tags for feature/team/user if you want chargeback-style reporting later.&lt;/p&gt;

&lt;p&gt;What you do not get, on purpose: pre-call blocking. If a call is about to blow your budget, this wrapper finds out after it already happened, same as any billing dashboard does. If you need to stop a call before it fires, you want a proxy, and honestly LiteLLM or Portkey do that well. This is for people who've already decided visibility without a critical-path dependency is the right tradeoff for their setup.&lt;/p&gt;

&lt;p&gt;Also worth knowing before you reach for it: streaming responses (&lt;code&gt;stream=True&lt;/code&gt;) aren't reported yet. If most of your traffic streams, this won't give you complete numbers right now. Non-streaming is solid, I would call it production-safe there. Streaming is next.&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;cognocient&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CognocientOpenAI&lt;/span&gt; &lt;span class="k"&gt;as&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;sk-...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cognocient_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;sk-cog-...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# everything else about the client works exactly like before
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT licensed, signed provenance on the PyPI release, genuinely early (v0.1.x). If you're already routing through a gateway and it is working for you, this probably isn't for you. If you have been putting off cost visibility specifically because you didn't want another hop in the path, I would like to hear if this is useful or if I have missed something obvious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/mandarvshinde/cognocient-python-wrapper" rel="noopener noreferrer"&gt;https://github.com/mandarvshinde/cognocient-python-wrapper&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;PyPI&lt;/strong&gt;: &lt;code&gt;pip install cognocient&lt;/code&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>python</category>
      <category>ai</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
