<?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: ADARSH PRASHAR</title>
    <description>The latest articles on DEV Community by ADARSH PRASHAR (@prashar32).</description>
    <link>https://dev.to/prashar32</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%2F3971653%2Fe56245e3-6baa-4e60-8815-94a62ec4e9b8.jpg</url>
      <title>DEV Community: ADARSH PRASHAR</title>
      <link>https://dev.to/prashar32</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prashar32"/>
    <language>en</language>
    <item>
      <title>I kill -9'd a running AI agent mid-task. It resumed without re-spending a cent.</title>
      <dc:creator>ADARSH PRASHAR</dc:creator>
      <pubDate>Wed, 10 Jun 2026 16:23:45 +0000</pubDate>
      <link>https://dev.to/prashar32/i-kill-9d-a-running-ai-agent-mid-task-it-resumed-without-re-spending-a-cent-423e</link>
      <guid>https://dev.to/prashar32/i-kill-9d-a-running-ai-agent-mid-task-it-resumed-without-re-spending-a-cent-423e</guid>
      <description>&lt;p&gt;The premise is simple: a long-running AI agent crashes mid-task. What should happen next?&lt;/p&gt;

&lt;p&gt;The common answer is: your orchestrator checkpoints the &lt;em&gt;agent's context&lt;/em&gt;, so it can resume from the last step. LangGraph does this with MemorySaver/SQLite. Temporal replays the event log. These work. For the agent's state.&lt;/p&gt;

&lt;p&gt;But there's a second thing nobody's checkpointing: the &lt;em&gt;budget envelope&lt;/em&gt; around the agent.&lt;/p&gt;

&lt;p&gt;What did this run spend before it crashed? How many loops did it complete? How much wall-clock time has elapsed? If those limits live only in memory and the process dies, your safety layer vanishes with it, and a "resumed" agent is really a new agent with a fresh, reset budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode
&lt;/h2&gt;

&lt;p&gt;Here's what that looks like in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent is mid-run: loop 47 of a research task, $2.50 of a $5 budget spent.&lt;/li&gt;
&lt;li&gt;The runtime crashes -- OOM kill, deployment restart, a developer &lt;code&gt;kill -9&lt;/code&gt;s the process to redeploy a fix.&lt;/li&gt;
&lt;li&gt;Your agent orchestrator resumes from its checkpoint. Good.&lt;/li&gt;
&lt;li&gt;Your enforcement layer? No crash persistence. It restarts fresh, budget at $5. The run is now allowed to spend another $5, not $2.50.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You've just doubled your effective ceiling. A $5 limit became $7.50 in practice, and you won't know it until the bill arrives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What crash-resumable enforcement looks like
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;riskkernel&lt;/code&gt; stores the complete run state in a SQLite database, not in memory: budget allocated, budget spent (from the cost ledger), loop counter, wall-clock start time, halt reason. When the runtime process dies and restarts, the state is still there. A call to &lt;code&gt;Runtime.resume_run()&lt;/code&gt; picks up the same run ID -- the same budget remaining, the same loop counter, the same ceiling.&lt;/p&gt;

&lt;p&gt;The demo (&lt;code&gt;examples/kill-9-resume/demo.sh&lt;/code&gt;) is deliberately hostile:&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;# 1. Start the runtime and kick off an agent run&lt;/span&gt;
riskkernel start &amp;amp;
python3 examples/quickstart.py &amp;amp;   &lt;span class="c"&gt;# agent starts consuming budget&lt;/span&gt;

&lt;span class="c"&gt;# 2. Mid-run: kill -9 the runtime process (not the agent -- the proxy)&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;4
&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;pgrep riskkernel&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# 3. Restart and resume the same run&lt;/span&gt;
riskkernel start &amp;amp;
python3 - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
from riskkernel import Runtime
rt = Runtime()
rt.resume_run("run_abc123")     # same run ID
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it completes: the total spend equals what a clean, uninterrupted run would have spent. The loop counter doesn't double -- loops completed before the crash are still logged. The budget remaining at the time of the crash is the budget remaining on resume. If the run was going to halt at call 20 under a $0.25 ceiling, it still halts at call 20 -- not call 20+N because the counter reset.&lt;/p&gt;

&lt;p&gt;That last point is the one worth stating clearly: the budget is a property of the &lt;em&gt;run&lt;/em&gt;, not the &lt;em&gt;process&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's complementary, what's different
&lt;/h2&gt;

&lt;p&gt;Temporal checkpoints &lt;em&gt;your workflow's state&lt;/em&gt; -- which steps executed, what data they returned, what the replay log looks like. LangGraph checkpoints &lt;em&gt;your agent's context&lt;/em&gt; -- conversation history, tool outputs, scratchpad. Both are right and necessary.&lt;/p&gt;

&lt;p&gt;RiskKernel checkpoints the &lt;em&gt;enforcement envelope&lt;/em&gt;: the hard limits that keep the run bounded and resumable. These are orthogonal layers and they compose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your agent resumes from its own checkpoint at step 47 of 100.&lt;/li&gt;
&lt;li&gt;RiskKernel resumes from the same run ID, with $2.50 remaining and 47 loops logged.&lt;/li&gt;
&lt;li&gt;Together: durability of intent &lt;em&gt;and&lt;/em&gt; durability of constraint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing to be explicit about: RiskKernel doesn't checkpoint your agent's LLM context. It doesn't know what your agent was thinking at loop 47. That's your orchestrator's job. What it does know -- durably -- is that this run ID has spent $2.50, completed 47 loops, and the ceiling is $5. The API proxy enforces that on every subsequent call, regardless of what the agent's internal state looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more than the setup cost
&lt;/h2&gt;

&lt;p&gt;A one-shot agent that stays under budget on a clean run is easy. The hard problem is a long-running agent: a code-review pipeline, a research sweep, an overnight batch job. These are exactly the agents that crash, get OOM-killed, or get redeployed while they're mid-run.&lt;/p&gt;

&lt;p&gt;Without crash-resumable enforcement, your safety layer is episodic: it runs until the process dies, and then it's gone. With it, the budget is durable -- a crashed run is a paused run, not a reset one.&lt;/p&gt;

&lt;p&gt;The runtime is &lt;a href="https://github.com/prashar32/riskkernel" rel="noopener noreferrer"&gt;RiskKernel&lt;/a&gt;: open-source (Apache-2.0), self-hosted, &lt;code&gt;pip install riskkernel&lt;/code&gt;. The full demo is in &lt;code&gt;examples/kill-9-resume/&lt;/code&gt; -- the kill -9 step is in the script, not just described. Run it, then run it again with a different budget and confirm the ceiling held. If it doesn't hold, open an issue; that's the only way to know it works is if someone tried to break it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Benchmarking a kill switch for runaway AI agents -- and why the real number is a ceiling, not a %</title>
      <dc:creator>ADARSH PRASHAR</dc:creator>
      <pubDate>Mon, 08 Jun 2026 20:39:12 +0000</pubDate>
      <link>https://dev.to/prashar32/benchmarking-a-kill-switch-for-runaway-ai-agents-and-why-the-real-number-is-a-ceiling-not-a--4832</link>
      <guid>https://dev.to/prashar32/benchmarking-a-kill-switch-for-runaway-ai-agents-and-why-the-real-number-is-a-ceiling-not-a--4832</guid>
      <description>&lt;p&gt;Claims about AI cost control are cheap. "Cut your agent spend by 60%!" is on every landing page. So instead of a claim, here's a benchmark you can run yourself in one command -- and an honest reading of what its number actually means, because the headline percentage is the &lt;em&gt;least&lt;/em&gt; interesting part.&lt;/p&gt;

&lt;p&gt;The short version: I ran the same looping agent twice -- once unguarded, once behind a hard dollar budget -- against a deterministic provider, and measured the spend. Then I'll show you why the "% saved" framing undersells it, and why a flat ceiling is the number that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I &lt;a href="https://dev.to/prashar32/the-47k-agent-loop-why-logging-monitoring-and-maxtokens-all-failed-to-stop-it-19ch"&gt;wrote about&lt;/a&gt; why a runaway agent slips past logging, monitoring, and &lt;code&gt;max_tokens&lt;/code&gt;: it's not one anomalous call, it's a thousand individually-valid ones, and the only thing that stops it is a deterministic, &lt;em&gt;pre-call&lt;/em&gt;, &lt;em&gt;per-run&lt;/em&gt; limit. This benchmark measures exactly that limit doing its job.&lt;/p&gt;

&lt;p&gt;The harness (&lt;a href="https://github.com/prashar32/riskkernel/tree/main/benchmark" rel="noopener noreferrer"&gt;&lt;code&gt;benchmark/&lt;/code&gt;&lt;/a&gt; in the repo) is built so the &lt;strong&gt;only&lt;/strong&gt; variable between the two runs is whether the budget fired:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic provider.&lt;/strong&gt; A mock of the Chat Completions API returns a fixed token usage (1000 in / 1000 out) on every call. No network variance, no real money, exactly reproducible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real prices, pinned.&lt;/strong&gt; &lt;code&gt;gpt-4o&lt;/code&gt; at its list price ($2.50 / $10.00 per 1M input/output tokens). That makes one call cost &lt;code&gt;1000·2.50/1e6 + 1000·10.00/1e6 = $0.0125&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measured, not modeled.&lt;/strong&gt; The governed run's spend is read straight from the runtime's own cost ledger (&lt;code&gt;GET /v1/runs/{id}&lt;/code&gt; -&amp;gt; &lt;code&gt;usage.dollars&lt;/code&gt;), not computed by the benchmark. The runtime meters each call and halts the run &lt;em&gt;before&lt;/em&gt; the call that would cross the ceiling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same per-call price on both sides&lt;/strong&gt;, so the two numbers are directly comparable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A 50-iteration runaway, with a $0.25 ceiling on the governed run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  RiskKernel cost benchmark -- runaway loop
  ------------------------------------------------------
  loop length (N)            50
  dollar budget              $0.25
  per-call cost              $0.0125   (gpt-4o, from the ledger)
  ------------------------------------------------------
                            calls        spend
  baseline (no governance)     50      $0.6250
  governed (RiskKernel)        20      $0.2500
  ------------------------------------------------------
  dollars saved              $0.3750   (60%)
  stopped by                 dollar_budget_exceeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;20 calls × $0.0125 = exactly $0.25. The 21st call was refused before it left the process. The baseline ran all 50.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "60%" is the wrong number
&lt;/h2&gt;

&lt;p&gt;Sixty percent looks like the headline. It isn't -- it's an artifact of where I set N. I chose a 50-call loop; the budget caught it at 20. Make the loop longer and the percentage climbs, because the governed spend &lt;strong&gt;doesn't move&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If the runaway loops…&lt;/th&gt;
&lt;th&gt;Baseline spend&lt;/th&gt;
&lt;th&gt;Governed spend&lt;/th&gt;
&lt;th&gt;Saved&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;50×&lt;/td&gt;
&lt;td&gt;$0.63&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.25&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0.38 (60%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000×&lt;/td&gt;
&lt;td&gt;$12.50&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.25&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$12.25 (98%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000×&lt;/td&gt;
&lt;td&gt;$125.00&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.25&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$124.75 (99.8%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The governed column is flat. That's the whole point. A runaway loop has no natural stopping condition -- that's what makes it a runaway -- so the baseline grows until a human notices, which in the &lt;a href="https://dev.to/prashar32/the-47k-agent-loop-why-logging-monitoring-and-maxtokens-all-failed-to-stop-it-19ch"&gt;canonical $47K incident&lt;/a&gt; took eleven days. The thing you're buying isn't a percentage discount. It's a number that &lt;strong&gt;cannot exceed what you set&lt;/strong&gt;, no matter how badly the agent misbehaves or how long before anyone looks.&lt;/p&gt;

&lt;p&gt;So I distrust "X% cheaper" claims in this space, including ones I could make. The percentage depends entirely on the failure you benchmark against. The honest guarantee is the ceiling: &lt;em&gt;spend is bounded by the budget, full stop.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this benchmark is honest (and where it isn't the whole story)
&lt;/h2&gt;

&lt;p&gt;I'd rather you trust the harness than the author, so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's one command, key-free, no real spend:&lt;/strong&gt; &lt;code&gt;python3 benchmark/benchmark.py&lt;/code&gt;. The mock and the pricing file are right there -- inspect them, change them, break them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It deliberately removes provider latency and variance&lt;/strong&gt; to isolate the governance effect. This is a benchmark about &lt;em&gt;dollars&lt;/em&gt;, not milliseconds. The enforcement overhead the runtime itself adds is small and belongs in a separate latency benchmark -- I won't smuggle it into this one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It measures one dimension: the cost ceiling.&lt;/strong&gt; The other half of "safe to leave running" is crash-recovery -- &lt;code&gt;kill -9&lt;/code&gt; a long run and resume it without re-spending -- which is demonstrated end-to-end in &lt;a href="https://github.com/prashar32/riskkernel/tree/main/examples/kill-9-resume" rel="noopener noreferrer"&gt;&lt;code&gt;examples/kill-9-resume&lt;/code&gt;&lt;/a&gt;, not in this harness. A &lt;em&gt;timed&lt;/em&gt; recovery benchmark is next.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;If you're evaluating anything that claims to control agent cost, ask it for two things: the &lt;strong&gt;harness&lt;/strong&gt; (so you can reproduce the number) and the &lt;strong&gt;ceiling&lt;/strong&gt; (so you know the worst case, not the average case). A percentage without a reproducible loop length is marketing. A flat, enforced ceiling -- refused pre-call, in compiled code, read back from a ledger -- is an SLA you can reason about.&lt;/p&gt;

&lt;p&gt;The runtime is &lt;a href="https://github.com/prashar32/riskkernel" rel="noopener noreferrer"&gt;RiskKernel&lt;/a&gt;: open-source (Apache-2.0), self-hosted, &lt;code&gt;pip install riskkernel&lt;/code&gt; or &lt;code&gt;docker run&lt;/code&gt;, one env var in front of an agent you already have. Run the benchmark, then tell me where you'd push on it -- a benchmark only earns trust if people try to break it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The $47K agent loop: why logging, monitoring, and max_tokens all failed to stop it</title>
      <dc:creator>ADARSH PRASHAR</dc:creator>
      <pubDate>Sun, 07 Jun 2026 15:28:36 +0000</pubDate>
      <link>https://dev.to/prashar32/the-47k-agent-loop-why-logging-monitoring-and-maxtokens-all-failed-to-stop-it-19ch</link>
      <guid>https://dev.to/prashar32/the-47k-agent-loop-why-logging-monitoring-and-maxtokens-all-failed-to-stop-it-19ch</guid>
      <description>&lt;p&gt;In November 2025, four AI agents ran for eleven days and produced a $47,000 bill.&lt;/p&gt;

&lt;p&gt;You've probably seen the story. A market-research pipeline: four LangChain agents coordinating over A2A. Two of them, an Analyzer and a Verifier, started ping-ponging. The Analyzer produced analysis, the Verifier asked for more, the Analyzer produced more. No termination condition, no budget cap. Eleven days later the invoice showed up.&lt;/p&gt;

&lt;p&gt;The number is what makes it travel. But the number is not the interesting part. This is the interesting part, from the post-mortem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;They had logging. They had monitoring. They did not have a hard limit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sit with that. The team was not flying blind. The data was all there: every call, every token, every dollar, streaming into a dashboard the whole time. None of it mattered, because &lt;strong&gt;observability is a witness, not a circuit breaker.&lt;/strong&gt; It can tell you the building is on fire. It cannot close the gas valve.&lt;/p&gt;

&lt;p&gt;I want to walk through &lt;em&gt;why&lt;/em&gt; the usual defenses don't catch this, and what the thing that actually catches it has to look like. Not the product pitch, the mechanism. If you run agents in production, this is the failure mode that should keep you up at night, and it's more structural than it looks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode: a thousand perfectly valid calls
&lt;/h2&gt;

&lt;p&gt;A runaway agent is not one big anomalous request. It's a thousand small, individually reasonable ones.&lt;/p&gt;

&lt;p&gt;Every single call the Analyzer and Verifier made was well-formed. Each was under its &lt;code&gt;max_tokens&lt;/code&gt;. Each returned a 200. Each looked, in isolation, exactly like a healthy agent doing its job. The pathology only exists at the level of the &lt;em&gt;run&lt;/em&gt; (the loop that never closes), and almost nothing in a normal stack is watching at that level.&lt;/p&gt;

&lt;p&gt;That's why the obvious guards slide right off it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;max_tokens&lt;/code&gt; is per-call, not per-run.&lt;/strong&gt; It bounds the size of one response. It has nothing to say about ten thousand responses. A loop is the size of a tweet, ten thousand times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost dashboards are post-hoc.&lt;/strong&gt; They render spend after the calls have already happened and the money is already gone. By design they trail reality. The fire has to start before the smoke detector has anything to detect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerts need a human in the loop, awake, watching.&lt;/strong&gt; "Spend exceeded $X" fires into a Slack channel at 3am on a Saturday. Nobody saw it for eleven days because seeing it was a person's job, and people sleep, and go on vacation, and assume the thing that's been fine is still fine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these is useful. None of them is a stop. They are all instruments on the dashboard; not one of them is the brake pedal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a stop actually requires
&lt;/h2&gt;

&lt;p&gt;If you want to &lt;em&gt;stop&lt;/em&gt; a runaway run, not narrate it, the enforcement has to satisfy three properties. Miss any one and you're back to writing post-mortems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It has to be deterministic.&lt;/strong&gt; No model in the decision path. The whole problem is an unbounded non-deterministic system; you do not get to bound it with another non-deterministic system and call it safe. "We added an LLM that decides when to stop the LLM" is not a control, it's a second thing that can fail. The limit is &lt;code&gt;total_cost &amp;gt; ceiling&lt;/code&gt; evaluated in compiled code, or it is not a limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. It has to be pre-call.&lt;/strong&gt; The check runs &lt;em&gt;before&lt;/em&gt; the next request leaves your process, and refuses it. Anything that runs after the call has, by definition, already let the call happen and the dollars leave. Post-hoc enforcement is a contradiction: the enforcement and the spend race, and the spend wins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It has to be per-run, not per-call.&lt;/strong&gt; The unit that goes wrong is the run: total dollars, total loop iterations, total wall-clock, accumulated across every call the run makes, plus a kill switch you can pull from outside. That's the altitude the pathology lives at, so that's the altitude the budget has to live at.&lt;/p&gt;

&lt;p&gt;Deterministic, pre-call, per-run. That's the shape of a brake pedal. I'll say the obvious thing: this is not novel computer science. It's a hard-coded resource governor, the kind of thing operating systems and databases and trading systems have had for decades. The novelty is purely that the agent world skipped it.&lt;/p&gt;

&lt;h2&gt;
  
  
  I've built this before, in a less forgiving domain
&lt;/h2&gt;

&lt;p&gt;I've spent years building deterministic risk engines that wrap non-deterministic systems, the kind where a mistake costs real money, in real time, with no undo. And the lesson was always the same: the thing that kept those systems safe was never the smart part. It was a dumb, hard-coded, deterministic layer wrapped around the smart part, with the authority to say no.&lt;/p&gt;

&lt;p&gt;The smart part proposes. The deterministic layer disposes. Every irreversible action is gated. You do not let the clever, probabilistic component hold the kill switch, because the whole reason you need a kill switch is that the clever component is the thing that goes wrong.&lt;/p&gt;

&lt;p&gt;Agents are exactly this pattern wearing new clothes. The LLM is the strategy. The risk engine belongs in compiled, statically-typed code that the LLM cannot talk its way past.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like in practice
&lt;/h2&gt;

&lt;p&gt;That conviction is why I've been building &lt;a href="https://github.com/prashar32/riskkernel" rel="noopener noreferrer"&gt;RiskKernel&lt;/a&gt;, an open-source, self-hosted runtime that puts that deterministic layer in front of an agent you already have. I'll keep this concrete rather than salesy, because the &lt;em&gt;shape&lt;/em&gt; is the point and you could build a version of it yourself.&lt;/p&gt;

&lt;p&gt;You point an existing agent at it with one environment variable:&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="nv"&gt;OPENAI_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:7070/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every call routes through a governor. You set a per-run budget (dollars, loop count, wall-clock seconds), and the moment the run crosses a ceiling, the &lt;em&gt;next&lt;/em&gt; call is refused with an HTTP 402 instead of being forwarded. Enforced in Go, never by a model. Bring your own provider key; nothing leaves your machine except the call you were already making.&lt;/p&gt;

&lt;p&gt;One detail I think is worth stealing regardless of what you use: &lt;strong&gt;a call that already reached the provider is never silently discarded.&lt;/strong&gt; You paid for it, so it's returned to you, and it's the &lt;em&gt;following&lt;/em&gt; call that gets refused. The ledger stays honest; the budget never double-counts the request that tipped it over. The brake engages on the next rotation of the loop, not by throwing away work you already paid for.&lt;/p&gt;

&lt;p&gt;And because the failure mode I actually lose sleep over is a long, legitimate run dying halfway through, it checkpoints: you can &lt;code&gt;kill -9&lt;/code&gt; a run and resume it without re-spending or restarting from zero. That's the part that makes a long agent run &lt;em&gt;safe to leave running&lt;/em&gt;, which is the whole game.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part
&lt;/h2&gt;

&lt;p&gt;The honest edges, today: single instance on SQLite, one API token, no streaming yet (the proxy returns a clean 501 for &lt;code&gt;stream: true&lt;/code&gt;; mid-stream enforcement is genuinely hard and I'd rather ship it right than ship it loud). Native providers are Anthropic and OpenAI, with the long tail via an upstream gateway. It's Apache-2.0, and it phones home to no one. The only outbound traffic is to your provider and the backends you point it at. I'd rather you know the edges than discover them.&lt;/p&gt;

&lt;p&gt;It is also not trying to be your observability stack or your policy firewall. It emits OpenTelemetry to whatever you already run; it interoperates with the gateways and the dashboards. It competes on exactly one thing: deterministically stopping a run before it hurts you.&lt;/p&gt;

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

&lt;p&gt;If you run agents, the question to ask isn't &lt;em&gt;"will I find out when one goes runaway?"&lt;/em&gt; You will, eventually: in the logs, in the bill, in the post-mortem. The question is &lt;em&gt;"what stops it before I find out?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Logging is not that thing. Monitoring is not that thing. &lt;code&gt;max_tokens&lt;/code&gt; is not that thing. A deterministic, pre-call, per-run limit with a kill switch is. And it's a few hours of work to put one in front of an agent you already have, whether you use what I built or roll your own.&lt;/p&gt;

&lt;p&gt;Eleven days. Forty-seven thousand dollars. A dashboard that saw all of it. Don't be the dashboard.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/prashar32/riskkernel" rel="noopener noreferrer"&gt;RiskKernel&lt;/a&gt; is open-source (Apache-2.0) and self-hosted (&lt;code&gt;pip install riskkernel&lt;/code&gt; or &lt;code&gt;docker run&lt;/code&gt;). If you put it in front of an agent and the guardrails are too strict or too loose, I'd genuinely like to hear where. That feedback is what the next release is made of.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
